Merged V3.1 to HEAD

13129: Merged V2.1-A to V3.1
      8598: Fix for ADB-41 (ACT 1657)
   13139: Merged V2.1-A to V3.1
      8674: First phase of using group display name in UI
   13148: Merged V2.1-A to V3.1
      8679: Completion of using group display name in UI
   13149: Merged V2.1-A to V3.1
      8690: Fixed ADB-33 again
   13150: Merged V2.1-A to V3.1
      8775: Fix ACT-2399
   13152: Merged V2.1-A to V3.1
      8941: ACT-2631: added max users message to send email action page

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13565 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2009-03-11 13:52:31 +00:00
parent 57afebd2cd
commit de9feffb28
14 changed files with 295 additions and 70 deletions

View File

@@ -100,6 +100,9 @@
<!-- Language selection from login dialog - if false then the language will be selected -->
<!-- from the client browser locale and the language drop-down will not be displayed -->
<language-select>true</language-select>
<!-- Allow zero byte file uploads - set to false log warning and ignore on upload otherwise -->
<zero-byte-file-uploads>true</zero-byte-file-uploads>
</client>
</config>

View File

@@ -25,27 +25,31 @@ package org.alfresco.web.app.servlet;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.alfresco.config.ConfigService;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.util.TempFileProvider;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.FileUploadBean;
import org.apache.commons.io.FilenameUtils;
import org.alfresco.web.config.ClientConfigElement;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Servlet that takes a file uploaded via a browser and represents it as an
@@ -58,6 +62,21 @@ public class UploadFileServlet extends BaseServlet
private static final long serialVersionUID = -5482538466491052873L;
private static final Log logger = LogFactory.getLog(UploadFileServlet.class);
private ConfigService configService;
/**
* @see javax.servlet.GenericServlet#init()
*/
@Override
public void init(ServletConfig sc) throws ServletException
{
super.init(sc);
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(sc.getServletContext());
this.configService = (ConfigService)ctx.getBean("webClientConfigService");
}
/**
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@@ -117,6 +136,10 @@ public class UploadFileServlet extends BaseServlet
{
logger.debug("Processing uploaded file: " + filename);
}
// ADB-41: Ignore non-existent files i.e. 0 byte streams.
if (allowZeroByteFiles() == true || item.getSize() > 0)
{
// workaround a bug in IE where the full path is returned
// IE is only available for Windows so only check for the Windows path separator
filename = FilenameUtils.getName(filename);
@@ -132,15 +155,23 @@ public class UploadFileServlet extends BaseServlet
" bytes created from upload filename: " + filename);
}
}
else
{
if (logger.isWarnEnabled())
logger.warn("Ignored file '" + filename + "' as there was no content, this is either " +
"caused by uploading an empty file or a file path that does not exist on the client.");
}
}
}
}
session.setAttribute(FileUploadBean.getKey(uploadId), bean);
if (bean.getFile() == null)
if (bean.getFile() == null && uploadId != null && logger.isWarnEnabled())
{
logger.warn("no file uploaded for upload " + uploadId);
logger.warn("no file uploaded for upload id: " + uploadId);
}
if (returnPage == null || returnPage.length() == 0)
{
throw new AlfrescoRuntimeException("return-page parameter has not been supplied");
@@ -184,4 +215,11 @@ public class UploadFileServlet extends BaseServlet
logger.debug("upload complete");
}
}
private boolean allowZeroByteFiles()
{
ClientConfigElement clientConfig = (ClientConfigElement)configService.getGlobalConfig().getConfigElement(
ClientConfigElement.CONFIG_ELEMENT_ID);
return clientConfig.isZeroByteFileUploads();
}
}

View File

@@ -571,14 +571,21 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis
{
// need a map (dummy node) to represent props for this Group Authority
node = new HashMap<String, Object>(8, 1.0f);
String groupDisplayName = this.authorityService.getAuthorityDisplayName(authority);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
if (authority.startsWith(PermissionService.GROUP_PREFIX) == true)
{
node.put(PROP_FULLNAME, authority.substring(PermissionService.GROUP_PREFIX.length()));
groupDisplayName = authority.substring(PermissionService.GROUP_PREFIX.length());
}
else
{
node.put(PROP_FULLNAME, authority);
groupDisplayName = authority;
}
}
node.put(PROP_FULLNAME, groupDisplayName);
node.put(PROP_USERNAME, authority);
node.put(PROP_ID, authority);
node.put(PROP_ICON, WebResources.IMAGE_GROUP);

View File

@@ -49,6 +49,7 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
@@ -101,6 +102,9 @@ public abstract class UserMembersBean extends BaseDialogBean implements IContext
/** PermissionService bean reference */
transient private PermissionService permissionService;
/** AuthorityService bean reference */
transient private AuthorityService authorityService;
/** PersonService bean reference */
transient private PersonService personService;
@@ -200,6 +204,23 @@ public abstract class UserMembersBean extends BaseDialogBean implements IContext
return permissionService;
}
/**
* @param authorityService The AuthorityService to set.
*/
public void setAuthorityService(AuthorityService authorityService)
{
this.authorityService = authorityService;
}
protected AuthorityService getAuthorityService()
{
if (authorityService == null)
{
authorityService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getAuthorityService();
}
return authorityService;
}
/**
* @param ownableService The ownableService to set.
*/
@@ -410,6 +431,7 @@ public abstract class UserMembersBean extends BaseDialogBean implements IContext
// it is much better for performance to do this now rather than during page bind
Map<String, Object> props = node.getProperties();
props.put("fullName", ((String)props.get("firstName")) + ' ' + ((String)props.get("lastName")));
props.put("userNameLabel", props.get("userName"));
props.put("roles", roleListToString(context, permissionMap.get(authority)));
props.put("icon", WebResources.IMAGE_PERSON);
props.put("isGroup", Boolean.FALSE);
@@ -422,14 +444,22 @@ public abstract class UserMembersBean extends BaseDialogBean implements IContext
{
// need a map (dummy node) to represent props for this Group Authority
Map<String, Object> node = new HashMap<String, Object>(8, 1.0f);
String groupDisplayName = getAuthorityService().getAuthorityDisplayName(authority);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
if (authority.startsWith(PermissionService.GROUP_PREFIX) == true)
{
node.put("fullName", authority.substring(PermissionService.GROUP_PREFIX.length()));
groupDisplayName = authority.substring(PermissionService.GROUP_PREFIX.length());
}
else
{
node.put("fullName", authority);
groupDisplayName = authority;
}
}
node.put("fullName", groupDisplayName);
node.put("userNameLabel", groupDisplayName);
node.put("userName", authority);
node.put("id", authority);
node.put("roles", roleListToString(context, permissionMap.get(authority)));
@@ -621,7 +651,13 @@ public abstract class UserMembersBean extends BaseDialogBean implements IContext
}
else
{
setPersonName(authority);
String label = params.get("userNameLabel");
if (label == null || label.length() == 0)
{
label = authority;
}
setPersonName(label);
}
// setup roles for this Authority

View File

@@ -295,9 +295,24 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
}
}
// reset max users flag
this.maxUsersReturned = false;
return outcome;
}
/* (non-Javadoc)
* @see org.alfresco.web.bean.dialog.BaseDialogBean#cancel()
*/
@Override
public String cancel()
{
// reset max users flag
this.maxUsersReturned = false;
return super.cancel();
}
/**
* @see org.alfresco.web.bean.dialog.BaseDialogBean#getFinishButtonDisabled()
*/
@@ -366,6 +381,15 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
// Use lucene search to retrieve user details
String term = QueryParser.escape(contains.trim());
StringBuilder query = new StringBuilder(128);
if (contains == null || contains.length() == 0)
{
// if there is no search term, search for all people
query.append("+TYPE:\"");
query.append(ContentModel.TYPE_PERSON.toString());
query.append("\"");
}
else
{
query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*");
query.append(term);
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*");
@@ -373,12 +397,14 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:");
query.append(term);
query.append("*");
}
int maxResults = Application.getClientConfig(context).getInviteUsersMaxResults();
if (logger.isDebugEnabled())
{
logger.debug("Maximum invite users results size: " + maxResults);
logger.debug("Using query to find users: " + query.toString());
}
SearchParameters searchParams = new SearchParameters();
@@ -428,12 +454,19 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
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 = authorityService.getAuthorityDisplayName(group);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
results.add(new SortableSelectItem(group, group.substring(offset), group));
groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length());
}
if (groupDisplayName.toLowerCase().indexOf(containsLower) != -1)
{
results.add(new SortableSelectItem(group, groupDisplayName, groupDisplayName));
}
}
}
@@ -684,8 +717,14 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean
*/
public String buildLabelForGroupAuthorityRole(String authority, String role)
{
String groupDisplayName = this.authorityService.getAuthorityDisplayName(authority);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
groupDisplayName = authority.substring(PermissionService.GROUP_PREFIX.length());
}
StringBuilder buf = new StringBuilder(100);
buf.append(authority.substring(PermissionService.GROUP_PREFIX.length()))
buf.append(groupDisplayName)
.append(" (")
.append(Application.getMessage(FacesContext.getCurrentInstance(), role))
.append(")");

