Commit 05134318 authored by Gabriel Guardincerri's avatar Gabriel Guardincerri Committed by gguardin

[JM-1281] Fixed an exception using a user with a not visible email and CS as a provider.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/branches@10018 b35dd754-fafc-0310-a699-88a17e54d16e
parent 6d34b403
...@@ -23,22 +23,36 @@ import org.xmpp.packet.JID; ...@@ -23,22 +23,36 @@ import org.xmpp.packet.JID;
import java.util.*; import java.util.*;
/** /**
* @author Daniel Henninger * The ClearspaceUserProvider uses the UserService and ProfileSearchService web service inside of Clearspace
* to retrieve user information and to search for users from Clearspace.
*
* @author Gabriel Guardincerri
*/ */
public class ClearspaceUserProvider implements UserProvider { public class ClearspaceUserProvider implements UserProvider {
// The UserService webservice url prefix
protected static final String USER_URL_PREFIX = "userService/"; protected static final String USER_URL_PREFIX = "userService/";
// The ProfileSearchService webservice url prefix
protected static final String SEARCH_URL_PREFIX = "profileSearchService/"; protected static final String SEARCH_URL_PREFIX = "profileSearchService/";
private ClearspaceManager manager; private ClearspaceManager manager;
// Used to know it CS is a read only user provider
private Boolean readOnly; private Boolean readOnly;
public ClearspaceUserProvider() { public ClearspaceUserProvider() {
// Gets the manager // Gets the manager
manager = ClearspaceManager.getInstance(); manager = ClearspaceManager.getInstance();
loadReadOnly();
} }
/**
* Loads the user using the userService/users GET service. Only loads local users.
* Throws a UserNotFoundException exception if the user could not be found.
*
* @param username the username of the user to load
* @return a user instance with the user information
* @throws UserNotFoundException if the user could not be found
*/
public User loadUser(String username) throws UserNotFoundException { public User loadUser(String username) throws UserNotFoundException {
// Checks if the user is local // Checks if the user is local
if (username.contains("@")) { if (username.contains("@")) {
...@@ -52,6 +66,19 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -52,6 +66,19 @@ public class ClearspaceUserProvider implements UserProvider {
return translate(getUserByUsername(username)); return translate(getUserByUsername(username));
} }
/**
* Creates user using the userService/users POST service. If Clearspace is a read only
* provider throws an UnsupportedOperationException. If there is already a user with
* the username throws a UserAlreadyExistsException.
*
* @param username the username of the user
* @param password the password of the user
* @param name the name of the user (optional)
* @param email the email of the user
* @return an instance of the created user
* @throws UserAlreadyExistsException If there is already a user with the username
* @throws UnsupportedOperationException If Clearspace is a read only provider
*/
public User createUser(String username, String password, String name, String email) throws UserAlreadyExistsException { public User createUser(String username, String password, String name, String email) throws UserAlreadyExistsException {
if (isReadOnly()) { if (isReadOnly()) {
// Reject the operation since the provider is read-only // Reject the operation since the provider is read-only
...@@ -100,6 +127,11 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -100,6 +127,11 @@ public class ClearspaceUserProvider implements UserProvider {
} }
} }
/**
* Creates user using the userService/users DELETE service. If the user is not found returns.
*
* @param username the username of the user to delete
*/
public void deleteUser(String username) { public void deleteUser(String username) {
if (isReadOnly()) { if (isReadOnly()) {
// Reject the operation since the provider is read-only // Reject the operation since the provider is read-only
...@@ -119,6 +151,11 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -119,6 +151,11 @@ public class ClearspaceUserProvider implements UserProvider {
} }
} }
/**
* Gets the user count using the userService/users/count GET service.
*
* @return the user count
*/
public int getUserCount() { public int getUserCount() {
try { try {
String path = USER_URL_PREFIX + "users/count"; String path = USER_URL_PREFIX + "users/count";
...@@ -131,11 +168,21 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -131,11 +168,21 @@ public class ClearspaceUserProvider implements UserProvider {
} }
} }
/**
* Gets all users using the userService/userNames GET service.
*
* @return a list of all users
*/
public Collection<User> getUsers() { public Collection<User> getUsers() {
Collection<String> usernames = getUsernames(); Collection<String> usernames = getUsernames();
return new UserCollection(usernames.toArray(new String[usernames.size()])); return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
/**
* Gets all usernames using the userService/userNames GET service.
*
* @return a list of all the usernames
*/
public Collection<String> getUsernames() { public Collection<String> getUsernames() {
try { try {
String path = USER_URL_PREFIX + "userNames"; String path = USER_URL_PREFIX + "userNames";
...@@ -148,6 +195,13 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -148,6 +195,13 @@ public class ClearspaceUserProvider implements UserProvider {
} }
} }
/**
* Gets a bounded list of users using the userService/userNames GET service.
*
* @param startIndex the start index
* @param numResults the number of result
* @return a bounded list of users
*/
public Collection<User> getUsers(int startIndex, int numResults) { public Collection<User> getUsers(int startIndex, int numResults) {
String[] usernamesAll = getUsernames().toArray(new String[0]); String[] usernamesAll = getUsernames().toArray(new String[0]);
Collection<String> usernames = new ArrayList<String>(); Collection<String> usernames = new ArrayList<String>();
...@@ -160,6 +214,13 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -160,6 +214,13 @@ public class ClearspaceUserProvider implements UserProvider {
return new UserCollection(usernames.toArray(new String[usernames.size()])); return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
/**
* Updates the name of the user using the userService/update service.
*
* @param username the username of the user
* @param name the new name of the user
* @throws UserNotFoundException if there is no user with that username
*/
public void setName(String username, String name) throws UserNotFoundException { public void setName(String username, String name) throws UserNotFoundException {
if (isReadOnly()) { if (isReadOnly()) {
// Reject the operation since the provider is read-only // Reject the operation since the provider is read-only
...@@ -177,6 +238,13 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -177,6 +238,13 @@ public class ClearspaceUserProvider implements UserProvider {
updateUser(userUpdateParams); updateUser(userUpdateParams);
} }
/**
* Updates the email of the user using the userService/update service.
*
* @param username the username of the user
* @param email the new email of the user
* @throws UserNotFoundException if the user could not be found
*/
public void setEmail(String username, String email) throws UserNotFoundException { public void setEmail(String username, String email) throws UserNotFoundException {
if (isReadOnly()) { if (isReadOnly()) {
// Reject the operation since the provider is read-only // Reject the operation since the provider is read-only
...@@ -194,6 +262,14 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -194,6 +262,14 @@ public class ClearspaceUserProvider implements UserProvider {
updateUser(userUpdateParams); updateUser(userUpdateParams);
} }
/**
* Updates the creationDate of the user using the userService/update service.
*
* @param username the username of the user
* @param creationDate the new email of the user
* @throws UserNotFoundException if the user could not be found
*/
public void setCreationDate(String username, Date creationDate) throws UserNotFoundException { public void setCreationDate(String username, Date creationDate) throws UserNotFoundException {
if (isReadOnly()) { if (isReadOnly()) {
// Reject the operation since the provider is read-only // Reject the operation since the provider is read-only
...@@ -212,6 +288,13 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -212,6 +288,13 @@ public class ClearspaceUserProvider implements UserProvider {
updateUser(userUpdateParams); updateUser(userUpdateParams);
} }
/**
* Updates the modificationDate of the user using the userService/update service.
*
* @param username the username of the user
* @param modificationDate the new modificationDate of the user
* @throws UserNotFoundException if the user could not be found
*/
public void setModificationDate(String username, Date modificationDate) throws UserNotFoundException { public void setModificationDate(String username, Date modificationDate) throws UserNotFoundException {
if (isReadOnly()) { if (isReadOnly()) {
// Reject the operation since the provider is read-only // Reject the operation since the provider is read-only
...@@ -230,6 +313,13 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -230,6 +313,13 @@ public class ClearspaceUserProvider implements UserProvider {
updateUser(userUpdateParams); updateUser(userUpdateParams);
} }
/**
* Creates the parameters to send in a update user request based on the information of <code>username</code>
*
* @param username the username of the user
* @return the parameters to send in a update user request
* @throws UserNotFoundException if the user could not be found
*/
protected Element getUserUpdateParams(String username) throws UserNotFoundException { protected Element getUserUpdateParams(String username) throws UserNotFoundException {
// Creates the user update params element // Creates the user update params element
Element userUpdateParams = DocumentHelper.createDocument().addElement("updateUser"); Element userUpdateParams = DocumentHelper.createDocument().addElement("updateUser");
...@@ -246,6 +336,12 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -246,6 +336,12 @@ public class ClearspaceUserProvider implements UserProvider {
return userUpdateParams; return userUpdateParams;
} }
/**
* Updates the user using the userService/users PUT service.
*
* @param userUpdateParams the request parameters
* @throws UserNotFoundException if the user could not be found
*/
protected void updateUser(Element userUpdateParams) throws UserNotFoundException { protected void updateUser(Element userUpdateParams) throws UserNotFoundException {
try { try {
String path = USER_URL_PREFIX + "users"; String path = USER_URL_PREFIX + "users";
...@@ -259,32 +355,44 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -259,32 +355,44 @@ public class ClearspaceUserProvider implements UserProvider {
} }
} }
/**
* Clearsapce can search using three fields: username, name and email.
*
* @return a list of username, name and email
* @throws UnsupportedOperationException
*/
public Set<String> getSearchFields() throws UnsupportedOperationException { public Set<String> getSearchFields() throws UnsupportedOperationException {
return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email")); return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email"));
} }
/**
* Search for the user using the userService/search POST method.
*
* @param fields the fields to search on.
* @param query the query string.
* @return a Collection of users that match the search.
* @throws UnsupportedOperationException if the provider does not
* support the operation (this is an optional operation).
*/
public Collection<User> findUsers(Set<String> fields, String query) throws UnsupportedOperationException { public Collection<User> findUsers(Set<String> fields, String query) throws UnsupportedOperationException {
// Creates the XML with the data // Creates the XML with the data
Document groupDoc = DocumentHelper.createDocument(); Element paramsE = DocumentHelper.createDocument().addElement("search");
Element rootE = groupDoc.addElement("searchProfile");
Element queryE = rootE.addElement("WSProfileSearchQuery"); Element queryE = paramsE.addElement("query");
Element keywords = queryE.addElement("keywords");
keywords.addText(query); queryE.addElement("keywords").addText(query);
Element searchUsername = queryE.addElement("searchUsername");
searchUsername.addText("true"); queryE.addElement("searchUsername").addText("true");
Element searchName = queryE.addElement("searchName"); queryE.addElement("searchName").addText("true");
searchName.addText("true"); queryE.addElement("searchEmail").addText("true");
Element searchEmail = queryE.addElement("searchEmail"); queryE.addElement("searchProfile").addText("false");
searchEmail.addText("true");
Element searchProfile = queryE.addElement("searchProfile");
searchProfile.addText("false");
try { try {
List<String> usernames = new ArrayList<String>(); List<String> usernames = new ArrayList<String>();
String path = SEARCH_URL_PREFIX + "searchProfile";
//TODO create a service on CS to get only the username field //TODO create a service on CS to get only the username field
Element element = manager.executeRequest(GET, path); String path = SEARCH_URL_PREFIX + "searchProfile";
Element element = manager.executeRequest(POST, path, paramsE.asXML());
List<Node> userNodes = (List<Node>) element.selectNodes("return"); List<Node> userNodes = (List<Node>) element.selectNodes("return");
for (Node userNode : userNodes) { for (Node userNode : userNodes) {
...@@ -299,28 +407,40 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -299,28 +407,40 @@ public class ClearspaceUserProvider implements UserProvider {
} }
} }
/**
* Search for the user using the userService/searchBounded POST method.
*
* @param fields the fields to search on.
* @param query the query string.
* @param startIndex the starting index in the search result to return.
* @param numResults the number of users to return in the search result.
* @return a Collection of users that match the search.
* @throws UnsupportedOperationException if the provider does not
* support the operation (this is an optional operation).
*/
public Collection<User> findUsers(Set<String> fields, String query, int startIndex, int numResults) throws UnsupportedOperationException { public Collection<User> findUsers(Set<String> fields, String query, int startIndex, int numResults) throws UnsupportedOperationException {
// Creates the XML with the data // Creates the XML with the data
Document groupDoc = DocumentHelper.createDocument(); Element paramsE = DocumentHelper.createDocument().addElement("searchBounded");
Element rootE = groupDoc.addElement("searchBounded");
Element queryE = rootE.addElement("WSProfileSearchQuery"); Element queryE = paramsE.addElement("query");
Element keywords = queryE.addElement("keywords");
keywords.addText(query); queryE.addElement("keywords").addText(query);
Element searchUsername = queryE.addElement("searchUsername");
searchUsername.addText("true"); queryE.addElement("searchUsername").addText("true");
Element searchName = queryE.addElement("searchName"); queryE.addElement("searchName").addText("true");
searchName.addText("true"); queryE.addElement("searchEmail").addText("true");
Element searchEmail = queryE.addElement("searchEmail"); queryE.addElement("searchProfile").addText("false");
searchEmail.addText("true");
Element searchProfile = queryE.addElement("searchProfile"); paramsE.addElement("startIndex").addText(String.valueOf(startIndex));
searchProfile.addText("false"); paramsE.addElement("numResults").addText(String.valueOf(numResults));
try { try {
List<String> usernames = new ArrayList<String>(); List<String> usernames = new ArrayList<String>();
String path = SEARCH_URL_PREFIX + "searchProfile/" + startIndex + "/" + numResults;
Element element = manager.executeRequest(GET, path);
//TODO create a service on CS to get only the username field //TODO create a service on CS to get only the username field
String path = SEARCH_URL_PREFIX + "searchProfile";
Element element = manager.executeRequest(POST, path, paramsE.asXML());
List<Node> userNodes = (List<Node>) element.selectNodes("return"); List<Node> userNodes = (List<Node>) element.selectNodes("return");
for (Node userNode : userNodes) { for (Node userNode : userNodes) {
String username = userNode.selectSingleNode("username").getText(); String username = userNode.selectSingleNode("username").getText();
...@@ -334,22 +454,44 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -334,22 +454,44 @@ public class ClearspaceUserProvider implements UserProvider {
} }
} }
/**
* Returns true if Clearspace is a read only user provider.
*
* @return true if Clearspace is a read only user provider
*/
public boolean isReadOnly() { public boolean isReadOnly() {
if (readOnly == null) {
synchronized (this) {
if (readOnly == null) { if (readOnly == null) {
loadReadOnly(); loadReadOnly();
} }
}
}
// If it is null returns the most restrictive answer. // If it is null returns the most restrictive answer.
return (readOnly == null ? false : readOnly); return (readOnly == null ? false : readOnly);
} }
/**
* In Clearspace name is optional.
*
* @return false
*/
public boolean isNameRequired() { public boolean isNameRequired() {
return false; return false;
} }
/**
* In Clearspace email is required
*
* @return true
*/
public boolean isEmailRequired() { public boolean isEmailRequired() {
return true; return true;
} }
/**
* Tries to load the read only attribute using the userService/isReadOnly service.
*/
private void loadReadOnly() { private void loadReadOnly() {
try { try {
// See if the is read only // See if the is read only
...@@ -361,6 +503,12 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -361,6 +503,12 @@ public class ClearspaceUserProvider implements UserProvider {
} }
} }
/**
* Translates a Clearspace xml user response into a Openfire User
*
* @param responseNode the Clearspace response
* @return a User instance with its information
*/
private User translate(Node responseNode) { private User translate(Node responseNode) {
String username = null; String username = null;
String name = null; String name = null;
...@@ -376,21 +524,21 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -376,21 +524,21 @@ public class ClearspaceUserProvider implements UserProvider {
// Gets the name if it is visible // Gets the name if it is visible
boolean nameVisible = Boolean.valueOf(userNode.selectSingleNode("nameVisible").getText()); boolean nameVisible = Boolean.valueOf(userNode.selectSingleNode("nameVisible").getText());
if (nameVisible) {
// Gets the name
tmpNode = userNode.selectSingleNode("name"); tmpNode = userNode.selectSingleNode("name");
if (tmpNode != null) { if (tmpNode != null) {
name = tmpNode.getText(); name = tmpNode.getText();
} }
}
// Gets the email if it is visible // Gets the email if it is visible
boolean emailVisible = Boolean.valueOf(userNode.selectSingleNode("emailVisible").getText()); boolean emailVisible = Boolean.valueOf(userNode.selectSingleNode("emailVisible").getText());
if (emailVisible) {
// Gets the email
tmpNode = userNode.selectSingleNode("email"); tmpNode = userNode.selectSingleNode("email");
if (tmpNode != null) { if (tmpNode != null) {
email = tmpNode.getText(); email = tmpNode.getText();
} }
}
// Gets the creation date // Gets the creation date
tmpNode = userNode.selectSingleNode("creationDate"); tmpNode = userNode.selectSingleNode("creationDate");
...@@ -405,9 +553,19 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -405,9 +553,19 @@ public class ClearspaceUserProvider implements UserProvider {
} }
// Creates the user // Creates the user
return new User(username, name, email, creationDate, modificationDate); User user = new User(username, name, email, creationDate, modificationDate);
user.setNameVisible(nameVisible);
user.setEmailVisible(emailVisible);
return user;
} }
/**
* Gets a user using the userService/users GET service.
*
* @param username the username of the user
* @return the user xml response
* @throws UserNotFoundException if the user could not be found
*/
private Element getUserByUsername(String username) throws UserNotFoundException { private Element getUserByUsername(String username) throws UserNotFoundException {
try { try {
......
...@@ -139,10 +139,10 @@ class ClearspaceVCardTranslator { ...@@ -139,10 +139,10 @@ class ClearspaceVCardTranslator {
/** /**
* Init the fields of clearspace based on they name. * Init the fields of clearspace based on they name.
* *
* @param fieldsId * @param fields the fields information
*/ */
protected void initClearspaceFieldsId(Element fieldsId) { protected void initClearspaceFieldsId(Element fields) {
List<Element> fieldsList = fieldsId.elements("return"); List<Element> fieldsList = fields.elements("return");
for (Element field : fieldsList) { for (Element field : fieldsList) {
String fieldName = field.elementText("name"); String fieldName = field.elementText("name");
long fieldID = Long.valueOf(field.elementText("ID")); long fieldID = Long.valueOf(field.elementText("ID"));
...@@ -155,6 +155,16 @@ class ClearspaceVCardTranslator { ...@@ -155,6 +155,16 @@ class ClearspaceVCardTranslator {
} }
/**
* Translates a VCard of Openfire into profiles, user information and a avatar of Clearspace.
* Returns what can of action has been made over the the profilesElement, userElement and avatarElement/
*
* @param vCardElement the VCard information
* @param profilesElement the profile to add/modify/delete the information
* @param userElement the user to add/modify/delete the information
* @param avatarElement the avatar to add/modify/delete the information
* @return a list of actions performed over the profilesElement, userElement and avatarElement
*/
protected Action[] translateVCard(Element vCardElement, Element profilesElement, Element userElement, Element avatarElement) { protected Action[] translateVCard(Element vCardElement, Element profilesElement, Element userElement, Element avatarElement) {
Action[] actions = new Action[3]; Action[] actions = new Action[3];
...@@ -171,6 +181,13 @@ class ClearspaceVCardTranslator { ...@@ -171,6 +181,13 @@ class ClearspaceVCardTranslator {
return actions; return actions;
} }
/**
* Updates the avatar values based on the vCard values
*
* @param avatarElement the avatar element to update
* @param vCardValues the vCard values with the information
* @return the action performed
*/
private Action updateAvatarValues(Element avatarElement, Map<VCardField, String> vCardValues) { private Action updateAvatarValues(Element avatarElement, Map<VCardField, String> vCardValues) {
Action action = Action.NO_ACTION; Action action = Action.NO_ACTION;
...@@ -201,6 +218,13 @@ class ClearspaceVCardTranslator { ...@@ -201,6 +218,13 @@ class ClearspaceVCardTranslator {
return action; return action;
} }
/**
* Updates the user values based on the vCard values
*
* @param userElement the user element to update
* @param vCardValues the vCard values
* @return the action performed
*/
private Action updateUserValues(Element userElement, Map<VCardField, String> vCardValues) { private Action updateUserValues(Element userElement, Map<VCardField, String> vCardValues) {
Action action = Action.NO_ACTION; Action action = Action.NO_ACTION;
...@@ -228,9 +252,9 @@ class ClearspaceVCardTranslator { ...@@ -228,9 +252,9 @@ class ClearspaceVCardTranslator {
/** /**
* Updates the values of the profiles with the values of the vCard * Updates the values of the profiles with the values of the vCard
* *
* @param profiles * @param profiles the profiles element to update
* @param vCardValues * @param vCardValues the vCard values
* @return * @return the action performed
*/ */
private Action updateProfilesValues(Element profiles, Map<VCardField, String> vCardValues) { private Action updateProfilesValues(Element profiles, Map<VCardField, String> vCardValues) {
Action action = Action.NO_ACTION; Action action = Action.NO_ACTION;
...@@ -259,32 +283,32 @@ class ClearspaceVCardTranslator { ...@@ -259,32 +283,32 @@ class ClearspaceVCardTranslator {
String oldValue; String oldValue;
switch (field) { switch (field) {
case TITLE: case TITLE:
if (modifyProfileValue(vCardValues, profiles, value, VCardField.TITLE)) { if (modifyProfileValue(vCardValues, value, VCardField.TITLE)) {
action = Action.MODIFY; action = Action.MODIFY;
} }
break; break;
case DEPARTMENT: case DEPARTMENT:
if (modifyProfileValue(vCardValues, profiles, value, VCardField.ORG_ORGUNIT)) { if (modifyProfileValue(vCardValues, value, VCardField.ORG_ORGUNIT)) {
action = Action.MODIFY; action = Action.MODIFY;
} }
break; break;
case ADDRESS: case ADDRESS:
if (modifyProfileValue(vCardValues, profiles, value, VCardField.ADR_WORK)) { if (modifyProfileValue(vCardValues, value, VCardField.ADR_WORK)) {
action = Action.MODIFY; action = Action.MODIFY;
} }
break; break;
case HOME_ADDRESS: case HOME_ADDRESS:
if (modifyProfileValue(vCardValues, profiles, value, VCardField.ADR_HOME)) { if (modifyProfileValue(vCardValues, value, VCardField.ADR_HOME)) {
action = Action.MODIFY; action = Action.MODIFY;
} }
break; break;
case TIME_ZONE: case TIME_ZONE:
if (modifyProfileValue(vCardValues, profiles, value, VCardField.TZ)) { if (modifyProfileValue(vCardValues, value, VCardField.TZ)) {
action = Action.MODIFY; action = Action.MODIFY;
} }
break; break;
case URL: case URL:
if (modifyProfileValue(vCardValues, profiles, value, VCardField.URL)) { if (modifyProfileValue(vCardValues, value, VCardField.URL)) {
action = Action.MODIFY; action = Action.MODIFY;
} }
break; break;
...@@ -454,6 +478,14 @@ class ClearspaceVCardTranslator { ...@@ -454,6 +478,14 @@ class ClearspaceVCardTranslator {
return action; return action;
} }
/**
* Adds a profiles element to the profiles if it is not empty
*
* @param profiles the profiles to add a profile to
* @param field the field type to add
* @param newValue the value to add
* @return true if the field was added
*/
private boolean addProfile(Element profiles, ClearspaceField field, String newValue) { private boolean addProfile(Element profiles, ClearspaceField field, String newValue) {
// Don't add empty vales // Don't add empty vales
if (newValue == null || "".equals(newValue.trim())) { if (newValue == null || "".equals(newValue.trim())) {
...@@ -470,7 +502,15 @@ class ClearspaceVCardTranslator { ...@@ -470,7 +502,15 @@ class ClearspaceVCardTranslator {
return true; return true;
} }
private boolean modifyProfileValue(Map<VCardField, String> vCardValues, Element profiles, Element value, VCardField vCardField) { /**
* Modifies the value of a profile if it is different from the original one.
*
* @param vCardValues the vCard values with the new values
* @param value the current value of the profile
* @param vCardField the vCard field
* @return true if the field was modified
*/
private boolean modifyProfileValue(Map<VCardField, String> vCardValues, Element value, VCardField vCardField) {
boolean modified = false; boolean modified = false;
String newValue = vCardValues.get(vCardField); String newValue = vCardValues.get(vCardField);
...@@ -486,6 +526,13 @@ class ClearspaceVCardTranslator { ...@@ -486,6 +526,13 @@ class ClearspaceVCardTranslator {
return modified; return modified;
} }
/**
* Adds the field type to the field value. Returns null if the value is empty.
*
* @param value the value
* @param type the type
* @return the field value with the type
*/
private String addFieldType(String value, String type) { private String addFieldType(String value, String type) {
if (value == null || "".equals(value.trim())) { if (value == null || "".equals(value.trim())) {
return null; return null;
...@@ -493,6 +540,13 @@ class ClearspaceVCardTranslator { ...@@ -493,6 +540,13 @@ class ClearspaceVCardTranslator {
return value + "|" + type; return value + "|" + type;
} }
/**
* Returns the field type of a field. Return null if the field doesn't
* contains a type
*
* @param field the field with the type
* @return the field type
*/
private String getFieldType(String field) { private String getFieldType(String field) {
int i = field.indexOf("|"); int i = field.indexOf("|");
if (i == -1) { if (i == -1) {
...@@ -502,6 +556,13 @@ class ClearspaceVCardTranslator { ...@@ -502,6 +556,13 @@ class ClearspaceVCardTranslator {
} }
} }
/**
* Returns the field value of a field. Return the field if the field doesn't
* contains a type.
*
* @param field the field
* @return the field value
*/
private String getFieldValue(String field) { private String getFieldValue(String field) {
int i = field.indexOf("|"); int i = field.indexOf("|");
if (i == -1) { if (i == -1) {
...@@ -513,10 +574,10 @@ class ClearspaceVCardTranslator { ...@@ -513,10 +574,10 @@ class ClearspaceVCardTranslator {
/** /**
* Collects the vCard values and store them into a map. * Collects the vCard values and store them into a map.
* They are stored with this constants: * They are stored with the VCardField enum.
* *
* @param vCardElement * @param vCardElement the vCard with the information
* @return * @return a map of the value of the vCard.
*/ */
private Map<VCardField, String> collectVCardValues(Element vCardElement) { private Map<VCardField, String> collectVCardValues(Element vCardElement) {
...@@ -602,10 +663,10 @@ class ClearspaceVCardTranslator { ...@@ -602,10 +663,10 @@ class ClearspaceVCardTranslator {
/** /**
* Translates the information from Clearspace into a VCard. * Translates the information from Clearspace into a VCard.
* *
* @param profile * @param profile the profile
* @param user * @param user the user
* @param avatar * @param avatar the avatar
* @return * @return the vCard with the information
*/ */
protected Element translateClearspaceInfo(Element profile, User user, Element avatar) { protected Element translateClearspaceInfo(Element profile, User user, Element avatar) {
...@@ -619,7 +680,12 @@ class ClearspaceVCardTranslator { ...@@ -619,7 +680,12 @@ class ClearspaceVCardTranslator {
return vCard; return vCard;
} }
/**
* Translates the profile information to the vCard
*
* @param profiles the profile information
* @param vCard the vCard to add the information to
*/
private void translateProfileInformation(Element profiles, Element vCard) { private void translateProfileInformation(Element profiles, Element vCard) {
// Translate the profile XML // Translate the profile XML
...@@ -747,15 +813,21 @@ class ClearspaceVCardTranslator { ...@@ -747,15 +813,21 @@ class ClearspaceVCardTranslator {
} }
} }
/**
* Translates the user information to the vCard
*
* @param user the user information
* @param vCard the vCard to add the information to
*/
private void translateUserInformation(User user, Element vCard) { private void translateUserInformation(User user, Element vCard) {
// The name could be null (if in Clearspace the name is not visible in Openfire it is null) // Only set the name to the VCard if it is visible
if (user.getName() != null && !"".equals(user.getName().trim())) { if (user.isNameVisible()) {
vCard.addElement("FN").setText(user.getName()); vCard.addElement("FN").setText(user.getName());
vCard.addElement("N").addElement("FAMILY").setText(user.getName()); vCard.addElement("N").addElement("FAMILY").setText(user.getName());
} }
// Email is mandatory, but may be invisible // Only set the eamail to the VCard if it is visible
if (user.getEmail() != null && !"".equals(user.getName().trim())) { if (user.isEmailVisible()) {
Element email = vCard.addElement("EMAIL"); Element email = vCard.addElement("EMAIL");
email.addElement("PREF"); email.addElement("PREF");
email.addElement("USERID").setText(user.getEmail()); email.addElement("USERID").setText(user.getEmail());
...@@ -765,6 +837,12 @@ class ClearspaceVCardTranslator { ...@@ -765,6 +837,12 @@ class ClearspaceVCardTranslator {
vCard.addElement("JABBERID").setText(jid); vCard.addElement("JABBERID").setText(jid);
} }
/**
* Translates the avatar information to the vCard.
*
* @param avatarResponse the avatar information
* @param vCard the vCard to add the information to
*/
private void translateAvatarInformation(Element avatarResponse, Element vCard) { private void translateAvatarInformation(Element avatarResponse, Element vCard) {
Element avatar = avatarResponse.element("return"); Element avatar = avatarResponse.element("return");
if (avatar != null) { if (avatar != null) {
...@@ -781,6 +859,12 @@ class ClearspaceVCardTranslator { ...@@ -781,6 +859,12 @@ class ClearspaceVCardTranslator {
} }
} }
/**
* Translates the address string of Clearspace to the vCard format.
*
* @param address the address string of Clearspae
* @param addressE the address element to add the address to
*/
private void translateAddress(String address, Element addressE) { private void translateAddress(String address, Element addressE) {
StringTokenizer strTokenize = new StringTokenizer(address, ","); StringTokenizer strTokenize = new StringTokenizer(address, ",");
while (strTokenize.hasMoreTokens()) { while (strTokenize.hasMoreTokens()) {
...@@ -819,6 +903,12 @@ class ClearspaceVCardTranslator { ...@@ -819,6 +903,12 @@ class ClearspaceVCardTranslator {
} }
/**
* Translates the address form the vCard format to the Clearspace string.
*
* @param addressElement the address in the vCard format
* @return the address int the Clearspace format
*/
private String translateAddress(Element addressElement) { private String translateAddress(Element addressElement) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
...@@ -850,8 +940,16 @@ class ClearspaceVCardTranslator { ...@@ -850,8 +940,16 @@ class ClearspaceVCardTranslator {
return sb.toString(); return sb.toString();
} }
private void translateAddressField(Element addressElement, String elementName, String fieldName, StringBuilder sb) { /**
String field = addressElement.elementTextTrim(elementName); * Translates the address field from the vCard format to the Clearspace format.
*
* @param addressElement the vCard address
* @param vCardFieldName the vCard field name
* @param fieldName the Clearspace field name
* @param sb the string builder to append the field string to
*/
private void translateAddressField(Element addressElement, String vCardFieldName, String fieldName, StringBuilder sb) {
String field = addressElement.elementTextTrim(vCardFieldName);
if (field != null && !"".equals(field)) { if (field != null && !"".equals(field)) {
sb.append(fieldName).append(":").append(field).append(","); sb.append(fieldName).append(":").append(field).append(",");
} }
......
...@@ -57,13 +57,18 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -57,13 +57,18 @@ public class User implements Cacheable, Externalizable, Result {
private static final String INSERT_PROPERTY = private static final String INSERT_PROPERTY =
"INSERT INTO jiveUserProp (username, name, propValue) VALUES (?, ?, ?)"; "INSERT INTO jiveUserProp (username, name, propValue) VALUES (?, ?, ?)";
// The name of the name visible property
private static final String NAME_VISIBLE_PROPERTY = "name.visible";
// The name of the email visible property
private static final String EMAIL_VISIBLE_PROPERTY = "email.visible";
private String username; private String username;
private String name; private String name;
private String email; private String email;
private Date creationDate; private Date creationDate;
private Date modificationDate; private Date modificationDate;
private Map<String,String> properties = null; private Map<String, String> properties = null;
/** /**
* Returns the value of the specified property for the given username. This method is * Returns the value of the specified property for the given username. This method is
...@@ -92,10 +97,18 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -92,10 +97,18 @@ public class User implements Cacheable, Externalizable, Result {
Log.error(sqle); Log.error(sqle);
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try {
catch (Exception e) { Log.error(e); } if (pstmt != null) pstmt.close();
try { if (con != null) con.close(); } }
catch (Exception e) { Log.error(e); } catch (Exception e) {
Log.error(e);
}
try {
if (con != null) con.close();
}
catch (Exception e) {
Log.error(e);
}
} }
return propertyValue; return propertyValue;
} }
...@@ -120,8 +133,7 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -120,8 +133,7 @@ public class User implements Cacheable, Externalizable, Result {
* @param modificationDate the date the user was last modified. * @param modificationDate the date the user was last modified.
*/ */
public User(String username, String name, String email, Date creationDate, public User(String username, String name, String email, Date creationDate,
Date modificationDate) Date modificationDate) {
{
if (username == null) { if (username == null) {
throw new NullPointerException("Username cannot be null"); throw new NullPointerException("Username cannot be null");
} }
...@@ -162,7 +174,7 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -162,7 +174,7 @@ public class User implements Cacheable, Externalizable, Result {
AuthFactory.getAuthProvider().setPassword(username, password); AuthFactory.getAuthProvider().setPassword(username, password);
// Fire event. // Fire event.
Map<String,Object> params = new HashMap<String,Object>(); Map<String, Object> params = new HashMap<String, Object>();
params.put("type", "passwordModified"); params.put("type", "passwordModified");
UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified, UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified,
params); params);
...@@ -194,7 +206,7 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -194,7 +206,7 @@ public class User implements Cacheable, Externalizable, Result {
this.name = name; this.name = name;
// Fire event. // Fire event.
Map<String,Object> params = new HashMap<String,Object>(); Map<String, Object> params = new HashMap<String, Object>();
params.put("type", "nameModified"); params.put("type", "nameModified");
params.put("originalValue", originalName); params.put("originalValue", originalName);
UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified, UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified,
...@@ -205,6 +217,24 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -205,6 +217,24 @@ public class User implements Cacheable, Externalizable, Result {
} }
} }
/**
* Returns true if name is visible to everyone or not.
*
* @return true if name is visible to everyone, false if not.
*/
public boolean isNameVisible() {
return !getProperties().containsKey(NAME_VISIBLE_PROPERTY) || Boolean.valueOf(getProperties().get(NAME_VISIBLE_PROPERTY));
}
/**
* Sets if name is visible to everyone or not.
*
* @param visible true if name is visible, false if not.
*/
public void setNameVisible(boolean visible) {
getProperties().put(NAME_VISIBLE_PROPERTY, String.valueOf(visible));
}
/** /**
* Returns the email address of the user or <tt>null</tt> if none is defined. * Returns the email address of the user or <tt>null</tt> if none is defined.
* *
...@@ -224,11 +254,11 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -224,11 +254,11 @@ public class User implements Cacheable, Externalizable, Result {
} }
try { try {
String originalEmail= this.email; String originalEmail = this.email;
UserManager.getUserProvider().setEmail(username, email); UserManager.getUserProvider().setEmail(username, email);
this.email = email; this.email = email;
// Fire event. // Fire event.
Map<String,Object> params = new HashMap<String,Object>(); Map<String, Object> params = new HashMap<String, Object>();
params.put("type", "emailModified"); params.put("type", "emailModified");
params.put("originalValue", originalEmail); params.put("originalValue", originalEmail);
UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified, UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified,
...@@ -239,6 +269,24 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -239,6 +269,24 @@ public class User implements Cacheable, Externalizable, Result {
} }
} }
/**
* Returns true if email is visible to everyone or not.
*
* @return true if email is visible to everyone, false if not.
*/
public boolean isEmailVisible() {
return !getProperties().containsKey(EMAIL_VISIBLE_PROPERTY) || Boolean.valueOf(getProperties().get(EMAIL_VISIBLE_PROPERTY));
}
/**
* Sets if the email is visible to everyone or not.
*
* @param visible true if the email is visible, false if not.
*/
public void setEmailVisible(boolean visible) {
getProperties().put(EMAIL_VISIBLE_PROPERTY, String.valueOf(visible));
}
public Date getCreationDate() { public Date getCreationDate() {
return creationDate; return creationDate;
} }
...@@ -254,7 +302,7 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -254,7 +302,7 @@ public class User implements Cacheable, Externalizable, Result {
this.creationDate = creationDate; this.creationDate = creationDate;
// Fire event. // Fire event.
Map<String,Object> params = new HashMap<String,Object>(); Map<String, Object> params = new HashMap<String, Object>();
params.put("type", "creationDateModified"); params.put("type", "creationDateModified");
params.put("originalValue", originalCreationDate); params.put("originalValue", originalCreationDate);
UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified, UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified,
...@@ -280,7 +328,7 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -280,7 +328,7 @@ public class User implements Cacheable, Externalizable, Result {
this.modificationDate = modificationDate; this.modificationDate = modificationDate;
// Fire event. // Fire event.
Map<String,Object> params = new HashMap<String,Object>(); Map<String, Object> params = new HashMap<String, Object>();
params.put("type", "nameModified"); params.put("type", "nameModified");
params.put("originalValue", originalModificationDate); params.put("originalValue", originalModificationDate);
UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified, UserEventDispatcher.dispatchEvent(this, UserEventDispatcher.EventType.user_modified,
...@@ -298,7 +346,7 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -298,7 +346,7 @@ public class User implements Cacheable, Externalizable, Result {
* *
* @return the extended properties. * @return the extended properties.
*/ */
public Map<String,String> getProperties() { public Map<String, String> getProperties() {
synchronized (this) { synchronized (this) {
if (properties == null) { if (properties == null) {
properties = new ConcurrentHashMap<String, String>(); properties = new ConcurrentHashMap<String, String>();
...@@ -352,9 +400,8 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -352,9 +400,8 @@ public class User implements Cacheable, Externalizable, Result {
return true; return true;
} }
if (object != null && object instanceof User) { if (object != null && object instanceof User) {
return username.equals(((User)object).getUsername()); return username.equals(((User) object).getUsername());
} } else {
else {
return false; return false;
} }
} }
...@@ -365,22 +412,21 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -365,22 +412,21 @@ public class User implements Cacheable, Externalizable, Result {
private class PropertiesMap extends AbstractMap { private class PropertiesMap extends AbstractMap {
public Object put(Object key, Object value) { public Object put(Object key, Object value) {
Map<String,Object> eventParams = new HashMap<String,Object>(); Map<String, Object> eventParams = new HashMap<String, Object>();
Object answer; Object answer;
String keyString = (String) key; String keyString = (String) key;
synchronized (keyString.intern()) { synchronized (keyString.intern()) {
if (properties.containsKey(keyString)) { if (properties.containsKey(keyString)) {
String originalValue = properties.get(keyString); String originalValue = properties.get(keyString);
answer = properties.put(keyString, (String)value); answer = properties.put(keyString, (String) value);
updateProperty(keyString, (String)value); updateProperty(keyString, (String) value);
// Configure event. // Configure event.
eventParams.put("type", "propertyModified"); eventParams.put("type", "propertyModified");
eventParams.put("propertyKey", key); eventParams.put("propertyKey", key);
eventParams.put("originalValue", originalValue); eventParams.put("originalValue", originalValue);
} } else {
else { answer = properties.put(keyString, (String) value);
answer = properties.put(keyString, (String)value); insertProperty(keyString, (String) value);
insertProperty(keyString, (String)value);
// Configure event. // Configure event.
eventParams.put("type", "propertyAdded"); eventParams.put("type", "propertyAdded");
eventParams.put("propertyKey", key); eventParams.put("propertyKey", key);
...@@ -417,7 +463,7 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -417,7 +463,7 @@ public class User implements Cacheable, Externalizable, Result {
} }
public Object next() { public Object next() {
current = (Map.Entry)iter.next(); current = (Map.Entry) iter.next();
return current; return current;
} }
...@@ -425,11 +471,11 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -425,11 +471,11 @@ public class User implements Cacheable, Externalizable, Result {
if (current == null) { if (current == null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
String key = (String)current.getKey(); String key = (String) current.getKey();
deleteProperty(key); deleteProperty(key);
iter.remove(); iter.remove();
// Fire event. // Fire event.
Map<String,Object> params = new HashMap<String,Object>(); Map<String, Object> params = new HashMap<String, Object>();
params.put("type", "propertyDeleted"); params.put("type", "propertyDeleted");
params.put("propertyKey", key); params.put("propertyKey", key);
UserEventDispatcher.dispatchEvent(User.this, UserEventDispatcher.dispatchEvent(User.this,
...@@ -456,10 +502,18 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -456,10 +502,18 @@ public class User implements Cacheable, Externalizable, Result {
Log.error(sqle); Log.error(sqle);
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try {
catch (Exception e) { Log.error(e); } if (pstmt != null) pstmt.close();
try { if (con != null) con.close(); } }
catch (Exception e) { Log.error(e); } catch (Exception e) {
Log.error(e);
}
try {
if (con != null) con.close();
}
catch (Exception e) {
Log.error(e);
}
} }
} }
...@@ -478,10 +532,18 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -478,10 +532,18 @@ public class User implements Cacheable, Externalizable, Result {
Log.error(e); Log.error(e);
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try {
catch (Exception e) { Log.error(e); } if (pstmt != null) pstmt.close();
try { if (con != null) con.close(); } }
catch (Exception e) { Log.error(e); } catch (Exception e) {
Log.error(e);
}
try {
if (con != null) con.close();
}
catch (Exception e) {
Log.error(e);
}
} }
} }
...@@ -500,10 +562,18 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -500,10 +562,18 @@ public class User implements Cacheable, Externalizable, Result {
Log.error(e); Log.error(e);
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try {
catch (Exception e) { Log.error(e); } if (pstmt != null) pstmt.close();
try { if (con != null) con.close(); } }
catch (Exception e) { Log.error(e); } catch (Exception e) {
Log.error(e);
}
try {
if (con != null) con.close();
}
catch (Exception e) {
Log.error(e);
}
} }
} }
...@@ -521,10 +591,18 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -521,10 +591,18 @@ public class User implements Cacheable, Externalizable, Result {
Log.error(e); Log.error(e);
} }
finally { finally {
try { if (pstmt != null) pstmt.close(); } try {
catch (Exception e) { Log.error(e); } if (pstmt != null) pstmt.close();
try { if (con != null) con.close(); } }
catch (Exception e) { Log.error(e); } catch (Exception e) {
Log.error(e);
}
try {
if (con != null) con.close();
}
catch (Exception e) {
Log.error(e);
}
} }
} }
...@@ -553,8 +631,7 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -553,8 +631,7 @@ public class User implements Cacheable, Externalizable, Result {
* (non-Javadoc) * (non-Javadoc)
* @see org.jivesoftware.util.resultsetmanager.Result#getUID() * @see org.jivesoftware.util.resultsetmanager.Result#getUID()
*/ */
public String getUID() public String getUID() {
{
return username; return username;
} }
} }
...@@ -95,9 +95,8 @@ public class UserNameManager { ...@@ -95,9 +95,8 @@ public class UserNameManager {
if (server.isLocal(entity)) { if (server.isLocal(entity)) {
// Contact is a local entity so search for his user name // Contact is a local entity so search for his user name
User localUser = UserManager.getInstance().getUser(entity.getNode()); User localUser = UserManager.getInstance().getUser(entity.getNode());
return "".equals(localUser.getName()) ? entity.getNode() : localUser.getName(); return !localUser.isNameVisible() || "".equals(localUser.getName()) ? entity.getNode() : localUser.getName();
} } else {
else {
UserNameProvider provider = providersByDomain.get(entity.getDomain()); UserNameProvider provider = providersByDomain.get(entity.getDomain());
if (provider != null) { if (provider != null) {
return provider.getUserName(entity); return provider.getUserName(entity);
......
...@@ -43,7 +43,7 @@ import java.util.Map.Entry; ...@@ -43,7 +43,7 @@ import java.util.Map.Entry;
/** /**
* Provides support for Jabber Search * Provides support for Jabber Search
* (<a href="http://www.xmpp.org/extensions/xep-0055.html">XEP-0055</a>).<p> * (<a href="http://www.xmpp.org/extensions/xep-0055.html">XEP-0055</a>).<p>
* * <p/>
* The basic functionality is to query an information repository * The basic functionality is to query an information repository
* regarding the possible search fields, to send a search query, * regarding the possible search fields, to send a search query,
* and to receive search results. This implementation was primarily designed to use * and to receive search results. This implementation was primarily designed to use
...@@ -76,6 +76,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -76,6 +76,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* A list of field names that are valid in jabber:iq:search * A list of field names that are valid in jabber:iq:search
*/ */
public final static Collection<String> validSearchRequestFields = new ArrayList<String>(); public final static Collection<String> validSearchRequestFields = new ArrayList<String>();
static { static {
validSearchRequestFields.add("first"); validSearchRequestFields.add("first");
validSearchRequestFields.add("last"); validSearchRequestFields.add("last");
...@@ -229,8 +230,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -229,8 +230,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* that <strong>all</strong> IQ request stanza's (type 'get' or 'set') MUST * that <strong>all</strong> IQ request stanza's (type 'get' or 'set') MUST
* be replied to. * be replied to.
* *
* @param iq * @param iq The IQ stanza that forms the request.
* The IQ stanza that forms the request.
* @return The response to the request. * @return The response to the request.
*/ */
private IQ handleIQRequest(IQ iq) { private IQ handleIQRequest(IQ iq) {
...@@ -284,8 +284,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -284,8 +284,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
/** /**
* Creates a response specific to the search plugin to Disco#Info requests. * Creates a response specific to the search plugin to Disco#Info requests.
* *
* @param iq * @param iq The IQ stanza that contains the request.
* The IQ stanza that contains the request.
* @return An IQ stanza, formulated as an answer to the received request. * @return An IQ stanza, formulated as an answer to the received request.
*/ */
private static IQ handleDiscoInfo(IQ iq) { private static IQ handleDiscoInfo(IQ iq) {
...@@ -340,8 +339,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -340,8 +339,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* provided as an argument. The stanza tells the recipient that this service * provided as an argument. The stanza tells the recipient that this service
* is currently unavailable. * is currently unavailable.
* *
* @param packet * @param packet The request IQ stanza to which a result will be returned.
* The request IQ stanza to which a result will be returned.
* @return A result stanza, telling the user that this service is * @return A result stanza, telling the user that this service is
* unavailable. * unavailable.
*/ */
...@@ -363,8 +361,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -363,8 +361,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* Processes an IQ stanza of type 'get', which in the context of 'Jabber * Processes an IQ stanza of type 'get', which in the context of 'Jabber
* Search' is a request for available search fields. * Search' is a request for available search fields.
* *
* @param packet * @param packet An IQ stanza of type 'get'
* An IQ stanza of type 'get'
* @return A result IQ stanza that contains the possbile search fields. * @return A result IQ stanza that contains the possbile search fields.
*/ */
private IQ processGetPacket(IQ packet) { private IQ processGetPacket(IQ packet) {
...@@ -424,8 +421,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -424,8 +421,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* Processes an IQ stanza of type 'set', which in the context of 'Jabber * Processes an IQ stanza of type 'set', which in the context of 'Jabber
* Search' is a search request. * Search' is a search request.
* *
* @param packet * @param packet An IQ stanza of type 'get'
* An IQ stanza of type 'get'
* @return A result IQ stanza that contains the possbile search fields. * @return A result IQ stanza that contains the possbile search fields.
*/ */
private IQ processSetPacket(IQ packet) { private IQ processSetPacket(IQ packet) {
...@@ -497,8 +493,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -497,8 +493,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* <li>if the stanza child element is has valid children itself.</li> * <li>if the stanza child element is has valid children itself.</li>
* </ul> * </ul>
* *
* @param iq * @param iq The IQ object that should include a jabber:iq:search request.
* The IQ object that should include a jabber:iq:search request.
* @return ''true'' if the supplied IQ stanza is a spec compliant search * @return ''true'' if the supplied IQ stanza is a spec compliant search
* request, ''false'' otherwise. * request, ''false'' otherwise.
*/ */
...@@ -553,8 +548,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -553,8 +548,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
/** /**
* Performs a search based on form data, and returns the search results. * Performs a search based on form data, and returns the search results.
* *
* @param incomingForm * @param incomingForm The form containing the search data
* The form containing the search data
* @return A set of users that matches the search criteria. * @return A set of users that matches the search criteria.
*/ */
private Set<User> performSearch(Element incomingForm) { private Set<User> performSearch(Element incomingForm) {
...@@ -593,7 +587,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -593,7 +587,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* defined as a set of key->value pairs, where the key denotes a search * defined as a set of key->value pairs, where the key denotes a search
* field, and the value contains the value that was filled out by the user * field, and the value contains the value that was filled out by the user
* for that field. * for that field.
* * <p/>
* The query can be specified in one of two ways. The first way is a query * The query can be specified in one of two ways. The first way is a query
* is formed is by filling out any of the the standard search fields. The * is formed is by filling out any of the the standard search fields. The
* other search method makes use of extended data forms. Search queries that * other search method makes use of extended data forms. Search queries that
...@@ -601,8 +595,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -601,8 +595,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* of this last method get forwarded to * of this last method get forwarded to
* {@link #extractExtendedSearchQuery(Element)}. * {@link #extractExtendedSearchQuery(Element)}.
* *
* @param incomingForm * @param incomingForm The form from which to extract the query
* The form from which to extract the query
* @return The search query for a particular user search request. * @return The search query for a particular user search request.
*/ */
private Hashtable<String, String> extractSearchQuery(Element incomingForm) { private Hashtable<String, String> extractSearchQuery(Element incomingForm) {
...@@ -637,8 +630,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -637,8 +630,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* specify the search request. This 'extended' way of constructing a search * specify the search request. This 'extended' way of constructing a search
* request is documented in XEP-0055, chapter 3. * request is documented in XEP-0055, chapter 3.
* *
* @param incomingForm * @param incomingForm The form from which to extract the query
* The form from which to extract the query
* @return The search query for a particular user search request. * @return The search query for a particular user search request.
* @see #extractSearchQuery(Element) * @see #extractSearchQuery(Element)
*/ */
...@@ -713,11 +705,11 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -713,11 +705,11 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
items.add(fieldUsername); items.add(fieldUsername);
XFormFieldImpl fieldName = new XFormFieldImpl(LocaleUtils.getLocalizedString("advance.user.search.name", "search")); XFormFieldImpl fieldName = new XFormFieldImpl(LocaleUtils.getLocalizedString("advance.user.search.name", "search"));
fieldName.addValue(removeNull(user.getName())); fieldName.addValue((user.isNameVisible() ? removeNull(user.getName()) : ""));
items.add(fieldName); items.add(fieldName);
XFormFieldImpl fieldEmail = new XFormFieldImpl(LocaleUtils.getLocalizedString("advance.user.search.email", "search")); XFormFieldImpl fieldEmail = new XFormFieldImpl(LocaleUtils.getLocalizedString("advance.user.search.email", "search"));
fieldEmail.addValue(removeNull(user.getEmail())); fieldEmail.addValue((user.isEmailVisible() ? removeNull(user.getEmail()) : ""));
items.add(fieldEmail); items.add(fieldEmail);
searchResults.addItemFields(items); searchResults.addItemFields(items);
...@@ -759,13 +751,13 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -759,13 +751,13 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
if ("Name".equals(field)) { if ("Name".equals(field)) {
Element element = item.addElement(reverseFieldLookup Element element = item.addElement(reverseFieldLookup
.get(field)); .get(field));
element.addText(removeNull(user.getName())); element.addText(user.isNameVisible() ? removeNull(user.getName()) : "");
} }
if ("Email".equals(field)) { if ("Email".equals(field)) {
Element element = item.addElement(reverseFieldLookup Element element = item.addElement(reverseFieldLookup
.get(field)); .get(field));
element.addText(removeNull(user.getEmail())); element.addText(user.isEmailVisible() ? removeNull(user.getEmail()) : "");
} }
} }
} }
...@@ -859,13 +851,11 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -859,13 +851,11 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
*/ */
public void propertySet(String property, Map<String, Object> params) { public void propertySet(String property, Map<String, Object> params) {
if (property.equals(SERVICEENABLED)) { if (property.equals(SERVICEENABLED)) {
this.serviceEnabled = Boolean.parseBoolean((String)params.get("value")); this.serviceEnabled = Boolean.parseBoolean((String) params.get("value"));
} } else if (property.equals(SERVICENAME)) {
else if (property.equals(SERVICENAME)) { changeServiceName((String) params.get("value"));
changeServiceName((String)params.get("value")); } else if (property.equals(EXCLUDEDFIELDS)) {
} exculudedFields = StringUtils.stringToCollection(JiveGlobals.getProperty(EXCLUDEDFIELDS, (String) params.get("value")));
else if (property.equals(EXCLUDEDFIELDS)) {
exculudedFields = StringUtils.stringToCollection(JiveGlobals.getProperty(EXCLUDEDFIELDS, (String)params.get("value")));
} }
} }
...@@ -878,11 +868,9 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -878,11 +868,9 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
public void propertyDeleted(String property, Map<String, Object> params) { public void propertyDeleted(String property, Map<String, Object> params) {
if (property.equals(SERVICEENABLED)) { if (property.equals(SERVICEENABLED)) {
this.serviceEnabled = true; this.serviceEnabled = true;
} } else if (property.equals(SERVICENAME)) {
else if (property.equals(SERVICENAME)) {
changeServiceName("search"); changeServiceName("search");
} } else if (property.equals(EXCLUDEDFIELDS)) {
else if (property.equals(EXCLUDEDFIELDS)) {
exculudedFields = new ArrayList<String>(); exculudedFields = new ArrayList<String>();
} }
} }
...@@ -947,8 +935,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -947,8 +935,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* Returns the trimmed argument, or an empty String object of null was * Returns the trimmed argument, or an empty String object of null was
* supplied as an argument. * supplied as an argument.
* *
* @param s * @param s The String to be trimmed.
* The String to be trimmed.
* @return String object that does not start or end with whitespace * @return String object that does not start or end with whitespace
* characters. * characters.
*/ */
...@@ -976,7 +963,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -976,7 +963,7 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
* field name of "email" and query of "jsmith@example.com" would search for * field name of "email" and query of "jsmith@example.com" would search for
* the user with that email address. Wildcard (*) characters are allowed as * the user with that email address. Wildcard (*) characters are allowed as
* part of queries. * part of queries.
* * <p/>
* A possible future improvement would be to have a third parameter that * A possible future improvement would be to have a third parameter that
* sets the maximum number of users returned and/or the number of users * sets the maximum number of users returned and/or the number of users
* that are searched. * that are searched.
...@@ -1004,33 +991,30 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -1004,33 +991,30 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
catch (UserNotFoundException e) { catch (UserNotFoundException e) {
Log.error("Error getting user", e); Log.error("Error getting user", e);
} }
} } else if (field.equals("Name")) {
else if (field.equals("Name")) { if (user.isNameVisible()) {
if (query.equalsIgnoreCase(user.getName())) { if (query.equalsIgnoreCase(user.getName())) {
foundUsers.add(user); foundUsers.add(user);
} }
} }
else if (field.equals("Email")) { } else if (field.equals("Email")) {
if (user.getEmail() != null) { if (user.isEmailVisible() && user.getEmail() != null) {
if (query.equalsIgnoreCase(user.getEmail())) { if (query.equalsIgnoreCase(user.getEmail())) {
foundUsers.add(user); foundUsers.add(user);
} }
} }
} }
} }
} } else {
else {
String prefix = query.substring(0, index); String prefix = query.substring(0, index);
Collection<User> users = userManager.getUsers(); Collection<User> users = userManager.getUsers();
for (User user : users) { for (User user : users) {
String userInfo = ""; String userInfo = "";
if (field.equals("Username")) { if (field.equals("Username")) {
userInfo = user.getUsername(); userInfo = user.getUsername();
} } else if (field.equals("Name")) {
else if (field.equals("Name")) {
userInfo = user.getName(); userInfo = user.getName();
} } else if (field.equals("Email")) {
else if (field.equals("Email")) {
userInfo = user.getEmail() == null ? "" : user.getEmail(); userInfo = user.getEmail() == null ? "" : user.getEmail();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment