Merged V3.1 to HEAD

13249: Fix for ETHREEOH-1064 and ETHREEOH-1286 and fix for issue where New Page action not activated in Share Wiki page list.
   13251: Final part of fix for ETHREEOH-1270 - Group pickers in JSF client now use new findAuthorities() API to find groups for user searches - over 10x quicker for installations with many groups.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13580 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2009-03-11 19:51:09 +00:00
parent 1aa1ef1f13
commit a94f5f0bff
9 changed files with 130 additions and 60 deletions

View File

@@ -306,6 +306,7 @@ upload_new_version=Upload new version
checkin_this_file=Check in this file
cannot_delete_node_has_working_copy=Cannot delete file \"{0}\" as it has an associated working copy.
unknown=Unknown
picker_search_min=Please enter at least {0} characters to perform a search.
# Properties
username=User Name

View File

@@ -111,6 +111,9 @@
<!-- Allow Users to modify their personal settings in the User Console screen - you may wish to -->
<!-- disable this if your admin does not wish to allow users to edit their own details -->
<allow-user-config>true</allow-user-config>
<!-- the minimum number of characters required for a valid search in the pickers -->
<picker-search-minimum>2</picker-search-minimum>
</client>
</config>

View File

@@ -46,7 +46,6 @@ import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.groups.GroupsDialog.UserAuthorityDetails;
@@ -213,13 +212,7 @@ public class AddUsersDialog extends BaseDialogBean
// Use lucene search to retrieve user details
String term = QueryParser.escape(contains.trim());
StringBuilder query = new StringBuilder(128);
query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:");
query.append(term);
query.append("*");
Utils.generatePersonSearch(query, term);
List<NodeRef> nodes;
ResultSet resultSet = Repository.getServiceRegistry(context).getSearchService().query(
Repository.getStoreRef(),

View File

@@ -39,7 +39,6 @@ import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.SortableSelectItem;
@@ -55,7 +54,6 @@ import org.apache.commons.logging.LogFactory;
*/
public class SetPermissionsDialog extends UpdatePermissionsDialog
{
private static final long serialVersionUID = -8139619811033232880L;
/** logger */
@@ -251,13 +249,7 @@ public class SetPermissionsDialog extends UpdatePermissionsDialog
// Use lucene search to retrieve user details
String term = QueryParser.escape(contains.trim());
StringBuilder query = new StringBuilder(128);
query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:");
query.append(term);
query.append("*");
Utils.generatePersonSearch(query, term);
ResultSet resultSet = Repository.getServiceRegistry(context).getSearchService().query(Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString());
List<NodeRef> nodes;
try
@@ -284,18 +276,23 @@ public class SetPermissionsDialog extends UpdatePermissionsDialog
}
else
{
// groups - simple text based match on name
Set<String> groups = getAuthorityService().getAllAuthorities(AuthorityType.GROUP);
// groups - text search match on supplied name
String term = PermissionService.GROUP_PREFIX + "*" + contains.trim() + "*";
Set<String> groups;
groups = getAuthorityService().findAuthorities(AuthorityType.GROUP, term);
groups.addAll(getAuthorityService().getAllAuthorities(AuthorityType.EVERYONE));
String containsLower = contains.trim().toLowerCase();
int offset = PermissionService.GROUP_PREFIX.length();
String groupDisplayName;
for (String group : groups)
{
if (group.toLowerCase().indexOf(containsLower, offset) != -1)
// get display name, if not present strip prefix from group id
groupDisplayName = getAuthorityService().getAuthorityDisplayName(group);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
results.add(new SortableSelectItem(group, group.substring(offset), group));
groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length());
}
results.add(new SortableSelectItem(group, groupDisplayName, groupDisplayName));
}
}

View File

@@ -35,6 +35,7 @@ import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.component.UISelectOne;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
@@ -86,6 +87,7 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
private static final String MSG_INVITED_TO = "invited_to";
private static final String MSG_INVITED_ROLE = "invite_role";
private static final String MSG_MAX_USERS = "max_users_returned";
private static final String MSG_SEARCH_MINIMUM = "picker_search_min";
protected static final String STEP_NOTIFY = "notify";
@@ -365,6 +367,15 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
{
FacesContext context = FacesContext.getCurrentInstance();
// quick exit if not enough characters entered for a search
String search = contains.trim();
int searchMin = Application.getClientConfig(context).getPickerSearchMinimum();
if (search.length() < searchMin)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(context, MSG_SEARCH_MINIMUM), searchMin));
return new SelectItem[0];
}
SelectItem[] items;
this.maxUsersReturned = false;
@@ -374,12 +385,14 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
tx = Repository.getUserTransaction(context, true);
tx.begin();
List<SelectItem> results = new ArrayList<SelectItem>();
int maxResults = Application.getClientConfig(context).getInviteUsersMaxResults();
List<SelectItem> results;
if (filterIndex == 0)
{
// Use lucene search to retrieve user details
String term = QueryParser.escape(contains.trim());
String term = QueryParser.escape(search);
StringBuilder query = new StringBuilder(128);
if (contains == null || contains.length() == 0)
{
@@ -390,17 +403,9 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
}
else
{
query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:");
query.append(term);
query.append("*");
Utils.generatePersonSearch(query, term);
}
int maxResults = Application.getClientConfig(context).getInviteUsersMaxResults();
if (logger.isDebugEnabled())
{
logger.debug("Maximum invite users results size: " + maxResults);
@@ -428,12 +433,7 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
resultSet.close();
}
// set the maximum users returned flag if appropriate
if (nodes.size() == maxResults)
{
this.maxUsersReturned = true;
}
results = new ArrayList<SelectItem>(nodes.size());
for (int index=0; index<nodes.size(); index++)
{
NodeRef personRef = nodes.get(index);
@@ -449,25 +449,28 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
}
else
{
// groups - simple text based match on name
Set<String> groups = getAuthorityService().getAllAuthorities(AuthorityType.GROUP);
// groups - text search match on supplied name
String term = PermissionService.GROUP_PREFIX + "*" + search + "*";
Set<String> groups;
groups = getAuthorityService().findAuthorities(AuthorityType.GROUP, term);
groups.addAll(getAuthorityService().getAllAuthorities(AuthorityType.EVERYONE));
String containsLower = contains.trim().toLowerCase();
results = new ArrayList<SelectItem>(groups.size());
int count = 0;
String groupDisplayName;
for (String group : groups)
{
// get display name, if not present strip prefix from group id
groupDisplayName = authorityService.getAuthorityDisplayName(group);
groupDisplayName = getAuthorityService().getAuthorityDisplayName(group);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length());
}
if (groupDisplayName.toLowerCase().indexOf(containsLower) != -1)
{
results.add(new SortableSelectItem(group, groupDisplayName, groupDisplayName));
}
if (++count == maxResults) break;
}
}
@@ -475,6 +478,12 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
results.toArray(items);
Arrays.sort(items);
// set the maximum users returned flag if appropriate
if (results.size() == maxResults)
{
this.maxUsersReturned = true;
}
// commit the transaction
tx.commit();
}

View File

@@ -37,12 +37,13 @@ import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.impl.lucene.QueryParser;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Repository;
@@ -57,6 +58,8 @@ import org.alfresco.web.ui.common.Utils;
*/
public abstract class BaseReassignDialog extends BaseDialogBean
{
private static final String MSG_SEARCH_MINIMUM = "picker_search_min";
transient private WorkflowService workflowService;
transient private PersonService personService;
@@ -125,6 +128,15 @@ public abstract class BaseReassignDialog extends BaseDialogBean
{
FacesContext context = FacesContext.getCurrentInstance();
// quick exit if not enough characters entered for a search
String search = contains.trim();
int searchMin = Application.getClientConfig(context).getPickerSearchMinimum();
if (search.length() < searchMin)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(context, MSG_SEARCH_MINIMUM), searchMin));
return new SelectItem[0];
}
SelectItem[] items;
UserTransaction tx = null;
@@ -134,18 +146,24 @@ public abstract class BaseReassignDialog extends BaseDialogBean
tx = Repository.getUserTransaction(context, true);
tx.begin();
int maxResults = Application.getClientConfig(context).getInviteUsersMaxResults();
// Use lucene search to retrieve user details
String term = QueryParser.escape(contains.trim());
StringBuilder query = new StringBuilder(128);
query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:");
query.append(term);
query.append("*");
resultSet = Repository.getServiceRegistry(context).getSearchService().query(
Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString());
Utils.generatePersonSearch(query, term);
SearchParameters searchParams = new SearchParameters();
searchParams.addStore(Repository.getStoreRef());
searchParams.setLanguage(SearchService.LANGUAGE_LUCENE);
searchParams.setQuery(query.toString());
if (maxResults > 0)
{
searchParams.setLimit(maxResults);
searchParams.setLimitBy(LimitBy.FINAL_SIZE);
}
resultSet = Repository.getServiceRegistry(context).getSearchService().query(searchParams);
List<NodeRef> nodes = resultSet.getNodeRefs();
ArrayList<SelectItem> itemList = new ArrayList<SelectItem>(nodes.size());

View File

@@ -85,6 +85,7 @@ public class ClientConfigElement extends ConfigElementAdapter
private boolean zeroByteFileUploads = true;
private boolean userGroupAdmin = true;
private boolean allowUserConfig = true;
private int pickerSearchMinimum = 2;
/**
@@ -281,6 +282,11 @@ public class ClientConfigElement extends ConfigElementAdapter
combinedElement.setUserGroupAdmin(newElement.isUserGroupAdmin());
}
if (newElement.getPickerSearchMinimum() != combinedElement.getPickerSearchMinimum())
{
combinedElement.setPickerSearchMinimum(newElement.getPickerSearchMinimum());
}
return combinedElement;
}
@@ -810,4 +816,20 @@ public class ClientConfigElement extends ConfigElementAdapter
{
this.allowUserConfig = allowUserConfig;
}
/**
* @return Returns the minimum number of characters for a picker search.
*/
public int getPickerSearchMinimum()
{
return this.pickerSearchMinimum;
}
/**
* @param searchMinimum The minimum number of characters for a picker search.
*/
/*package*/ void setPickerSearchMinimum(int searchMinimum)
{
this.pickerSearchMinimum = searchMinimum;
}
}

View File

@@ -70,6 +70,7 @@ public class ClientElementReader implements ConfigElementReader
public static final String ELEMENT_ZEROBYTEFILEUPLOADS = "zero-byte-file-uploads";
public static final String ELEMENT_USERGROUPADMIN = "user-group-admin";
public static final String ELEMENT_ALLOWUSERCONFIG = "allow-user-config";
public static final String ELEMENT_PICKERSEARCHMINIMUM = "picker-search-minimum";
/**
@@ -307,6 +308,13 @@ public class ClientElementReader implements ConfigElementReader
{
configElement.setAllowUserConfig(Boolean.parseBoolean(userConfig.getTextTrim()));
}
// get the minimum number of characters for valid picker search string
Element pickerSearchMin = element.element(ELEMENT_PICKERSEARCHMINIMUM);
if (pickerSearchMin != null)
{
configElement.setPickerSearchMinimum(Integer.parseInt(pickerSearchMin.getTextTrim()));
}
}
return configElement;

View File

@@ -67,6 +67,7 @@ import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NoTransformerException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.URLEncoder;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.DownloadContentServlet;
@@ -1051,4 +1052,22 @@ public final class Utils extends StringUtils
}
return userAgent;
}
/**
* Generate the Lucene query for a standard Person search. The query used is standardised
* across multiple JSF components and beans.
*
* @param query Buffer for the query
* @param term Search term
*/
public static void generatePersonSearch(StringBuilder query, String term)
{
query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:");
query.append(term);
query.append("*");
}
}