Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
Openfire
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Openfire
Commits
4818ae96
Commit
4818ae96
authored
Jun 01, 2017
by
Dave Cridland
Committed by
GitHub
Jun 01, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #812 from guusdk/OF-1336_UserPropertyProvider
OF-1336: Introduce UserPropertyProvider
parents
9df410ae
47798ec7
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1134 additions
and
186 deletions
+1134
-186
User.java
src/java/org/jivesoftware/openfire/user/User.java
+70
-173
UserManager.java
src/java/org/jivesoftware/openfire/user/UserManager.java
+46
-2
DefaultUserPropertyProvider.java
...e/openfire/user/property/DefaultUserPropertyProvider.java
+191
-0
HybridUserPropertyProvider.java
...re/openfire/user/property/HybridUserPropertyProvider.java
+280
-0
JDBCUserPropertyProvider.java
...ware/openfire/user/property/JDBCUserPropertyProvider.java
+200
-0
MappedUserPropertyProvider.java
...re/openfire/user/property/MappedUserPropertyProvider.java
+169
-0
UserPropertyProvider.java
...software/openfire/user/property/UserPropertyProvider.java
+102
-0
UserPropertyProviderMapper.java
...re/openfire/user/property/UserPropertyProviderMapper.java
+55
-0
changelog.html
src/plugins/justmarried/changelog.html
+6
-0
plugin.xml
src/plugins/justmarried/plugin.xml
+2
-2
pom.xml
src/plugins/justmarried/pom.xml
+1
-1
JustMarriedPlugin.java
...vesoftware/openfire/plugin/married/JustMarriedPlugin.java
+1
-3
changelog.html
src/plugins/restAPI/changelog.html
+6
-0
plugin.xml
src/plugins/restAPI/plugin.xml
+2
-2
pom.xml
src/plugins/restAPI/pom.xml
+2
-0
JustMarriedController.java
...penfire/plugin/rest/controller/JustMarriedController.java
+1
-3
No files found.
src/java/org/jivesoftware/openfire/user/User.java
View file @
4818ae96
...
...
@@ -16,24 +16,6 @@
package
org
.
jivesoftware
.
openfire
.
user
;
import
java.io.Externalizable
;
import
java.io.IOException
;
import
java.io.ObjectInput
;
import
java.io.ObjectOutput
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.util.AbstractMap
;
import
java.util.AbstractSet
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.ConcurrentHashMap
;
import
org.jivesoftware.database.DbConnectionManager
;
import
org.jivesoftware.openfire.XMPPServer
;
import
org.jivesoftware.openfire.auth.AuthFactory
;
import
org.jivesoftware.openfire.auth.ConnectionException
;
...
...
@@ -49,30 +31,28 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
org.xmpp.resultsetmanagement.Result
;
import
java.io.Externalizable
;
import
java.io.IOException
;
import
java.io.ObjectInput
;
import
java.io.ObjectOutput
;
import
java.util.*
;
/**
* Encapsulates information about a user. New users are created using
* {@link UserManager#createUser(String, String, String, String)}. All user
* properties are loaded on demand and are read from the <tt>ofUserProp</tt>
* database table. The currently-installed {@link UserProvider} is used for
* setting all other user data and some operations may not be supported
* depending on the capabilities of the {@link UserProvider}.
* Encapsulates information about a user.
*
* New users are created using {@link UserManager#createUser(String, String, String, String)}.
*
* The currently-installed {@link UserProvider} is used for setting all other user data and some operations may not be
* supported depending on the capabilities of the {@link UserProvider}.
*
* All user properties are loaded on demand from the currently-installed
* {@link org.jivesoftware.openfire.user.property.UserPropertyProvider}.
*
* @author Matt Tucker
*/
public
class
User
implements
Cacheable
,
Externalizable
,
Result
{
private
static
final
Logger
Log
=
LoggerFactory
.
getLogger
(
User
.
class
);
private
static
final
String
LOAD_PROPERTIES
=
"SELECT name, propValue FROM ofUserProp WHERE username=?"
;
private
static
final
String
LOAD_PROPERTY
=
"SELECT propValue FROM ofUserProp WHERE username=? AND name=?"
;
private
static
final
String
DELETE_PROPERTY
=
"DELETE FROM ofUserProp WHERE username=? AND name=?"
;
private
static
final
String
UPDATE_PROPERTY
=
"UPDATE ofUserProp SET propValue=? WHERE name=? AND username=?"
;
private
static
final
String
INSERT_PROPERTY
=
"INSERT INTO ofUserProp (username, name, propValue) VALUES (?, ?, ?)"
;
private
static
final
Logger
Log
=
LoggerFactory
.
getLogger
(
User
.
class
);
// The name of the name visible property
private
static
final
String
NAME_VISIBLE_PROPERTY
=
"name.visible"
;
...
...
@@ -98,29 +78,10 @@ public class User implements Cacheable, Externalizable, Result {
* @param username the username of the user to get a specific property value.
* @param propertyName the name of the property to return its value.
* @return the value of the specified property for the given username.
* @throws UserNotFoundException Depending on the installed user provider (some will return null instead).
*/
public
static
String
getPropertyValue
(
String
username
,
String
propertyName
)
{
String
propertyValue
=
null
;
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
ResultSet
rs
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
LOAD_PROPERTY
);
pstmt
.
setString
(
1
,
username
);
pstmt
.
setString
(
2
,
propertyName
);
rs
=
pstmt
.
executeQuery
();
while
(
rs
.
next
())
{
propertyValue
=
rs
.
getString
(
1
);
}
}
catch
(
SQLException
sqle
)
{
Log
.
error
(
sqle
.
getMessage
(),
sqle
);
}
finally
{
DbConnectionManager
.
closeConnection
(
rs
,
pstmt
,
con
);
}
return
propertyValue
;
public
static
String
getPropertyValue
(
String
username
,
String
propertyName
)
throws
UserNotFoundException
{
return
UserManager
.
getUserPropertyProvider
().
loadProperty
(
username
,
propertyName
);
}
/**
...
...
@@ -195,35 +156,35 @@ public class User implements Cacheable, Externalizable, Result {
Log
.
error
(
e
.
getMessage
(),
e
);
}
}
public
String
getStoredKey
()
{
return
storedKey
;
}
public
void
setStoredKey
(
String
storedKey
)
{
this
.
storedKey
=
storedKey
;
}
public
String
getServerKey
()
{
return
serverKey
;
}
public
void
setServerKey
(
String
serverKey
)
{
this
.
serverKey
=
serverKey
;
}
public
String
getSalt
()
{
return
salt
;
}
public
void
setSalt
(
String
salt
)
{
this
.
salt
=
salt
;
}
public
int
getIterations
()
{
return
iterations
;
}
public
void
setIterations
(
int
iterations
)
{
this
.
iterations
=
iterations
;
}
...
...
@@ -398,8 +359,11 @@ public class User implements Cacheable, Externalizable, Result {
public
Map
<
String
,
String
>
getProperties
()
{
synchronized
(
this
)
{
if
(
properties
==
null
)
{
properties
=
new
ConcurrentHashMap
<>();
loadProperties
();
try
{
properties
=
UserManager
.
getUserPropertyProvider
().
loadProperties
(
username
);
}
catch
(
UserNotFoundException
e
)
{
Log
.
error
(
"Unable to retrieve properties for user "
+
username
,
e
);
}
}
}
// Return a wrapper that will intercept add and remove commands.
...
...
@@ -472,28 +436,34 @@ public class User implements Cacheable, Externalizable, Result {
String
answer
;
String
keyString
=
key
;
synchronized
(
getName
()
+
keyString
.
intern
())
{
if
(
properties
.
containsKey
(
keyString
))
{
String
originalValue
=
properties
.
get
(
keyString
);
answer
=
properties
.
put
(
keyString
,
value
);
updateProperty
(
keyString
,
value
);
// Configure event.
eventParams
.
put
(
"type"
,
"propertyModified"
);
eventParams
.
put
(
"propertyKey"
,
key
);
eventParams
.
put
(
"originalValue"
,
originalValue
);
}
else
{
answer
=
properties
.
put
(
keyString
,
value
);
insertProperty
(
keyString
,
value
);
// Configure event.
eventParams
.
put
(
"type"
,
"propertyAdded"
);
eventParams
.
put
(
"propertyKey"
,
key
);
try
{
synchronized
((
getName
()
+
keyString
).
intern
())
{
if
(
properties
.
containsKey
(
keyString
))
{
String
originalValue
=
properties
.
get
(
keyString
);
answer
=
properties
.
put
(
keyString
,
value
);
UserManager
.
getUserPropertyProvider
().
updateProperty
(
username
,
keyString
,
value
);
// Configure event.
eventParams
.
put
(
"type"
,
"propertyModified"
);
eventParams
.
put
(
"propertyKey"
,
key
);
eventParams
.
put
(
"originalValue"
,
originalValue
);
}
else
{
answer
=
properties
.
put
(
keyString
,
value
);
UserManager
.
getUserPropertyProvider
().
insertProperty
(
username
,
keyString
,
value
);
// Configure event.
eventParams
.
put
(
"type"
,
"propertyAdded"
);
eventParams
.
put
(
"propertyKey"
,
key
);
}
}
// Fire event.
UserEventDispatcher
.
dispatchEvent
(
User
.
this
,
UserEventDispatcher
.
EventType
.
user_modified
,
eventParams
);
return
answer
;
}
catch
(
UserNotFoundException
e
)
{
Log
.
error
(
"Unable to put property for user "
+
username
,
e
);
}
// Fire event.
UserEventDispatcher
.
dispatchEvent
(
User
.
this
,
UserEventDispatcher
.
EventType
.
user_modified
,
eventParams
);
return
answer
;
return
null
;
}
@Override
...
...
@@ -536,96 +506,23 @@ public class User implements Cacheable, Externalizable, Result {
throw
new
IllegalStateException
();
}
String
key
=
current
.
getKey
();
deleteProperty
(
key
);
iter
.
remove
();
// Fire event.
Map
<
String
,
Object
>
params
=
new
HashMap
<>();
params
.
put
(
"type"
,
"propertyDeleted"
);
params
.
put
(
"propertyKey"
,
key
);
UserEventDispatcher
.
dispatchEvent
(
User
.
this
,
UserEventDispatcher
.
EventType
.
user_modified
,
params
);
try
{
UserManager
.
getUserPropertyProvider
().
deleteProperty
(
username
,
key
);
iter
.
remove
();
// Fire event.
Map
<
String
,
Object
>
params
=
new
HashMap
<>();
params
.
put
(
"type"
,
"propertyDeleted"
);
params
.
put
(
"propertyKey"
,
key
);
UserEventDispatcher
.
dispatchEvent
(
User
.
this
,
UserEventDispatcher
.
EventType
.
user_modified
,
params
);
}
catch
(
UserNotFoundException
e
)
{
Log
.
error
(
"Unable to delete property for user "
+
username
,
e
);
}
}
};
}
}
private
void
loadProperties
()
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
ResultSet
rs
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
LOAD_PROPERTIES
);
pstmt
.
setString
(
1
,
username
);
rs
=
pstmt
.
executeQuery
();
while
(
rs
.
next
())
{
properties
.
put
(
rs
.
getString
(
1
),
rs
.
getString
(
2
));
}
}
catch
(
SQLException
sqle
)
{
Log
.
error
(
sqle
.
getMessage
(),
sqle
);
}
finally
{
DbConnectionManager
.
closeConnection
(
rs
,
pstmt
,
con
);
}
}
private
void
insertProperty
(
String
propName
,
String
propValue
)
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
INSERT_PROPERTY
);
pstmt
.
setString
(
1
,
username
);
pstmt
.
setString
(
2
,
propName
);
pstmt
.
setString
(
3
,
propValue
);
pstmt
.
executeUpdate
();
}
catch
(
SQLException
e
)
{
Log
.
error
(
e
.
getMessage
(),
e
);
}
finally
{
DbConnectionManager
.
closeConnection
(
pstmt
,
con
);
}
}
private
void
updateProperty
(
String
propName
,
String
propValue
)
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
UPDATE_PROPERTY
);
pstmt
.
setString
(
1
,
propValue
);
pstmt
.
setString
(
2
,
propName
);
pstmt
.
setString
(
3
,
username
);
pstmt
.
executeUpdate
();
}
catch
(
SQLException
e
)
{
Log
.
error
(
e
.
getMessage
(),
e
);
}
finally
{
DbConnectionManager
.
closeConnection
(
pstmt
,
con
);
}
}
private
void
deleteProperty
(
String
propName
)
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
DELETE_PROPERTY
);
pstmt
.
setString
(
1
,
username
);
pstmt
.
setString
(
2
,
propName
);
pstmt
.
executeUpdate
();
}
catch
(
SQLException
e
)
{
Log
.
error
(
e
.
getMessage
(),
e
);
}
finally
{
DbConnectionManager
.
closeConnection
(
pstmt
,
con
);
}
}
@Override
public
void
writeExternal
(
ObjectOutput
out
)
throws
IOException
{
ExternalizableUtil
.
getInstance
().
writeSafeUTF
(
out
,
username
);
...
...
src/java/org/jivesoftware/openfire/user/UserManager.java
View file @
4818ae96
...
...
@@ -29,6 +29,8 @@ import org.dom4j.Element;
import
org.jivesoftware.openfire.XMPPServer
;
import
org.jivesoftware.openfire.event.UserEventDispatcher
;
import
org.jivesoftware.openfire.event.UserEventListener
;
import
org.jivesoftware.openfire.user.property.DefaultUserPropertyProvider
;
import
org.jivesoftware.openfire.user.property.UserPropertyProvider
;
import
org.jivesoftware.util.ClassUtils
;
import
org.jivesoftware.util.JiveGlobals
;
import
org.jivesoftware.util.PropertyEventDispatcher
;
...
...
@@ -50,7 +52,7 @@ import org.xmpp.packet.JID;
*/
public
class
UserManager
implements
IQResultListener
{
private
static
final
Logger
Log
=
LoggerFactory
.
getLogger
(
UserManager
.
class
);
private
static
final
Logger
Log
=
LoggerFactory
.
getLogger
(
UserManager
.
class
);
// Wrap this guy up so we can mock out the UserManager class.
private
static
class
UserManagerContainer
{
...
...
@@ -69,6 +71,21 @@ public class UserManager implements IQResultListener {
return
UserManagerContainer
.
instance
.
provider
;
}
/**
* Returns the currently-installed UserPropertyProvider.
*
* <b>Warning:</b> in virtually all cases the user property provider should not be used directly. Instead, use the
* Map returned by {@link User#getProperties() ) to create, read, update or delete user properties. Failure to do so
* is likely to result in inconsistent data behavior and race conditions. Direct access to the user property
* provider is only provided for special-case logic.
*
* @return the current UserPropertyProvider.
* @see User#getProperties
*/
public
static
UserPropertyProvider
getUserPropertyProvider
()
{
return
UserManagerContainer
.
instance
.
propertyProvider
;
}
/**
* Returns a singleton UserManager instance.
*
...
...
@@ -83,14 +100,16 @@ public class UserManager implements IQResultListener {
/** Cache if a local or remote user exists. */
private
Cache
<
String
,
Boolean
>
remoteUsersCache
;
private
UserProvider
provider
;
private
UserPropertyProvider
propertyProvider
;
private
UserManager
()
{
// Initialize caches.
userCache
=
CacheFactory
.
createCache
(
"User"
);
remoteUsersCache
=
CacheFactory
.
createCache
(
"Remote Users Existence"
);
// Load a user provider.
// Load a user
& property
provider.
initProvider
();
initPropertyProvider
();
// Detect when a new auth provider class is set
PropertyEventListener
propListener
=
new
PropertyEventListener
()
{
...
...
@@ -99,6 +118,9 @@ public class UserManager implements IQResultListener {
if
(
"provider.user.className"
.
equals
(
property
))
{
initProvider
();
}
if
(
"provider.userproperty.className"
.
equals
(
property
))
{
initPropertyProvider
();
}
}
@Override
...
...
@@ -106,6 +128,9 @@ public class UserManager implements IQResultListener {
if
(
"provider.user.className"
.
equals
(
property
))
{
initProvider
();
}
if
(
"provider.userproperty.className"
.
equals
(
property
))
{
initPropertyProvider
();
}
}
@Override
...
...
@@ -492,4 +517,23 @@ public class UserManager implements IQResultListener {
}
}
}
private
void
initPropertyProvider
()
{
// Convert XML based provider setup to Database based
JiveGlobals
.
migrateProperty
(
"provider.userproperty.className"
);
String
className
=
JiveGlobals
.
getProperty
(
"provider.userproperty.className"
,
"org.jivesoftware.openfire.user.property.DefaultUserPropertyProvider"
);
// Check if we need to reset the provider class
if
(
propertyProvider
==
null
||
!
className
.
equals
(
propertyProvider
.
getClass
().
getName
()))
{
try
{
Class
c
=
ClassUtils
.
forName
(
className
);
propertyProvider
=
(
UserPropertyProvider
)
c
.
newInstance
();
}
catch
(
Exception
e
)
{
Log
.
error
(
"Error loading user property provider: "
+
className
,
e
);
propertyProvider
=
new
DefaultUserPropertyProvider
();
}
}
}
}
\ No newline at end of file
src/java/org/jivesoftware/openfire/user/property/DefaultUserPropertyProvider.java
0 → 100644
View file @
4818ae96
/*
* Copyright 2017 IgniteRealtime.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
jivesoftware
.
openfire
.
user
.
property
;
import
org.jivesoftware.database.DbConnectionManager
;
import
org.jivesoftware.openfire.user.User
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* Default implementation of the UserPropertyProvider interface, which reads and writes data from the
* <tt>ofUserProp</tt> database table.
*
* This implementation will not explicitly verify if a user exists, when operating on its properties. The methods of
* this implementation will <em>not</em> throw {@link org.jivesoftware.openfire.user.UserNotFoundException}.
*
* <b>Warning:</b> in virtually all cases a user property provider should not be used directly. Instead, use the
* Map returned by {@link User#getProperties() ) to create, read, update or delete user properties. Failure to do so
* is likely to result in inconsistent data behavior and race conditions. Direct access to the user property
* provider is only provided for special-case logic.
*
* @author Guus der Kinderen, guus@goodbytes.nl
* @see User#getProperties
*/
public
class
DefaultUserPropertyProvider
implements
UserPropertyProvider
{
private
static
final
Logger
Log
=
LoggerFactory
.
getLogger
(
DefaultUserPropertyProvider
.
class
);
private
static
final
String
LOAD_PROPERTIES
=
"SELECT name, propValue FROM ofUserProp WHERE username=?"
;
private
static
final
String
LOAD_PROPERTY
=
"SELECT propValue FROM ofUserProp WHERE username=? AND name=?"
;
private
static
final
String
DELETE_PROPERTY
=
"DELETE FROM ofUserProp WHERE username=? AND name=?"
;
private
static
final
String
UPDATE_PROPERTY
=
"UPDATE ofUserProp SET propValue=? WHERE name=? AND username=?"
;
private
static
final
String
INSERT_PROPERTY
=
"INSERT INTO ofUserProp (username, name, propValue) VALUES (?, ?, ?)"
;
@Override
public
Map
<
String
,
String
>
loadProperties
(
String
username
)
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
ResultSet
rs
=
null
;
final
Map
<
String
,
String
>
properties
=
new
ConcurrentHashMap
<>();
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
LOAD_PROPERTIES
);
pstmt
.
setString
(
1
,
username
);
rs
=
pstmt
.
executeQuery
();
while
(
rs
.
next
()
)
{
properties
.
put
(
rs
.
getString
(
1
),
rs
.
getString
(
2
)
);
}
}
catch
(
SQLException
sqle
)
{
Log
.
error
(
sqle
.
getMessage
(),
sqle
);
}
finally
{
DbConnectionManager
.
closeConnection
(
rs
,
pstmt
,
con
);
}
return
properties
;
}
@Override
public
String
loadProperty
(
String
username
,
String
propertyName
)
{
String
propertyValue
=
null
;
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
ResultSet
rs
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
LOAD_PROPERTY
);
pstmt
.
setString
(
1
,
username
);
pstmt
.
setString
(
2
,
propertyName
);
rs
=
pstmt
.
executeQuery
();
while
(
rs
.
next
()
)
{
propertyValue
=
rs
.
getString
(
1
);
}
}
catch
(
SQLException
sqle
)
{
Log
.
error
(
sqle
.
getMessage
(),
sqle
);
}
finally
{
DbConnectionManager
.
closeConnection
(
rs
,
pstmt
,
con
);
}
return
propertyValue
;
}
@Override
public
void
insertProperty
(
String
username
,
String
propName
,
String
propValue
)
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
INSERT_PROPERTY
);
pstmt
.
setString
(
1
,
username
);
pstmt
.
setString
(
2
,
propName
);
pstmt
.
setString
(
3
,
propValue
);
pstmt
.
executeUpdate
();
}
catch
(
SQLException
e
)
{
Log
.
error
(
e
.
getMessage
(),
e
);
}
finally
{
DbConnectionManager
.
closeConnection
(
pstmt
,
con
);
}
}
@Override
public
void
updateProperty
(
String
username
,
String
propName
,
String
propValue
)
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
UPDATE_PROPERTY
);
pstmt
.
setString
(
1
,
propValue
);
pstmt
.
setString
(
2
,
propName
);
pstmt
.
setString
(
3
,
username
);
pstmt
.
executeUpdate
();
}
catch
(
SQLException
e
)
{
Log
.
error
(
e
.
getMessage
(),
e
);
}
finally
{
DbConnectionManager
.
closeConnection
(
pstmt
,
con
);
}
}
@Override
public
void
deleteProperty
(
String
username
,
String
propName
)
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
try
{
con
=
DbConnectionManager
.
getConnection
();
pstmt
=
con
.
prepareStatement
(
DELETE_PROPERTY
);
pstmt
.
setString
(
1
,
username
);
pstmt
.
setString
(
2
,
propName
);
pstmt
.
executeUpdate
();
}
catch
(
SQLException
e
)
{
Log
.
error
(
e
.
getMessage
(),
e
);
}
finally
{
DbConnectionManager
.
closeConnection
(
pstmt
,
con
);
}
}
@Override
public
boolean
isReadOnly
()
{
return
false
;
}
}
src/java/org/jivesoftware/openfire/user/property/HybridUserPropertyProvider.java
0 → 100644
View file @
4818ae96
/*
* Copyright 2017 IgniteRealtime.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
jivesoftware
.
openfire
.
user
.
property
;
import
org.jivesoftware.openfire.user.UserNotFoundException
;
import
org.jivesoftware.util.JiveGlobals
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
/**
* Delegate UserPropertyProvider operations among up to three configurable provider implementation classes.
*
* This implementation will not explicitly verify if a user exists, when operating on its properties. The methods of
* this implementation will <em>not</em> throw {@link org.jivesoftware.openfire.user.UserNotFoundException}.
*
* This class related to, but is distinct from {@link MappedUserPropertyProvider}. The Hybrid variant of the provider
* iterates over providers, operating on the first applicable instance. The Mapped variant, however, maps each user to
* exactly one provider.
*
* To use this provider, use the following system property definition:
*
* <ul>
* <li><tt>provider.userproperty.className = org.jivesoftware.openfire.user.HybridUserPropertyProvider</tt></li>
* </ul>
*
* Next, configure up to three providers, by setting these properties:
* <ol>
* <li><tt>hybridUserPropertyProvider.primaryProvider.className = fully.qualified.ClassUserPropertyProvider</tt></li>
* <li><tt>hybridUserPropertyProvider.secondaryProvider.className = fully.qualified.ClassUserPropertyProvider</tt></li>
* <li><tt>hybridUserPropertyProvider.tertiaryProvider.className = fully.qualified.ClassUserPropertyProvider</tt></li>
* </ol>
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public
class
HybridUserPropertyProvider
implements
UserPropertyProvider
{
private
static
final
Logger
Log
=
LoggerFactory
.
getLogger
(
HybridUserPropertyProvider
.
class
);
private
final
List
<
UserPropertyProvider
>
providers
=
new
ArrayList
<>();
public
HybridUserPropertyProvider
()
{
// Migrate user provider properties
JiveGlobals
.
migrateProperty
(
"hybridUserPropertyProvider.primaryProvider.className"
);
JiveGlobals
.
migrateProperty
(
"hybridUserPropertyProvider.secondaryProvider.className"
);
JiveGlobals
.
migrateProperty
(
"hybridUserPropertyProvider.tertiaryProvider.className"
);
// Load primary, secondary, and tertiary user providers.
final
UserPropertyProvider
primary
=
MappedUserPropertyProvider
.
instantiate
(
"hybridUserPropertyProvider.primaryProvider.className"
);
if
(
primary
!=
null
)
{
providers
.
add
(
primary
);
}
final
UserPropertyProvider
secondary
=
MappedUserPropertyProvider
.
instantiate
(
"hybridUserPropertyProvider.secondaryProvider.className"
);
if
(
secondary
!=
null
)
{
providers
.
add
(
secondary
);
}
final
UserPropertyProvider
tertiary
=
MappedUserPropertyProvider
.
instantiate
(
"hybridUserPropertyProvider.tertiaryProvider.className"
);
if
(
tertiary
!=
null
)
{
providers
.
add
(
tertiary
);
}
// Verify that there's at least one provider available.
if
(
providers
.
isEmpty
()
)
{
Log
.
error
(
"At least one UserPropertyProvider must be specified via openfire.xml or the system properties!"
);
}
}
/**
* Returns the properties from the first provider that returns a non-empty collection.
*
* When none of the providers provide properties an empty collection is returned.
*
* @param username The identifier of the user (cannot be null or empty).
* @return A collection, possibly empty, never null.
*/
@Override
public
Map
<
String
,
String
>
loadProperties
(
String
username
)
{
for
(
final
UserPropertyProvider
provider
:
providers
)
{
try
{
final
Map
<
String
,
String
>
properties
=
provider
.
loadProperties
(
username
);
if
(
!
properties
.
isEmpty
()
)
{
return
properties
;
}
}
catch
(
UserNotFoundException
e
)
{
// User not in this provider. Try other providers;
}
}
return
Collections
.
emptyMap
();
}
/**
* Returns a property from the first provider that returns a non-null value.
*
* This method will return null when the desired property was not defined in any provider.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @return The property value (possibly null).
*/
@Override
public
String
loadProperty
(
String
username
,
String
propName
)
{
for
(
final
UserPropertyProvider
provider
:
providers
)
{
try
{
final
String
property
=
provider
.
loadProperty
(
username
,
propName
);
if
(
property
!=
null
)
{
return
property
;
}
}
catch
(
UserNotFoundException
e
)
{
// User not in this provider. Try other providers;
}
}
return
null
;
}
/**
* Adds a new property, updating a previous property value if one already exists.
*
* Note that the implementation of this method is equal to that of {@link #updateProperty(String, String, String)}.
*
* First, tries to find a provider that has the property for the provided user. If that provider is read-only, an
* UnsupportedOperationException is thrown. If the provider is not read-only, the existing property value will be
* updated.
*
* When the property is not defined in any provider, it will be added in the first non-read-only provider.
*
* When all providers are read-only, an UnsupportedOperationException is thrown.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @param propValue The property value (cannot be null).
*/
@Override
public
void
insertProperty
(
String
username
,
String
propName
,
String
propValue
)
throws
UnsupportedOperationException
{
updateProperty
(
username
,
propName
,
propValue
);
}
/**
* Updates a property (or adds a new property when the property does not exist).
*
* Note that the implementation of this method is equal to that of {@link #insertProperty(String, String, String)}.
*
* First, tries to find a provider that has the property for the provided user. If that provider is read-only, an
* UnsupportedOperationException is thrown. If the provider is not read-only, the existing property value will be
* updated.
*
* When the property is not defined in any provider, it will be added in the first non-read-only provider.
*
* When all providers are read-only, an UnsupportedOperationException is thrown.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @param propValue The property value (cannot be null).
*/
@Override
public
void
updateProperty
(
String
username
,
String
propName
,
String
propValue
)
throws
UnsupportedOperationException
{
for
(
final
UserPropertyProvider
provider
:
providers
)
{
try
{
if
(
provider
.
loadProperty
(
username
,
propName
)
!=
null
)
{
provider
.
updateProperty
(
username
,
propName
,
propValue
);
return
;
}
}
catch
(
UserNotFoundException
e
)
{
// User not in this provider. Try other providers;
}
}
for
(
final
UserPropertyProvider
provider
:
providers
)
{
try
{
if
(
!
provider
.
isReadOnly
()
)
{
provider
.
insertProperty
(
username
,
propName
,
propValue
);
return
;
}
}
catch
(
UserNotFoundException
e
)
{
// User not in this provider. Try other providers;
}
}
throw
new
UnsupportedOperationException
();
}
/**
* Removes a property from all non-read-only providers.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
*/
@Override
public
void
deleteProperty
(
String
username
,
String
propName
)
throws
UnsupportedOperationException
{
// all providers are read-only
if
(
isReadOnly
()
)
{
throw
new
UnsupportedOperationException
();
}
for
(
final
UserPropertyProvider
provider
:
providers
)
{
if
(
provider
.
isReadOnly
()
)
{
continue
;
}
try
{
provider
.
deleteProperty
(
username
,
propName
);
}
catch
(
UserNotFoundException
e
)
{
// User not in this provider. Try other providers;
}
}
}
/**
* Returns whether <em>all</em> backing providers are read-only. When read-only, properties can not be created,
* deleted, or modified. If at least one provider is not read-only, this method returns false.
*
* @return true when all backing providers are read-only, otherwise false.
*/
@Override
public
boolean
isReadOnly
()
{
// TODO Make calls concurrent for improved throughput.
for
(
final
UserPropertyProvider
provider
:
providers
)
{
// If at least one provider is not readonly, neither is this proxy.
if
(
!
provider
.
isReadOnly
()
)
{
return
false
;
}
}
return
true
;
}
}
src/java/org/jivesoftware/openfire/user/property/JDBCUserPropertyProvider.java
0 → 100644
View file @
4818ae96
/*
* Copyright 2017 IgniteRealtime.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
jivesoftware
.
openfire
.
user
.
property
;
import
org.jivesoftware.database.DbConnectionManager
;
import
org.jivesoftware.util.JiveGlobals
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.sql.*
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* The JDBC user property provider allows you to use an external database to define the user properties. It is best used
* with the JDBCUserProvider, JDBCAuthProvider &and JDBCGroupProvider to provide integration between your external
* system and Openfire. All data is treated as read-only so any set operations will result in an exception.
*
* This implementation will not explicitly verify if a user exists, when operating on its properties. The methods of
* this implementation will <em>not</em> throw {@link org.jivesoftware.openfire.user.UserNotFoundException}.
*
* To enable this provider, set the following in the system properties:
*
* <ul>
* <li><tt>provider.userproperty.className = org.jivesoftware.openfire.user.property.JDBCUserPropertyProvider</tt></li>
* </ul>
*
* Then you need to set your driver, connection string and SQL statements:
*
* <ul>
* <li><tt>jdbcUserPropertyProvider.driver = com.mysql.jdbc.Driver</tt></li>
* <li><tt>jdbcUserPropertyProvider.connectionString = jdbc:mysql://localhost/dbname?user=username&password=secret</tt></li>
* <li><tt>jdbcUserPropertyProvider.loadPropertySQL = SELECT propName, propValue FROM myUser WHERE user = ? AND propName = ?</tt></li>
* <li><tt>jdbcUserPropertyProvider.loadPropertiesSQL = SELECT propValue FROM myUser WHERE user = ?</tt></li>
* </ul>
*
* In order to use the configured JDBC connection provider do not use a JDBCconnection string, set the following
* property:
*
* <tt>jdbcUserPropertyProvider.useConnectionProvider = true</tt></li>
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public
class
JDBCUserPropertyProvider
implements
UserPropertyProvider
{
private
static
final
Logger
Log
=
LoggerFactory
.
getLogger
(
JDBCUserPropertyProvider
.
class
);
private
String
loadPropertySQL
;
private
String
loadPropertiesSQL
;
private
String
connectionString
;
private
boolean
useConnectionProvider
;
/**
* Constructs a new JDBC user property provider.
*/
public
JDBCUserPropertyProvider
()
{
// Convert XML based provider setup to Database based
JiveGlobals
.
migrateProperty
(
"jdbcUserPropertyProvider.driver"
);
JiveGlobals
.
migrateProperty
(
"jdbcUserPropertyProvider.connectionString"
);
JiveGlobals
.
migrateProperty
(
"jdbcUserPropertyProvider.loadPropertySQL"
);
JiveGlobals
.
migrateProperty
(
"jdbcUserPropertyProvider.loadPropertiesSQL"
);
useConnectionProvider
=
JiveGlobals
.
getBooleanProperty
(
"jdbcUserProvider.useConnectionProvider"
);
// Load the JDBC driver and connection string.
if
(
!
useConnectionProvider
)
{
String
jdbcDriver
=
JiveGlobals
.
getProperty
(
"jdbcUserPropertyProvider.driver"
);
try
{
Class
.
forName
(
jdbcDriver
).
newInstance
();
}
catch
(
Exception
e
)
{
Log
.
error
(
"Unable to load JDBC driver: "
+
jdbcDriver
,
e
);
return
;
}
connectionString
=
JiveGlobals
.
getProperty
(
"jdbcProvider.connectionString"
);
}
// Load database statements for user data.
loadPropertySQL
=
JiveGlobals
.
getProperty
(
"jdbcUserPropertyProvider.loadPropertySQL"
);
loadPropertiesSQL
=
JiveGlobals
.
getProperty
(
"jdbcUserPropertyProvider.loadPropertiesSQL"
);
}
private
Connection
getConnection
()
throws
SQLException
{
if
(
useConnectionProvider
)
{
return
DbConnectionManager
.
getConnection
();
}
else
{
return
DriverManager
.
getConnection
(
connectionString
);
}
}
@Override
public
Map
<
String
,
String
>
loadProperties
(
String
username
)
throws
UnsupportedOperationException
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
ResultSet
rs
=
null
;
try
{
con
=
getConnection
();
pstmt
=
con
.
prepareStatement
(
loadPropertiesSQL
);
pstmt
.
setString
(
1
,
username
);
rs
=
pstmt
.
executeQuery
();
final
Map
<
String
,
String
>
result
=
new
HashMap
<>();
while
(
rs
.
next
()
)
{
final
String
propName
=
rs
.
getString
(
1
);
final
String
propValue
=
rs
.
getString
(
2
);
result
.
put
(
propName
,
propValue
);
}
return
result
;
}
catch
(
Exception
e
)
{
throw
new
UnsupportedOperationException
(
e
);
}
finally
{
DbConnectionManager
.
closeConnection
(
rs
,
pstmt
,
con
);
}
}
@Override
public
String
loadProperty
(
String
username
,
String
propName
)
{
Connection
con
=
null
;
PreparedStatement
pstmt
=
null
;
ResultSet
rs
=
null
;
try
{
con
=
getConnection
();
pstmt
=
con
.
prepareStatement
(
loadPropertySQL
);
pstmt
.
setString
(
1
,
username
);
pstmt
.
setString
(
2
,
propName
);
rs
=
pstmt
.
executeQuery
();
final
Map
<
String
,
String
>
result
=
new
HashMap
<>();
if
(
rs
.
next
()
)
{
return
rs
.
getString
(
1
);
}
return
null
;
}
catch
(
Exception
e
)
{
throw
new
UnsupportedOperationException
(
e
);
}
finally
{
DbConnectionManager
.
closeConnection
(
rs
,
pstmt
,
con
);
}
}
@Override
public
void
insertProperty
(
String
username
,
String
propName
,
String
propValue
)
throws
UnsupportedOperationException
{
throw
new
UnsupportedOperationException
();
}
@Override
public
void
updateProperty
(
String
username
,
String
propName
,
String
propValue
)
throws
UnsupportedOperationException
{
throw
new
UnsupportedOperationException
();
}
@Override
public
void
deleteProperty
(
String
username
,
String
propName
)
throws
UnsupportedOperationException
{
throw
new
UnsupportedOperationException
();
}
@Override
public
boolean
isReadOnly
()
{
return
true
;
}
}
src/java/org/jivesoftware/openfire/user/property/MappedUserPropertyProvider.java
0 → 100644
View file @
4818ae96
/*
* Copyright 2017 IgniteRealtime.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
jivesoftware
.
openfire
.
user
.
property
;
import
org.jivesoftware.openfire.user.UserNotFoundException
;
import
org.jivesoftware.util.ClassUtils
;
import
org.jivesoftware.util.JiveGlobals
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.util.Map
;
/**
* A {@link UserPropertyProvider} that delegates to a user-specific UserPropertyProvider.
*
* This implementation will explicitly verify if a user exists, when operating on its properties, but only if the
* corresponding mapped provider does so. If that is the case, then the methods of this implementation will throw
* {@link org.jivesoftware.openfire.user.UserNotFoundException}.
*
* This class related to, but is distinct from {@link HybridUserPropertyProvider}. The Hybrid variant of the provider
* iterates over providers, operating on the first applicable instance. This Mapped variant, however, maps each user to
* exactly one provider.
*
* To use this provider, use the following system property definition:
*
* <ul>
* <li><tt>provider.userproperty.className = org.jivesoftware.openfire.user.MappedUserPropertyProvider</tt></li>
* </ul>
*
* To be usable, a {@link UserPropertyProviderMapper} must be configured using the <tt>mappedUserPropertyProvider.mapper.className</tt>
* system property. It is of importance to note that most UserPropertyProviderMapper implementations will require additional
* configuration.
*
* @author Guus der Kinderen, guus@goodbytes.nl
*/
public
class
MappedUserPropertyProvider
implements
UserPropertyProvider
{
/**
* Name of the property of which the value is expected to be the classname of the UserPropertyProviderMapper
* instance to be used by instances of this class.
*/
public
static
final
String
PROPERTY_MAPPER_CLASSNAME
=
"mappedUserPropertyProvider.mapper.className"
;
private
static
final
Logger
Log
=
LoggerFactory
.
getLogger
(
MappedUserPropertyProvider
.
class
);
/**
* Used to determine what provider is to be used to operate on a particular user.
*/
protected
final
UserPropertyProviderMapper
mapper
;
public
MappedUserPropertyProvider
()
{
// Migrate properties.
JiveGlobals
.
migrateProperty
(
PROPERTY_MAPPER_CLASSNAME
);
// Instantiate mapper.
final
String
mapperClass
=
JiveGlobals
.
getProperty
(
PROPERTY_MAPPER_CLASSNAME
);
if
(
mapperClass
==
null
)
{
throw
new
IllegalStateException
(
"A mapper must be specified via openfire.xml or the system properties."
);
}
try
{
final
Class
c
=
ClassUtils
.
forName
(
mapperClass
);
mapper
=
(
UserPropertyProviderMapper
)
c
.
newInstance
();
}
catch
(
Exception
e
)
{
throw
new
IllegalStateException
(
"Unable to create new instance of UserPropertyProviderMapper class: "
+
mapperClass
,
e
);
}
}
/**
* Instantiates a UserPropertyProvider based on a property value (that is expected to be a class name). When the
* property is not set, this method returns null. When the property is set, but an exception occurs while
* instantiating the class, this method logs the error and returns null.
*
* UserProvider classes are required to have a public, no-argument constructor.
*
* @param propertyName A property name (cannot ben ull).
* @return A user provider (can be null).
*/
public
static
UserPropertyProvider
instantiate
(
String
propertyName
)
{
final
String
className
=
JiveGlobals
.
getProperty
(
propertyName
);
if
(
className
==
null
)
{
Log
.
debug
(
"Property '{}' is undefined. Skipping."
,
propertyName
);
return
null
;
}
Log
.
debug
(
"About to to instantiate an UserPropertyProvider '{}' based on the value of property '{}'."
,
className
,
propertyName
);
try
{
final
Class
c
=
ClassUtils
.
forName
(
className
);
final
UserPropertyProvider
provider
=
(
UserPropertyProvider
)
c
.
newInstance
();
Log
.
debug
(
"Instantiated UserPropertyProvider '{}'"
,
className
);
return
provider
;
}
catch
(
Exception
e
)
{
Log
.
error
(
"Unable to load UserPropertyProvider '{}'. Users in this provider will be disabled."
,
className
,
e
);
return
null
;
}
}
@Override
public
Map
<
String
,
String
>
loadProperties
(
String
username
)
throws
UserNotFoundException
{
return
mapper
.
getUserPropertyProvider
(
username
).
loadProperties
(
username
);
}
@Override
public
String
loadProperty
(
String
username
,
String
propName
)
throws
UserNotFoundException
{
return
mapper
.
getUserPropertyProvider
(
username
).
loadProperty
(
username
,
propName
);
}
@Override
public
void
insertProperty
(
String
username
,
String
propName
,
String
propValue
)
throws
UserNotFoundException
{
mapper
.
getUserPropertyProvider
(
username
).
insertProperty
(
username
,
propName
,
propValue
);
}
@Override
public
void
updateProperty
(
String
username
,
String
propName
,
String
propValue
)
throws
UserNotFoundException
{
mapper
.
getUserPropertyProvider
(
username
).
updateProperty
(
username
,
propName
,
propValue
);
}
@Override
public
void
deleteProperty
(
String
username
,
String
propName
)
throws
UserNotFoundException
{
mapper
.
getUserPropertyProvider
(
username
).
deleteProperty
(
username
,
propName
);
}
/**
* Returns whether <em>all</em> backing providers are read-only. When read-only, properties can not be created,
* deleted, or modified. If at least one provider is not read-only, this method returns false.
*
* @return true when all backing providers are read-only, otherwise false.
*/
@Override
public
boolean
isReadOnly
()
{
// TODO Make calls concurrent for improved throughput.
for
(
final
UserPropertyProvider
provider
:
mapper
.
getUserPropertyProviders
()
)
{
// If at least one provider is not readonly, neither is this proxy.
if
(
!
provider
.
isReadOnly
()
)
{
return
false
;
}
}
return
true
;
}
}
src/java/org/jivesoftware/openfire/user/property/UserPropertyProvider.java
0 → 100644
View file @
4818ae96
/*
* Copyright 2017 IgniteRealtime.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
jivesoftware
.
openfire
.
user
.
property
;
import
org.jivesoftware.openfire.user.User
;
import
org.jivesoftware.openfire.user.UserNotFoundException
;
import
java.util.Map
;
/**
* A provider for user properties. User properties are defined Map of String key and values that does not support null.
* value.
*
* Some, but not all, implementations are expected to store user properties in a relation to an existing user object.
* This interface definition does not require implementations to verify that a user object indeed exists, when
* processing data. As a result, methods defined here may, but are not required to throw {@link UserNotFoundException}
* when processing property data for non-existing users. Implementations should clearly document their behavior in
* this respect.
*
* <b>Warning:</b> in virtually all cases a user property provider should not be used directly. Instead, use the
* Map returned by {@link User#getProperties() ) to create, read, update or delete user properties. Failure to do so
* is likely to result in inconsistent data behavior and race conditions. Direct access to the user property
* provider is only provided for special-case logic.
*
* @author Guus der Kinderen, guus@goodbytes.nl
* @see User#getProperties
*/
public
interface
UserPropertyProvider
{
/**
* Returns true if this UserPropertyProvider is read-only. When read-only, properties can not be created, deleted or
* modified. Invocation of the corresponding methods should result in an {@link UnsupportedOperationException}.
*
* @return true if the user provider is read-only.
*/
boolean
isReadOnly
();
/**
* Retrieves all properties for a particular user.
*
* @param username The identifier of the user (cannot be null or empty).
* @return A collection, possibly empty, but never null.
*/
Map
<
String
,
String
>
loadProperties
(
String
username
)
throws
UserNotFoundException
;
/**
* Retrieves a property value for a user.
*
* This method will return null when the desired property was not defined for the user (null values are not
* supported).
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @return The property value (possibly null).
*/
String
loadProperty
(
String
username
,
String
propName
)
throws
UserNotFoundException
;
/**
* Adds a property for an user.
*
* The behavior of inserting a duplicate property name is not defined by this interface.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @param propValue The property value (cannot be null).
*/
void
insertProperty
(
String
username
,
String
propName
,
String
propValue
)
throws
UserNotFoundException
,
UnsupportedOperationException
;
/**
* Changes a property value for an user.
*
* The behavior of updating a non-existing property is not defined by this interface.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @param propValue The property value (cannot be null).
*/
void
updateProperty
(
String
username
,
String
propName
,
String
propValue
)
throws
UserNotFoundException
,
UnsupportedOperationException
;
/**
* Removes one particular property for a particular user.
*
* The behavior of deleting a non-existing property is not defined by this interface.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
*/
void
deleteProperty
(
String
username
,
String
propName
)
throws
UserNotFoundException
,
UnsupportedOperationException
;
}
src/java/org/jivesoftware/openfire/user/property/UserPropertyProviderMapper.java
0 → 100644
View file @
4818ae96
/*
* Copyright 2017 IgniteRealtime.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
jivesoftware
.
openfire
.
user
.
property
;
import
java.util.Set
;
/**
* Implementations are used to determine what UserPropertyProvider is to be used for a particular username.
*
* Note that the provided username need not reflect a pre-existing user (the instance might be used to determine in
* which provider a new user is to be created).
*
* Implementation must have a no-argument constructor.
*
* @author Guus der Kinderen, guus@goodbytes.nl
* @see MappedUserPropertyProvider
*/
public
interface
UserPropertyProviderMapper
{
/**
* Finds a suitable UserPropertyProvider for the user.
*
* Note that the provided username need not reflect a pre-existing user (the instance might be used to determine in
* which provider a new user is to be created).
*
* Implementations are expected to be able to find a UserPropertyProvider for any username. If an implementation
* fails to do so, such a failure is assumed to be the result of a problem in implementation or configuration.
*
* @param username A user identifier (cannot be null or empty).
* @return A UserPropertyProvider for the user (never null).
*/
UserPropertyProvider
getUserPropertyProvider
(
String
username
);
/**
* Returns all providers that are used by this instance.
*
* The returned collection should have a consistent, predictable iteration order.
*
* @return all providers (never null).
*/
Set
<
UserPropertyProvider
>
getUserPropertyProviders
();
}
src/plugins/justmarried/changelog.html
View file @
4818ae96
...
...
@@ -44,6 +44,12 @@
Just married Plugin Changelog
</h1>
<p><b>
1.2.1
</b>
-- May 31, 2017
</p>
<ul>
<li>
Updated to match new API in Openfire 4.2.0
</li>
<li>
Slight optimization for copying the user properties.
</li>
</ul>
<p><b>
1.2.0
</b>
-- October 12, 2015
</p>
<ul>
<li>
[
<a
href=
'http://www.igniterealtime.org/issues/browse/OF-953'
>
OF-953
</a>
] - Updated JSP libraries.
</li>
...
...
src/plugins/justmarried/plugin.xml
View file @
4818ae96
...
...
@@ -5,8 +5,8 @@
<name>
Just married
</name>
<description>
Allows admins to rename or copy users
</description>
<author>
Holger Bergunde
</author>
<version>
1.2.
0
</version>
<date>
10/12/2015
</date>
<version>
1.2.
1
</version>
<date>
05/31/2017
</date>
<minServerVersion>
4.0.0
</minServerVersion>
<adminconsole>
...
...
src/plugins/justmarried/pom.xml
View file @
4818ae96
...
...
@@ -8,7 +8,7 @@
</parent>
<groupId>
org.igniterealtime.openfire.plugins
</groupId>
<artifactId>
justmarried
</artifactId>
<version>
1.2.
0
</version>
<version>
1.2.
1
</version>
<name>
JustMarried Plugin
</name>
<description>
Allows admins to rename or copy users
</description>
...
...
src/plugins/justmarried/src/java/org/jivesoftware/openfire/plugin/married/JustMarriedPlugin.java
View file @
4818ae96
...
...
@@ -98,9 +98,7 @@ public class JustMarriedPlugin implements Plugin {
}
private
static
void
copyProperties
(
User
currentUser
,
User
newUser
)
{
for
(
String
key
:
currentUser
.
getProperties
().
keySet
())
{
newUser
.
getProperties
().
put
(
key
,
User
.
getPropertyValue
(
currentUser
.
getUsername
(),
key
));
}
newUser
.
getProperties
().
putAll
(
currentUser
.
getProperties
()
);
}
private
static
void
copyRoster
(
User
currentUser
,
User
newUser
,
String
currentUserName
)
{
...
...
src/plugins/restAPI/changelog.html
View file @
4818ae96
...
...
@@ -44,6 +44,12 @@
REST API Plugin Changelog
</h1>
<p><b>
1.2.6
</b>
-- May 31, 2017
</p>
<ul>
<li>
Updated to match new API in Openfire 4.2.0
</li>
<li>
Slight optimization for copying the user properties.
</li>
</ul>
<p><b>
1.2.5
</b>
-- October 14th, 2016
</p>
<ul>
<li>
Updated to match new API in Openfire 4.1.0
</li>
...
...
src/plugins/restAPI/plugin.xml
View file @
4818ae96
...
...
@@ -5,8 +5,8 @@
<name>
REST API
</name>
<description>
Allows administration over a RESTful API.
</description>
<author>
Roman Soldatow
</author>
<version>
1.2.
5
</version>
<date>
10/14/2016
</date>
<version>
1.2.
6
</version>
<date>
05/31/2017
</date>
<minServerVersion>
4.1.0
</minServerVersion>
<adminconsole>
<tab
id=
"tab-server"
>
...
...
src/plugins/restAPI/pom.xml
View file @
4818ae96
...
...
@@ -8,7 +8,9 @@
</parent>
<groupId>
org.igniterealtime.openfire.plugins
</groupId>
<artifactId>
restAPI
</artifactId>
<version>
1.2.6
</version>
<name>
Rest API Plugin
</name>
<description>
Allows administration over a RESTful API.
</description>
<build>
<sourceDirectory>
src/java
</sourceDirectory>
...
...
src/plugins/restAPI/src/java/org/jivesoftware/openfire/plugin/rest/controller/JustMarriedController.java
View file @
4818ae96
...
...
@@ -148,9 +148,7 @@ public class JustMarriedController {
* the new user
*/
private
static
void
copyProperties
(
User
currentUser
,
User
newUser
)
{
for
(
String
key
:
currentUser
.
getProperties
().
keySet
())
{
newUser
.
getProperties
().
put
(
key
,
User
.
getPropertyValue
(
currentUser
.
getUsername
(),
key
));
}
newUser
.
getProperties
().
putAll
(
currentUser
.
getProperties
()
);
}
/**
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment