Merged V3.2 to HEAD

19363: *RECORD ONLY* Fix for ALF-1952 - multi-pass HTML stripping
   19527: Fix for ALF-1037 - only documents modified by current user should be shown in My Documents dashlet filter
   19528: Fix for ALF-944 - list of users for Group admin in Explorer now only retrieves data required for values on display

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19529 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2010-03-24 12:15:41 +00:00
parent 6a19ab8088
commit 2fed36c870
4 changed files with 275 additions and 176 deletions

View File

@@ -36,6 +36,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application; import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.IContextListener; import org.alfresco.web.app.context.IContextListener;
import org.alfresco.web.app.context.UIContextService; import org.alfresco.web.app.context.UIContextService;
@@ -43,6 +44,7 @@ import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.dialog.ChangeViewSupport; import org.alfresco.web.bean.dialog.ChangeViewSupport;
import org.alfresco.web.bean.dialog.FilterViewSupport; import org.alfresco.web.bean.dialog.FilterViewSupport;
import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.data.DynamicResolver;
import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.IBreadcrumbHandler; import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
import org.alfresco.web.ui.common.component.UIActionLink; import org.alfresco.web.ui.common.component.UIActionLink;
@@ -333,191 +335,182 @@ public class GroupsDialog extends BaseDialogBean
return this.location; return this.location;
} }
/** /**
* @return true if user is in the root group * @return true if user is in the root group
*/ */
public boolean isAllowSearchGroups() public boolean isAllowSearchGroups()
{ {
return this.group == null; return this.group == null;
} }
/** /**
* @return The list of group objects to display. Returns the list of root groups or the list of sub-groups for the current group if set. * @return The list of group objects to display. Returns the list of root groups or the list of sub-groups for the current group if set.
*/ */
public List<Map<String,String>> getGroups() public List<Map<String,String>> getGroups()
{ {
if (this.group == null) if (this.group == null)
{ {
if (this.groups == null) if (this.groups == null)
{ {
searchGroups(); searchGroups();
} }
} }
else else
{ {
if (this.groups == null) if (this.groups == null)
{ {
showAllGroups(); showAllGroups();
} }
} }
return this.groups; return this.groups;
} }
/**
* @return Returns the groups search criteria
*/
public String getGroupsSearchCriteria()
{
return groupsSearchCriteria;
}
/** /**
* Event handler called when the user wishes to search for a group * @return Returns the groups search criteria
* */
* @return The outcome public String getGroupsSearchCriteria()
*/ {
public String searchGroups() return groupsSearchCriteria;
{ }
searchGroups(false);
// return null to stay on the same page
return null;
}
/** /**
* Action handler to show all the sub-groups in the group * Event handler called when the user wishes to search for a group
* *
* @return The outcome * @return The outcome
*/ */
public String showAllGroups() public String searchGroups()
{ {
searchGroups(true); searchGroups(false);
// return null to stay on the same page // return null to stay on the same page
return null; return null;
} }
/** /**
* Searches groups * Action handler to show all the sub-groups in the group
* *
* @param all if true searches all groups and doesn't take account of search term * @return The outcome
*/ */
private void searchGroups(boolean all) public String showAllGroups()
{ {
groupsRichList.setValue(null); searchGroups(true);
String search = null; // return null to stay on the same page
return null;
}
// Use the search criteria if we are not searching for everything /**
if (!all) * Searches groups
{ *
if (this.groupsSearchCriteria == null) * @param all if true searches all groups and doesn't take account of search term
{ */
search = null; private void searchGroups(boolean all)
{
groupsRichList.setValue(null);
String search = null;
// Use the search criteria if we are not searching for everything
if (!all)
{
if (this.groupsSearchCriteria == null)
{
search = null;
}
else
{
search = groupsSearchCriteria.trim();
if (search.length() == 0)
{
search = null;
} }
else else
{ {
search = groupsSearchCriteria.trim(); // Let's make it search on the short name/display name prefix
if (search.length() == 0) search = search + "*";
{
search = null;
}
else
{
// Let's make it search on the short name/display name prefix
search = search + "*";
}
} }
} }
}
if (!all && search == null)
{
// Do not allow empty searches
this.groups = Collections.<Map<String,String>> emptyList();
}
else
{
boolean immediate = (this.filterMode.equals(FILTER_CHILDREN));
Set<String> authorities = this.authService.findAuthorities(AuthorityType.GROUP, this.group, immediate, search, AuthorityService.ZONE_APP_DEFAULT);
groups = new ArrayList<Map<String,String>>(authorities.size());
for (String authority : authorities)
{
Map<String, String> authMap = new HashMap<String, String>(11);
if (!all && search == null) String name = this.authService.getAuthorityDisplayName(authority);
{ if (name == null)
// Do not allow empty searches
this.groups = Collections.<Map<String,String>> emptyList();
}
else
{
boolean immediate = (this.filterMode.equals(FILTER_CHILDREN));
Set<String> authorities = this.authService.findAuthorities(AuthorityType.GROUP, this.group, immediate, search, AuthorityService.ZONE_APP_DEFAULT);
groups = new ArrayList<Map<String,String>>(authorities.size());
for (String authority : authorities)
{ {
Map<String, String> authMap = new HashMap<String, String>(11); name = this.authService.getShortName(name);
String name = this.authService.getAuthorityDisplayName(authority);
if (name == null)
{
name = this.authService.getShortName(name);
}
authMap.put("name", name);
authMap.put("id", authority);
authMap.put("group", authority);
authMap.put("groupName", name);
groups.add(authMap);
} }
} authMap.put("name", name);
} authMap.put("id", authority);
authMap.put("group", authority);
authMap.put("groupName", name);
groups.add(authMap);
}
}
}
/** /**
* @return The list of user objects to display. Returns the list of user for the current group. * @return The list of user objects to display. Returns the list of user for the current group.
*/ */
public List<Map<String,String>> getUsers() public List<Map<String, Object>> getUsers()
{ {
List<Map<String,String>> users; List<Map<String, Object>> users;
UserTransaction tx = null; UserTransaction tx = null;
try try
{ {
FacesContext context = FacesContext.getCurrentInstance(); FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context, true); tx = Repository.getUserTransaction(context, true);
tx.begin(); tx.begin();
Set<String> authorities; Set<String> authorities;
if (this.group == null) if (this.group == null)
{ {
authorities = Collections.<String>emptySet(); authorities = Collections.<String>emptySet();
} }
else else
{ {
// users of an existing group // users of an existing group
boolean immediate = (this.filterMode.equals(FILTER_CHILDREN)); boolean immediate = (this.filterMode.equals(FILTER_CHILDREN));
authorities = this.getAuthorityService().getContainedAuthorities(AuthorityType.USER, this.group, immediate); authorities = this.getAuthorityService().getContainedAuthorities(AuthorityType.USER, this.group, immediate);
} }
users = new ArrayList<Map<String,String>>(authorities.size()); users = new ArrayList<Map<String, Object>>(authorities.size());
for (String authority : authorities) for (String authority : authorities)
{ {
Map<String, String> authMap = new HashMap<String, String>(5); final Map<String, Object> authMap = new HashMap<String, Object>(8);
String userName = this.getAuthorityService().getShortName(authority); final String userName = this.getAuthorityService().getShortName(authority);
authMap.put("userName", userName); authMap.put("userName", userName);
authMap.put("id", authority); authMap.put("id", authority);
authMap.put("name", new AuthorityNamePropertyResolver(userName));
// get Person details for this Authority authMap.put("firstName", new AuthorityPropertyResolver(userName, ContentModel.PROP_FIRSTNAME));
NodeRef ref = this.getPersonService().getPerson(authority); authMap.put("lastName", new AuthorityPropertyResolver(userName, ContentModel.PROP_LASTNAME));
String firstName = (String)this.getNodeService().getProperty(ref, ContentModel.PROP_FIRSTNAME);
String lastName = (String)this.getNodeService().getProperty(ref, ContentModel.PROP_LASTNAME); users.add(authMap);
}
// build a sensible label for display
StringBuilder label = new StringBuilder(48); // commit the transaction
label.append(firstName) tx.commit();
.append(' ') }
.append(lastName != null ? lastName : ""); catch (Throwable err)
authMap.put("name", label.toString()); {
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
users.add(authMap); FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
} users = Collections.<Map<String, Object>>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
// commit the transaction }
tx.commit();
} return users;
catch (Throwable err) }
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
users = Collections.<Map<String,String>>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
return users;
}
/** /**
* Set the current Group Authority. * Set the current Group Authority.
@@ -723,6 +716,7 @@ public class GroupsDialog extends BaseDialogBean
public String Label; public String Label;
} }
/** /**
* Simple wrapper bean exposing user authority and person details for JSF results list * Simple wrapper bean exposing user authority and person details for JSF results list
*/ */
@@ -749,4 +743,62 @@ public class GroupsDialog extends BaseDialogBean
private String name; private String name;
private String authority; private String authority;
} }
/**
* Simple dynamic resolver class to return authority properties at runtime
*/
public class AuthorityPropertyResolver implements DynamicResolver
{
final private String authority;
final private QName property;
private String value = null;
AuthorityPropertyResolver(String authority, QName property)
{
this.authority = authority;
this.property = property;
}
@Override
public String toString()
{
if (this.value == null)
{
NodeRef ref = getPersonService().getPerson(this.authority);
this.value = (String)getNodeService().getProperty(ref, this.property);
}
return this.value;
}
}
public class AuthorityNamePropertyResolver implements DynamicResolver
{
final private String authority;
private String value = null;
AuthorityNamePropertyResolver(String authority)
{
this.authority = authority;
}
@Override
public String toString()
{
if (this.value == null)
{
NodeRef ref = getPersonService().getPerson(this.authority);
String firstName = (String)getNodeService().getProperty(ref, ContentModel.PROP_FIRSTNAME);
String lastName = (String)getNodeService().getProperty(ref, ContentModel.PROP_LASTNAME);
// build a sensible label for display
StringBuilder label = new StringBuilder(48);
label.append(firstName != null ? firstName : "")
.append(' ')
.append(lastName != null ? lastName : "");
this.value = label.toString();
}
return this.value;
}
}
} }

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing
*/
package org.alfresco.web.data;
/**
* Interface marker used to indicate that a property is resolved at runtime
*
* @author Kevin Roast
*/
public interface DynamicResolver
{
}

View File

@@ -183,6 +183,10 @@ public abstract class Sort
{ {
this.comparator = new TimestampComparator(); this.comparator = new TimestampComparator();
} }
else if (DynamicResolver.class.isAssignableFrom(returnType))
{
this.comparator = new SimpleStringComparator();
}
else else
{ {
s_logger.warn("Unsupported sort data type: " + returnType + " defaulting to .toString()"); s_logger.warn("Unsupported sort data type: " + returnType + " defaulting to .toString()");

View File

@@ -131,7 +131,7 @@
<a:richList id="users-list" binding="#{DialogManager.bean.usersRichList}" viewMode="#{DialogManager.bean.viewMode}" pageSize="12" <a:richList id="users-list" binding="#{DialogManager.bean.usersRichList}" viewMode="#{DialogManager.bean.viewMode}" pageSize="12"
styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow" altRowStyleClass="recordSetRowAlt" width="100%" styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow" altRowStyleClass="recordSetRowAlt" width="100%"
value="#{DialogManager.bean.users}" var="r" initialSortColumn="name" initialSortDescending="true"> value="#{DialogManager.bean.users}" var="r" initialSortColumn="userName" initialSortDescending="true">
<%-- Primary column for icons view mode --%> <%-- Primary column for icons view mode --%>
<a:column primary="true" style="padding:2px;text-align:left;vertical-align:top;font-weight: bold;" rendered="#{DialogManager.bean.viewMode == 'icons'}"> <a:column primary="true" style="padding:2px;text-align:left;vertical-align:top;font-weight: bold;" rendered="#{DialogManager.bean.viewMode == 'icons'}">
@@ -144,12 +144,20 @@
<%-- Primary column for details view mode --%> <%-- Primary column for details view mode --%>
<a:column primary="true" style="padding:2px;text-align:left;" rendered="#{DialogManager.bean.viewMode == 'details'}"> <a:column primary="true" style="padding:2px;text-align:left;" rendered="#{DialogManager.bean.viewMode == 'details'}">
<f:facet name="small-icon"> <f:facet name="small-icon">
<h:graphicImage alt="#{r.name}" value="/images/icons/person.gif" /> <h:graphicImage alt="#{r.firstName}" value="/images/icons/person.gif" />
</f:facet> </f:facet>
<f:facet name="header"> <f:facet name="header">
<a:sortLink label="#{msg.name}" value="name" mode="case-insensitive" styleClass="header"/> <a:sortLink label="#{msg.first_name}" value="firstName" mode="case-insensitive" styleClass="header"/>
</f:facet> </f:facet>
<h:outputText value="#{r.name}" /> <h:outputText value="#{r.firstName}" />
</a:column>
<%-- Last name column --%>
<a:column width="120" style="text-align:left" rendered="#{DialogManager.bean.viewMode == 'details'}">
<f:facet name="header">
<a:sortLink label="#{msg.last_name}" value="lastName" styleClass="header" />
</f:facet>
<h:outputText value="#{r.lastName}" />
</a:column> </a:column>
<%-- Username column --%> <%-- Username column --%>