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

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

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

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@10022 b35dd754-fafc-0310-a699-88a17e54d16e
parent 5c9bed2d
...@@ -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) { if (readOnly == null) {
loadReadOnly(); synchronized (this) {
if (readOnly == null) {
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,20 +524,20 @@ public class ClearspaceUserProvider implements UserProvider { ...@@ -376,20 +524,20 @@ 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) {
tmpNode = userNode.selectSingleNode("name"); // Gets the name
if (tmpNode != null) { tmpNode = userNode.selectSingleNode("name");
name = tmpNode.getText(); if (tmpNode != null) {
} 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) {
tmpNode = userNode.selectSingleNode("email"); // Gets the email
if (tmpNode != null) { tmpNode = userNode.selectSingleNode("email");
email = tmpNode.getText(); if (tmpNode != null) {
} email = tmpNode.getText();
} }
// Gets the creation date // Gets the creation date
...@@ -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,6 +57,11 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -57,6 +57,11 @@ 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;
...@@ -205,6 +210,24 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -205,6 +210,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.
* *
...@@ -239,6 +262,24 @@ public class User implements Cacheable, Externalizable, Result { ...@@ -239,6 +262,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;
} }
......
...@@ -22,11 +22,11 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -22,11 +22,11 @@ import java.util.concurrent.ConcurrentHashMap;
* entities (i.e. users) the {@link User} name is used. For remote entities the following logic * entities (i.e. users) the {@link User} name is used. For remote entities the following logic
* is used: * is used:
* <ol> * <ol>
* <li>Check if a {@link UserNameProvider} is registered for the entity's domain. If a provider * <li>Check if a {@link UserNameProvider} is registered for the entity's domain. If a provider
* was found then use it to get the entity's name</li> * was found then use it to get the entity's name</li>
* <li>If no provider was found then retrieve the vCard of the entity and return the name as * <li>If no provider was found then retrieve the vCard of the entity and return the name as
* defined in the vCard. <i>This is not implemented yet.</i></li> * defined in the vCard. <i>This is not implemented yet.</i></li>
* <li>If no vCard was found then return the string representation of the entity's JID.</li> * <li>If no vCard was found then return the string representation of the entity's JID.</li>
* </ol> * </ol>
* *
* @author Gaston Dombiak * @author Gaston Dombiak
...@@ -72,7 +72,7 @@ public class UserNameManager { ...@@ -72,7 +72,7 @@ public class UserNameManager {
* @param entity the JID of the entity to get its name. * @param entity the JID of the entity to get its name.
* @return the name of the XMPP entity. * @return the name of the XMPP entity.
* @throws UserNotFoundException if the jid belongs to the local server but no user was * @throws UserNotFoundException if the jid belongs to the local server but no user was
* found for that jid. * found for that jid.
*/ */
public static String getUserName(JID entity) throws UserNotFoundException { public static String getUserName(JID entity) throws UserNotFoundException {
return getUserName(entity, entity.toString()); return getUserName(entity, entity.toString());
...@@ -85,19 +85,18 @@ public class UserNameManager { ...@@ -85,19 +85,18 @@ public class UserNameManager {
* the vCard of the entity might be requested and if none was found then a string * the vCard of the entity might be requested and if none was found then a string
* representation of the entity's JID will be returned. * representation of the entity's JID will be returned.
* *
* @param entity the JID of the entity to get its name. * @param entity the JID of the entity to get its name.
* @param defaultName default name to return when no name was found. * @param defaultName default name to return when no name was found.
* @return the name of the XMPP entity. * @return the name of the XMPP entity.
* @throws UserNotFoundException if the jid belongs to the local server but no user was * @throws UserNotFoundException if the jid belongs to the local server but no user was
* found for that jid. * found for that jid.
*/ */
public static String getUserName(JID entity, String defaultName) throws UserNotFoundException { public static String getUserName(JID entity, String defaultName) throws UserNotFoundException {
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);
......
...@@ -713,11 +713,11 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -713,11 +713,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 +759,13 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -759,13 +759,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()) : "");
} }
} }
} }
...@@ -1006,12 +1006,13 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener { ...@@ -1006,12 +1006,13 @@ public class SearchPlugin implements Component, Plugin, PropertyEventListener {
} }
} }
else if (field.equals("Name")) { else if (field.equals("Name")) {
if (query.equalsIgnoreCase(user.getName())) { if (user.isNameVisible()) {
foundUsers.add(user); if (query.equalsIgnoreCase(user.getName())) {
foundUsers.add(user);
}
} }
} } else if (field.equals("Email")) {
else if (field.equals("Email")) { if (user.isEmailVisible() && user.getEmail() != null) {
if (user.getEmail() != null) {
if (query.equalsIgnoreCase(user.getEmail())) { if (query.equalsIgnoreCase(user.getEmail())) {
foundUsers.add(user); foundUsers.add(user);
} }
......
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