View File

@@ -82,6 +82,7 @@ public class ClientConfigElement extends ConfigElementAdapter
private String breadcrumbMode = BREADCRUMB_PATH;
private String cifsURLSuffix;
private boolean languageSelect = true;
private boolean zeroByteFileUploads = true;
/**
@@ -263,6 +264,11 @@ public class ClientConfigElement extends ConfigElementAdapter
combinedElement.setLanguageSelect(newElement.isLanguageSelect());
}
if (newElement.isZeroByteFileUploads() != combinedElement.isZeroByteFileUploads())
{
combinedElement.setZeroByteFileUploads(newElement.isZeroByteFileUploads());
}
return combinedElement;
}
@@ -744,4 +750,20 @@ public class ClientConfigElement extends ConfigElementAdapter
{
this.languageSelect = value;
}
/**
* @return true if zero byte file uploads are allowed, false otherwise
*/
public boolean isZeroByteFileUploads()
{
return this.zeroByteFileUploads;
}
/**
* @param zeroByteFileUploads true if zero byte file uploads are allowed, false otherwise
*/
/*package*/ void setZeroByteFileUploads(boolean zeroByteFileUploads)
{
this.zeroByteFileUploads = zeroByteFileUploads;
}
}

View File

@@ -67,6 +67,7 @@ public class ClientElementReader implements ConfigElementReader
public static final String ELEMENT_BREADCRUMB_MODE = "breadcrumb-mode";
public static final String ELEMENT_CIFSURLSUFFIX = "cifs-url-suffix";
public static final String ELEMENT_LANGUAGESELECT = "language-select";
public static final String ELEMENT_ZEROBYTEFILEUPLOADS = "zero-byte-file-uploads";
/**
@@ -283,6 +284,13 @@ public class ClientElementReader implements ConfigElementReader
{
configElement.setLanguageSelect(Boolean.parseBoolean(langSelect.getTextTrim()));
}
// get the zero byte file upload mode
Element zeroByteFiles = element.element(ELEMENT_ZEROBYTEFILEUPLOADS);
if (zeroByteFiles != null)
{
configElement.setZeroByteFileUploads(Boolean.parseBoolean(zeroByteFiles.getTextTrim()));
}
}
return configElement;

View File

@@ -726,10 +726,17 @@ public abstract class BaseAssociationEditor extends UIInput
}
else if (ContentModel.TYPE_AUTHORITY_CONTAINER.equals(nodeService.getType(targetRef)))
{
int offset = PermissionService.GROUP_PREFIX.length();
// get display name, if not present strip prefix from group id
String groupDisplayName = (String)nodeService.getProperty(targetRef,
ContentModel.PROP_AUTHORITY_DISPLAY_NAME);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
String group = (String)nodeService.getProperty(targetRef,
ContentModel.PROP_AUTHORITY_NAME);
out.write(group.substring(offset));
groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length());
}
out.write(groupDisplayName);
}
else
{
@@ -867,15 +874,24 @@ public abstract class BaseAssociationEditor extends UIInput
}
else if (ContentModel.TYPE_AUTHORITY_CONTAINER.equals(nodeService.getType(item)))
{
// if the node represents a group, show the authority name instead of the name
int offset = PermissionService.GROUP_PREFIX.length();
// if the node represents a group, show the authority display name instead of the name
String groupDisplayName = (String)nodeService.getProperty(item,
ContentModel.PROP_AUTHORITY_DISPLAY_NAME);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
String group = (String)nodeService.getProperty(item,
ContentModel.PROP_AUTHORITY_NAME);
groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length());
}
out.write("<option value='");
out.write(item.toString());
out.write("'>");
out.write(group.substring(offset));
out.write(groupDisplayName);
out.write("</option>");
}
else
{
@@ -949,15 +965,22 @@ public abstract class BaseAssociationEditor extends UIInput
if (authorityDAO != null)
{
List<String> matchingGroups = new ArrayList<String>();
int offset = PermissionService.GROUP_PREFIX.length();
String groupDisplayName;
for (String group : groups)
{
// get display name, if not present strip prefix from group id
groupDisplayName = authorityService.getAuthorityDisplayName(group);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length());
}
// if a search string is present make sure the group matches
// otherwise just add the group name to the sorted set
if (safeContains != null)
{
if (group.toLowerCase().indexOf(safeContains, offset) != -1)
if (groupDisplayName.toLowerCase().indexOf(safeContains) != -1)
{
matchingGroups.add(group);
}

View File

@@ -175,11 +175,17 @@ public class UIAssociationEditor extends BaseAssociationEditor
}
else if (ContentModel.TYPE_AUTHORITY_CONTAINER.equals(nodeService.getType(targetNode)))
{
// if the node represents a group, show the group name instead of the name
int offset = PermissionService.GROUP_PREFIX.length();
// if the node represents a group, show the group display name instead of the name
String groupDisplayName = (String)nodeService.getProperty(targetNode,
ContentModel.PROP_AUTHORITY_DISPLAY_NAME);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
String group = (String)nodeService.getProperty(targetNode,
ContentModel.PROP_AUTHORITY_NAME);
out.write(group.substring(offset));
groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length());
}
out.write(groupDisplayName);
}
else
{

View File

@@ -172,11 +172,17 @@ public class UIChildAssociationEditor extends BaseAssociationEditor
}
else if (ContentModel.TYPE_AUTHORITY_CONTAINER.equals(nodeService.getType(targetNode)))
{
// if the node represents a group, show the group name instead of the name
int offset = PermissionService.GROUP_PREFIX.length();
// if the node represents a group, show the group display name instead of the name
String groupDisplayName = (String)nodeService.getProperty(targetNode,
ContentModel.PROP_AUTHORITY_DISPLAY_NAME);
if (groupDisplayName == null || groupDisplayName.length() == 0)
{
String group = (String)nodeService.getProperty(targetNode,
ContentModel.PROP_AUTHORITY_NAME);
out.write(group.substring(offset));
groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length());
}
out.write(groupDisplayName);
}
else
{

View File

@@ -1218,6 +1218,10 @@
<property-name>permissionService</property-name>
<value>#{PermissionService}</value>
</managed-property>
<managed-property>
<property-name>authorityService</property-name>
<value>#{AuthorityService}</value>
</managed-property>
<managed-property>
<property-name>ownableService</property-name>
<value>#{OwnableService}</value>
@@ -1251,6 +1255,10 @@
<property-name>permissionService</property-name>
<value>#{PermissionService}</value>
</managed-property>
<managed-property>
<property-name>authorityService</property-name>
<value>#{AuthorityService}</value>
</managed-property>
<managed-property>
<property-name>ownableService</property-name>
<value>#{OwnableService}</value>

View File

@@ -30,6 +30,11 @@
<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
<%@ page import="javax.faces.context.FacesContext" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
<%@ page import="org.alfresco.web.bean.spaces.InviteSpaceUsersWizard" %>
<%@ page import="org.alfresco.web.app.servlet.FacesHelper" %>
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
<r:page titleId="title_action_email">
@@ -138,6 +143,18 @@
<td colspan="2" class="mainSubTitle"><h:outputText value="#{msg.set_action_values}" /></td>
</tr>
<h:panelGroup rendered="#{InviteSpaceUsersWizard.haveMaximumUsersBeenReturned}">
<f:verbatim><tr><td colspan="2">
<% out.write("<div style='padding:2px;'></div>");
PanelGenerator.generatePanelStart(out, request.getContextPath(), "yellowInner", "#ffffcc"); %>
<img src='<%=request.getContextPath()%>/images/icons/info_icon.gif' align='absmiddle' />&nbsp;&nbsp;
</f:verbatim>
<h:outputText id="infoMsg" value="#{InviteSpaceUsersWizard.maximumUsersMsg}" />
<f:verbatim>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "yellowInner"); %>
</td></tr></f:verbatim>
</h:panelGroup>
<%-- Select the email receipients --%>
<tr><td colspan="2" class="paddingRow"></td></tr>
<tr><td colspan="2" class="mainSubTitle"><h:outputText value="#{msg.message_recipients}" /></td></tr>
@@ -267,3 +284,11 @@
</f:view>
</r:page>
<%
InviteSpaceUsersWizard wizard = (InviteSpaceUsersWizard)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "InviteSpaceUsersWizard");
if (wizard != null)
{
wizard.init(new HashMap<String, String>());
}
%>

View File

@@ -63,9 +63,9 @@
<%-- Username column --%>
<a:column width="120" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.authority}" value="userName" styleClass="header"/>
<a:sortLink label="#{msg.authority}" value="userNameLabel" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.userName}" />
<h:outputText value="#{r.userNameLabel}" />
</a:column>
<%-- Roles column --%>
@@ -83,10 +83,12 @@
</f:facet>
<a:booleanEvaluator value="#{!r.inherited}">
<a:actionLink value="#{msg.change_roles}" image="/images/icons/edituser.gif" showLink="false" action="dialog:editContentUserRoles" actionListener="#{EditContentUserRolesDialog.setupUserAction}">
<f:param name="userName" value="#{r.userName}" />
<f:param id="p1" name="userName" value="#{r.userName}" />
<f:param id="p2" name="userNameLabel" value="#{r.userNameLabel}" />
</a:actionLink>
<a:actionLink value="#{msg.remove}" image="/images/icons/delete_person.gif" showLink="false" action="dialog:removeContentUser" actionListener="#{RemoveContentUserDialog.setupUserAction}">
<f:param name="userName" value="#{r.userName}" />
<f:param id="p3" name="userName" value="#{r.userName}" />
<f:param id="p4" name="userNameLabel" value="#{r.userNameLabel}" />
</a:actionLink>
</a:booleanEvaluator>
</a:column>

View File

@@ -65,9 +65,9 @@
<%-- Username column --%>
<a:column width="120" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.authority}" value="userName" styleClass="header"/>
<a:sortLink label="#{msg.authority}" value="userNameLabel" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.userName}" />
<h:outputText value="#{r.userNameLabel}" />
</a:column>
<%-- Roles column --%>
@@ -86,9 +86,11 @@
<a:booleanEvaluator value="#{!r.inherited}">
<a:actionLink value="#{msg.change_roles}" image="/images/icons/edituser.gif" showLink="false" action="dialog:editUserRoles" actionListener="#{EditUserRolesDialog.setupUserAction}">
<f:param name="userName" value="#{r.userName}" />
<f:param name="userNameLabel" value="#{r.userNameLabel}" />
</a:actionLink>
<a:actionLink value="#{msg.remove}" image="/images/icons/delete_person.gif" showLink="false" action="dialog:removeInvitedUser" actionListener="#{RemoveInvitedUserDialog.setupUserAction}">
<f:param name="userName" value="#{r.userName}" />
<f:param name="userNameLabel" value="#{r.userNameLabel}" />
</a:actionLink>
</a:booleanEvaluator>
</a:column>