diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties
index 4f6f498e71..28e9b1a883 100644
--- a/config/alfresco/messages/webclient.properties
+++ b/config/alfresco/messages/webclient.properties
@@ -2041,6 +2041,7 @@ idle=Idle
loading=Loading
eg=e.g.
click_to_edit=click to edit
+please_select=Please select...
# File Picker
go_up=Go up
diff --git a/config/alfresco/web-client-application-context.xml b/config/alfresco/web-client-application-context.xml
index 9c9dcad9b2..a37851c8da 100644
--- a/config/alfresco/web-client-application-context.xml
+++ b/config/alfresco/web-client-application-context.xml
@@ -175,7 +175,7 @@
- org.alfresco.web.app.servlet.RemoteUserMapper
+ org.alfresco.repo.webdav.auth.RemoteUserMapperorg.alfresco.repo.management.subsystems.ActivateableBean
@@ -271,6 +271,12 @@
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java
index 53b5f9297c..9fa7527b7d 100644
--- a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java
+++ b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java
@@ -510,6 +510,21 @@ public class AlfrescoNavigationHandler extends NavigationHandler
return dispatchNode;
}
+ protected void handleBrowseDispatch(FacesContext context, String fromAction, String outcome)
+ {
+ Node dispatchNode = null;
+
+ NavigationBean navBean = (NavigationBean) context.getExternalContext().getSessionMap()
+ .get(NavigationBean.BEAN_NAME);
+
+ if (navBean != null)
+ {
+ dispatchNode = navBean.getCurrentNode();
+ }
+
+ handleDispatch(context, fromAction, outcome, dispatchNode);
+ }
+
/**
* Processes any dispatching that may need to occur
*
@@ -520,7 +535,11 @@ public class AlfrescoNavigationHandler extends NavigationHandler
protected void handleDispatch(FacesContext context, String fromAction, String outcome)
{
Node dispatchNode = getDispatchContextNode(context);
-
+ handleDispatch(context, fromAction, outcome, dispatchNode);
+ }
+
+ private void handleDispatch(FacesContext context, String fromAction, String outcome, Node dispatchNode)
+ {
if (dispatchNode != null)
{
if (logger.isDebugEnabled())
@@ -789,7 +808,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler
}
else
{
- navigate(context, fromAction, overriddenOutcome);
+ handleBrowseDispatch(context, fromAction, overriddenOutcome);
}
}
}
diff --git a/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java b/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java
index dd623cb6cf..9736628814 100644
--- a/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java
+++ b/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java
@@ -37,6 +37,7 @@ import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.webdav.auth.RemoteUserMapper;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -273,11 +274,24 @@ public final class AuthenticationHelper
HttpSession session = httpRequest.getSession();
try
{
- auth.validate(ticket, session.getId());
-
- // We may have previously been authenticated via WebDAV so we may need to 'promote' the user object
+ // If we already have a cached user, make sure it is for the right ticket
SessionUser user = (SessionUser)session.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
- if (user == null || !(user instanceof User))
+ if (user != null && !user.getTicket().equals(ticket))
+ {
+ session.removeAttribute(AUTHENTICATION_USER);
+ if (!Application.inPortalServer())
+ {
+ session.invalidate();
+ session = httpRequest.getSession();
+ }
+ user = null;
+ }
+
+ // Validate the ticket and associate it with the session
+ auth.validate(ticket, session.getId());
+
+ // Cache a new user in the session if required
+ if (user == null)
{
setUser(context, httpRequest, auth.getCurrentUserName(), ticket, false);
}
@@ -285,6 +299,10 @@ public final class AuthenticationHelper
catch (AuthenticationException authErr)
{
session.removeAttribute(AUTHENTICATION_USER);
+ if (!Application.inPortalServer())
+ {
+ session.invalidate();
+ }
return AuthenticationStatus.Failure;
}
catch (Throwable e)
diff --git a/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapper.java b/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapper.java
index 481400a4d5..c28d868923 100644
--- a/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapper.java
+++ b/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapper.java
@@ -28,6 +28,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.repo.webdav.auth.RemoteUserMapper;
/**
* A default {@link RemoteUserMapper} implementation. Extracts a user ID using
* {@link HttpServletRequest#getRemoteUser()} and optionally from a configured request header. If there is no configured
diff --git a/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java b/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java
index efea132636..5de9ada8fe 100644
--- a/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java
+++ b/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java
@@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletRequest;
import org.alfresco.repo.management.subsystems.AbstractChainedSubsystemTest;
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
import org.alfresco.repo.management.subsystems.DefaultChildApplicationContextManager;
+import org.alfresco.repo.webdav.auth.RemoteUserMapper;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.context.ApplicationContext;
diff --git a/source/java/org/alfresco/web/app/servlet/KerberosAuthenticationFilter.java b/source/java/org/alfresco/web/app/servlet/KerberosAuthenticationFilter.java
index c52b0ef4b8..9413685e52 100644
--- a/source/java/org/alfresco/web/app/servlet/KerberosAuthenticationFilter.java
+++ b/source/java/org/alfresco/web/app/servlet/KerberosAuthenticationFilter.java
@@ -130,9 +130,10 @@ public class KerberosAuthenticationFilter extends BaseKerberosAuthenticationFilt
throws IOException
{
// If the original URL requested was the login page then redirect to the browse view
- if (userInit || req.getRequestURI().endsWith(getLoginPage()))
+ String requestURI = req.getRequestURI();
+ if (requestURI.startsWith(req.getContextPath() + BaseServlet.FACES_SERVLET) && (userInit || requestURI.endsWith(getLoginPage())))
{
- if (logger.isDebugEnabled() && req.getRequestURI().endsWith(getLoginPage()))
+ if (logger.isDebugEnabled() && requestURI.endsWith(getLoginPage()))
logger.debug("Login page requested - redirecting to initially configured page");
if (logger.isDebugEnabled() && userInit)
logger.debug("Session reinitialised - redirecting to initially configured page");
diff --git a/source/java/org/alfresco/web/app/servlet/NTLMAuthenticationFilter.java b/source/java/org/alfresco/web/app/servlet/NTLMAuthenticationFilter.java
index 3ccb33d8f6..34d72cc0b3 100644
--- a/source/java/org/alfresco/web/app/servlet/NTLMAuthenticationFilter.java
+++ b/source/java/org/alfresco/web/app/servlet/NTLMAuthenticationFilter.java
@@ -123,9 +123,10 @@ public class NTLMAuthenticationFilter extends BaseNTLMAuthenticationFilter
throws IOException
{
// If the original URL requested was the login page then redirect to the browse view
- if (userInit || req.getRequestURI().endsWith(getLoginPage()))
+ String requestURI = req.getRequestURI();
+ if (requestURI.startsWith(req.getContextPath() + BaseServlet.FACES_SERVLET) && (userInit || requestURI.endsWith(getLoginPage())))
{
- if (logger.isDebugEnabled() && req.getRequestURI().endsWith(getLoginPage()))
+ if (logger.isDebugEnabled() && requestURI.endsWith(getLoginPage()))
logger.debug("Login page requested - redirecting to initially configured page");
if (logger.isDebugEnabled() && userInit)
logger.debug("Session reinitialised - redirecting to initially configured page");
diff --git a/source/java/org/alfresco/web/app/servlet/RemoteUserMapper.java b/source/java/org/alfresco/web/app/servlet/RemoteUserMapper.java
deleted file mode 100644
index 745fb4ec8a..0000000000
--- a/source/java/org/alfresco/web/app/servlet/RemoteUserMapper.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2005-2010 Alfresco Software Limited.
- *
- * This file is part of Alfresco
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- */
-package org.alfresco.web.app.servlet;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * An interface for objects capable of extracting an externally authenticated user ID from an HTTP request.
- *
- * @author dward
- */
-public interface RemoteUserMapper
-{
- /**
- * Gets an externally authenticated user ID from an HTTP request.
- *
- * @param request
- * the request
- * @return the user ID or null if the user is unauthenticated
- */
- public String getRemoteUser(HttpServletRequest request);
-}
diff --git a/source/java/org/alfresco/web/bean/NavigationBean.java b/source/java/org/alfresco/web/bean/NavigationBean.java
index fae2635d7e..906f83f5e8 100644
--- a/source/java/org/alfresco/web/bean/NavigationBean.java
+++ b/source/java/org/alfresco/web/bean/NavigationBean.java
@@ -1020,13 +1020,19 @@ public class NavigationBean implements Serializable
}
/**
- * @return true if users can configure their own settings and password in the User Console
+ * @return true if users can configure their own settings in the User Console
*/
public boolean isAllowUserConfig()
{
- // For correct behaviour, we ask the authentication chain whether this particular user is mutable
- return this.clientConfig.getAllowUserConfig()
- && this.authService.isAuthenticationMutable(this.authService.getCurrentUserName());
+ return this.clientConfig.getAllowUserConfig();
+ }
+
+ /**
+ * @return true if a users can modify the password set against their authentication
+ */
+ public boolean isAllowUserChangePassword()
+ {
+ return this.authService.isAuthenticationMutable(this.authService.getCurrentUserName());
}
diff --git a/source/java/org/alfresco/web/bean/content/DocumentDetailsDialog.java b/source/java/org/alfresco/web/bean/content/DocumentDetailsDialog.java
index cfa8f4850c..c2e7901ffc 100644
--- a/source/java/org/alfresco/web/bean/content/DocumentDetailsDialog.java
+++ b/source/java/org/alfresco/web/bean/content/DocumentDetailsDialog.java
@@ -22,7 +22,6 @@ import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -39,7 +38,6 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
-import org.alfresco.repo.version.common.VersionLabelComparator;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
@@ -391,15 +389,14 @@ public class DocumentDetailsDialog extends BaseDetailsBean implements Navigatio
*
* @return List of editions
*/
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("unused")
private List initEditionHistory()
{
// get the mlContainer
NodeRef mlContainer = getDocumentMlContainer().getNodeRef();
- // get all editions and sort them ascending according their version label
+ // get all editions (in descending order - ie. most recent first)
List orderedEditionList = new ArrayList(getEditionService().getEditions(mlContainer).getAllVersions());
- Collections.sort(orderedEditionList, new VersionLabelComparator());
// the list of Single Edition Bean to return
editionHistory = new ArrayList(orderedEditionList.size());
@@ -449,11 +446,10 @@ public class DocumentDetailsDialog extends BaseDetailsBean implements Navigatio
// add each translation in the SingleEditionBean
for (VersionHistory versionHistory : translationHistories)
{
- // get the list of versions and sort them ascending according their version label
+ // get the list of versions (in descending order - ie. most recent first)
List orderedVersions = new ArrayList(versionHistory.getAllVersions());
- Collections.sort(orderedVersions, new VersionLabelComparator());
- // the last version is the first version of the list
+ // the last version (ie. most recent) is the first version of the list
Version lastVersion = orderedVersions.get(0);
// get the properties of the lastVersion
diff --git a/source/java/org/alfresco/web/bean/content/VersionedDocumentDetailsDialog.java b/source/java/org/alfresco/web/bean/content/VersionedDocumentDetailsDialog.java
index bfa8fec46a..e870349ea7 100644
--- a/source/java/org/alfresco/web/bean/content/VersionedDocumentDetailsDialog.java
+++ b/source/java/org/alfresco/web/bean/content/VersionedDocumentDetailsDialog.java
@@ -31,9 +31,8 @@ import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
-import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.model.ContentModel;
-import org.alfresco.repo.version.common.VersionLabelComparator;
+import org.alfresco.repo.version.common.VersionHistoryImpl.VersionComparatorDesc;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
import org.alfresco.service.cmr.ml.EditionService;
@@ -45,7 +44,6 @@ import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
-import org.springframework.extensions.surf.util.ParameterCheck;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.bean.BrowseBean;
@@ -54,6 +52,8 @@ import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIActionLink;
+import org.springframework.extensions.surf.util.I18NUtil;
+import org.springframework.extensions.surf.util.ParameterCheck;
/**
* Bean with generic function helping the rendering of the versioned properties
@@ -71,7 +71,7 @@ public class VersionedDocumentDetailsDialog implements Serializable
transient private MultilingualContentService multilingualContentService;
transient private ContentFilterLanguagesService contentFilterLanguagesService;
- private static final Comparator VERSION_LABEL_COMPARATOR = new VersionLabelComparator();
+ private static final Comparator VERSION_COMPARATOR_DESC = new VersionComparatorDesc();
/** Determine if the version is a translation of a old edition */
private boolean fromPreviousEditon;
@@ -196,7 +196,7 @@ public class VersionedDocumentDetailsDialog implements Serializable
}
else
{
- Collections.sort(nextVersions, VERSION_LABEL_COMPARATOR);
+ Collections.sort(nextVersions, VERSION_COMPARATOR_DESC);
this.documentVersion = nextVersions.get(0);
}
}
@@ -223,12 +223,10 @@ public class VersionedDocumentDetailsDialog implements Serializable
{
Version prevVersion = this.versionHistory.getPredecessor(this.documentVersion);
- // if the version history doesn't contains predecessor, get the last version
+ // if the version history doesn't contains predecessor, get the last version (ie. most recent)
if(prevVersion == null)
{
List allVersions = new ArrayList(this.versionHistory.getAllVersions());
- Collections.sort(allVersions, VERSION_LABEL_COMPARATOR);
-
this.documentVersion = allVersions.get(0);
}
else
@@ -265,14 +263,13 @@ public class VersionedDocumentDetailsDialog implements Serializable
{
translationNodeRef = new HashMap(translationsList.size());
- // get the last version of the translation in the given lang of the edition
+ // get the last (most recent) version of the translation in the given lang of the edition
for (VersionHistory history : translationsList)
{
- // get the list of versions and sort them ascending according their version label
+ // get the list of versions (in descending order - ie. most recent first)
List orderedVersions = new ArrayList(history.getAllVersions());
- Collections.sort(orderedVersions, VERSION_LABEL_COMPARATOR);
- // the last version is the first version of the list
+ // the last (most recent) version is the first version of the list
Version lastVersion = orderedVersions.get(0);
// fill the list of translation
@@ -471,7 +468,7 @@ public class VersionedDocumentDetailsDialog implements Serializable
}
/**
- * Util method which return the last version of a translation of a given edition of a mlContainer according its language
+ * Util method which return the last (most recent) version of a translation of a given edition of a mlContainer according its language
*/
@SuppressWarnings("unchecked")
private Version getBrowsingVersionForMLContainer(NodeRef document, String editionLabel, String lang)
@@ -489,14 +486,13 @@ public class VersionedDocumentDetailsDialog implements Serializable
{
Version versionToReturn = null;
- // get the last version of the translation in the given lang of the edition
+ // get the last (most recent) version of the translation in the given lang of the edition
for (VersionHistory history : translations)
{
- // get the list of versions and sort them ascending according their version label
+ // get the list of versions (in descending order - ie. most recent first)
List orderedVersions = new ArrayList(history.getAllVersions());
- Collections.sort(orderedVersions, VERSION_LABEL_COMPARATOR);
- // the last version is the first version of the list
+ // the last version (ie. most recent) is the first version of the list
Version lastVersion = orderedVersions.get(0);
if(lastVersion != null)
diff --git a/source/java/org/alfresco/web/bean/ml/MultilingualManageDialog.java b/source/java/org/alfresco/web/bean/ml/MultilingualManageDialog.java
index a70ff9f73b..3904d987cc 100644
--- a/source/java/org/alfresco/web/bean/ml/MultilingualManageDialog.java
+++ b/source/java/org/alfresco/web/bean/ml/MultilingualManageDialog.java
@@ -21,7 +21,6 @@ package org.alfresco.web.bean.ml;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -31,7 +30,6 @@ import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.alfresco.model.ContentModel;
-import org.alfresco.repo.version.common.VersionLabelComparator;
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
import org.alfresco.service.cmr.ml.EditionService;
import org.alfresco.service.cmr.ml.MultilingualContentService;
@@ -427,15 +425,13 @@ public class MultilingualManageDialog extends BaseDialogBean
*
* @return List of editions
*/
- @SuppressWarnings("unchecked")
private List initEditionHistory()
{
// get the mlContainer
NodeRef mlContainer = getDocumentMlContainer().getNodeRef();
- // get all editions and sort them ascending according their version label
+ // get all editions (in descending order - ie. most recent first)
List orderedEditionList = new ArrayList(getEditionService().getEditions(mlContainer).getAllVersions());
- Collections.sort(orderedEditionList, new VersionLabelComparator());
// the list of Single Edition Bean to return
editionHistory = new ArrayList(orderedEditionList.size());
@@ -498,11 +494,10 @@ public class MultilingualManageDialog extends BaseDialogBean
}
}
- // get the list of versions and sort them ascending according their version label
+ // get the list of versions (in descending order - ie. most recent first)
List orderedVersions = new ArrayList(versionHistory.getAllVersions());
- Collections.sort(orderedVersions, new VersionLabelComparator());
- // the last version is the first version of the list
+ // the last version (ie. most recent) is the first version of the list
Version lastVersion = orderedVersions.get(0);
// get the properties of the lastVersion
diff --git a/source/java/org/alfresco/web/bean/users/CreateUserWizard.java b/source/java/org/alfresco/web/bean/users/CreateUserWizard.java
index 7ec6198bdc..b16804ba25 100644
--- a/source/java/org/alfresco/web/bean/users/CreateUserWizard.java
+++ b/source/java/org/alfresco/web/bean/users/CreateUserWizard.java
@@ -20,6 +20,7 @@ package org.alfresco.web.bean.users;
import java.io.Serializable;
import java.text.MessageFormat;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -976,4 +977,9 @@ public class CreateUserWizard extends BaseWizardBean
return true;
}
+
+ public Map getPersonPropertiesImmutability()
+ {
+ return Collections.EMPTY_MAP;
+ }
}
diff --git a/source/java/org/alfresco/web/bean/users/EditUserWizard.java b/source/java/org/alfresco/web/bean/users/EditUserWizard.java
index a585d6d8eb..7ec8ec3585 100644
--- a/source/java/org/alfresco/web/bean/users/EditUserWizard.java
+++ b/source/java/org/alfresco/web/bean/users/EditUserWizard.java
@@ -220,10 +220,17 @@ public class EditUserWizard extends CreateUserWizard
ReportedException.throwIfNecessary(e);
}
- if (outcome == null) {
+ if (outcome == null)
+ {
this.isFinished = false;
}
return outcome;
}
+
+ @Override
+ public Map getPersonPropertiesImmutability()
+ {
+ return this.properties.getImmutability();
+ }
}
diff --git a/source/java/org/alfresco/web/bean/users/UsersBeanProperties.java b/source/java/org/alfresco/web/bean/users/UsersBeanProperties.java
index 36d0a7ba43..f9ad668c61 100644
--- a/source/java/org/alfresco/web/bean/users/UsersBeanProperties.java
+++ b/source/java/org/alfresco/web/bean/users/UsersBeanProperties.java
@@ -19,11 +19,17 @@
package org.alfresco.web.bean.users;
import java.io.Serializable;
+import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
+import org.alfresco.repo.security.sync.UserRegistrySynchronizer;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
@@ -33,301 +39,450 @@ import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.usage.ContentUsageService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
+import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.data.UIRichList;
+import org.springframework.web.jsf.FacesContextUtils;
+/**
+ * Bean holding the properties for a Person node.
+ *
+ * Used by the Create/EditUserWizard, UsersDialog and EditUserDetailsDetails to maitain user state during dialog.
+ *
+ * Also provides access to a map of the properties to mutability which is used to disable appropriate controls on edit
+ * dialogs if properties are externally mapped to LDAP or similar.
+ */
public class UsersBeanProperties implements Serializable
{
- private static final long serialVersionUID = 8874192805959149144L;
-
- /** NodeService bean reference */
- transient private NodeService nodeService;
-
- /** SearchService bean reference */
- transient private SearchService searchService;
-
- /** AuthenticationService bean reference */
- transient private MutableAuthenticationService authenticationService;
-
- /** PersonService bean reference */
- transient private PersonService personService;
-
- /** ContentUsageService bean reference */
- transient private ContentUsageService contentUsageService;
-
-
- /** Component reference for Users RichList control */
- private UIRichList usersRichList;
-
- /** action context */
- private Node person = null;
-
- private String password = null;
- private String oldPassword = null;
- private String confirm = null;
- private String searchCriteria = null;
- private String userName = null;
-
- // ------------------------------------------------------------------------------
- // Bean property getters and setters
-
- /**
- * @return the nodeService
- */
- public NodeService getNodeService()
- {
- //check for null for cluster environment
- if (nodeService == null)
- {
- nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
- }
- return nodeService;
- }
-
- /**
- * @return the searchService
- */
- public SearchService getSearchService()
- {
- //check for null for cluster environment
- if (searchService == null)
- {
- searchService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getSearchService();
- }
-
- return searchService;
- }
-
- /**
- * @return the authenticationService
- */
- public MutableAuthenticationService getAuthenticationService()
- {
- //check for null for cluster environment
- if (authenticationService == null)
- {
- authenticationService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getAuthenticationService();
- }
- return authenticationService;
- }
-
- /**
- * @return the personService
- */
- public PersonService getPersonService()
- {
- //check for null for cluster environment
- if(personService == null)
- {
- personService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getPersonService();
- }
- return personService;
- }
-
-
- /**
- *@return contentUsageService
- */
- public ContentUsageService getContentUsageService()
- {
- //check for null for cluster environment
- if(contentUsageService == null)
- {
- contentUsageService = (ContentUsageService) FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "ContentUsageService");
- }
- return contentUsageService;
- }
+ private static final long serialVersionUID = 8874192805959149144L;
+
+ /** NodeService bean reference */
+ transient private NodeService nodeService;
+
+ /** SearchService bean reference */
+ transient private SearchService searchService;
+
+ /** AuthenticationService bean reference */
+ transient private MutableAuthenticationService authenticationService;
+
+ /** PersonService bean reference */
+ transient private PersonService personService;
+
+ /** ContentUsageService bean reference */
+ transient private ContentUsageService contentUsageService;
+
+ /** userRegistrySynchronizer bean reference */
+ transient private UserRegistrySynchronizer userRegistrySynchronizer;
+
+ /** Component reference for Users RichList control */
+ private UIRichList usersRichList;
+
+ /** action context */
+ private Node person = null;
+ private String password = null;
+ private String oldPassword = null;
+ private String confirm = null;
+ private String searchCriteria = null;
+ private String userName = null;
+ private Map immutabilty = null;
+
+
+ // ------------------------------------------------------------------------------
+ // Bean property getters and setters
/**
- * @param nodeService The NodeService to set.
- */
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
+ * @return the nodeService
+ */
+ public NodeService getNodeService()
+ {
+ if (nodeService == null)
+ {
+ nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
+ }
+ return nodeService;
+ }
- /**
- * @param searchService the search service
- */
- public void setSearchService(SearchService searchService)
- {
- this.searchService = searchService;
- }
+ /**
+ * @return the searchService
+ */
+ public SearchService getSearchService()
+ {
+ if (searchService == null)
+ {
+ searchService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getSearchService();
+ }
+ return searchService;
+ }
- /**
- * @param authenticationService The AuthenticationService to set.
- */
- public void setAuthenticationService(MutableAuthenticationService authenticationService)
- {
- this.authenticationService = authenticationService;
- }
+ /**
+ * @return the authenticationService
+ */
+ public MutableAuthenticationService getAuthenticationService()
+ {
+ if (authenticationService == null)
+ {
+ authenticationService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getAuthenticationService();
+ }
+ return authenticationService;
+ }
- /**
- * @param personService The PersonService to set.
- */
- public void setPersonService(PersonService personService)
- {
- this.personService = personService;
- }
-
- /**
- * @param contentUsageService The ContentUsageService to set.
- */
- public void setContentUsageService(ContentUsageService contentUsageService)
- {
- this.contentUsageService = contentUsageService;
- }
+ /**
+ * @return the personService
+ */
+ public PersonService getPersonService()
+ {
+ if (personService == null)
+ {
+ personService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getPersonService();
+ }
+ return personService;
+ }
- /**
- * @return Returns the usersRichList.
- */
- public UIRichList getUsersRichList()
- {
- return this.usersRichList;
- }
+ /**
+ * @return contentUsageService
+ */
+ public ContentUsageService getContentUsageService()
+ {
+ if (contentUsageService == null)
+ {
+ contentUsageService = (ContentUsageService) FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "ContentUsageService");
+ }
+ return contentUsageService;
+ }
+
+ /**
+ * @return userRegistrySynchronizer
+ */
+ public UserRegistrySynchronizer getUserRegistrySynchronizer()
+ {
+ if (userRegistrySynchronizer == null)
+ {
+ userRegistrySynchronizer = (UserRegistrySynchronizer)FacesContextUtils.getRequiredWebApplicationContext(
+ FacesContext.getCurrentInstance()).getBean("userRegistrySynchronizer");
+ }
+ return userRegistrySynchronizer;
+ }
+
+ /**
+ * @param nodeService The NodeService to set.
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
- /**
- * @param usersRichList The usersRichList to set.
- */
- public void setUsersRichList(UIRichList usersRichList)
- {
- this.usersRichList = usersRichList;
- }
+ /**
+ * @param searchServiceq the search service
+ */
+ public void setSearchService(SearchService searchService)
+ {
+ this.searchService = searchService;
+ }
- /**
- * @return Returns the search criteria
- */
- public String getSearchCriteria()
- {
- return searchCriteria;
- }
+ /**
+ * @param authenticationService The AuthenticationService to set.
+ */
+ public void setAuthenticationService(MutableAuthenticationService authenticationService)
+ {
+ this.authenticationService = authenticationService;
+ }
- /**
- * @param searchCriteria The search criteria to select
- */
- public void setSearchCriteria(String searchCriteria)
- {
- this.searchCriteria = searchCriteria;
- }
+ /**
+ * @param personService The PersonService to set.
+ */
+ public void setPersonService(PersonService personService)
+ {
+ this.personService = personService;
+ }
- /**
- * @return Returns the confirm password.
- */
- public String getConfirm()
- {
- return this.confirm;
- }
+ /**
+ * @param contentUsageService The ContentUsageService to set.
+ */
+ public void setContentUsageService(ContentUsageService contentUsageService)
+ {
+ this.contentUsageService = contentUsageService;
+ }
+
+ /**
+ * @param userRegistrySynchronizer
+ */
+ public void setUserRegistrySynchronizer(UserRegistrySynchronizer userRegistrySynchronizer)
+ {
+ this.userRegistrySynchronizer = userRegistrySynchronizer;
+ }
- /**
- * @param confirm The confirm password to set.
- */
- public void setConfirm(String confirm)
- {
- this.confirm = confirm;
- }
+ /**
+ * @return Returns the usersRichList.
+ */
+ public UIRichList getUsersRichList()
+ {
+ return this.usersRichList;
+ }
- /**
- * @return Returns the password.
- */
- public String getPassword()
- {
- return this.password;
- }
+ /**
+ * @param usersRichList The usersRichList to set.
+ */
+ public void setUsersRichList(UIRichList usersRichList)
+ {
+ this.usersRichList = usersRichList;
+ }
- /**
- * @param password The password to set.
- */
- public void setPassword(String password)
- {
- this.password = password;
- }
-
- /**
- * @return Returns the old password.
- */
- public String getOldPassword()
- {
- return this.oldPassword;
- }
+ /**
+ * @return Returns the search criteria
+ */
+ public String getSearchCriteria()
+ {
+ return searchCriteria;
+ }
- /**
- * @param oldPassword The old password to set.
- */
- public void setOldPassword(String oldPassword)
- {
- this.oldPassword = oldPassword;
- }
+ /**
+ * @param searchCriteria The search criteria to select
+ */
+ public void setSearchCriteria(String searchCriteria)
+ {
+ this.searchCriteria = searchCriteria;
+ }
- /**
- * @return Returns the person context.
- */
- public Node getPerson()
- {
- return this.person;
- }
+ /**
+ * @return Returns the confirm password.
+ */
+ public String getConfirm()
+ {
+ return this.confirm;
+ }
- /**
- * @param person The person context to set.
- */
- public void setPerson(Node person)
- {
- this.person = person;
- this.userName = (String)person.getProperties().get(ContentModel.PROP_USERNAME);
- }
-
- public Long getUserUsage(String userName)
- {
- long usage = getContentUsageService().getUserUsage(userName);
- return (usage == -1 ? null : usage);
- }
-
- public Long getUserUsage()
- {
- long usage = getContentUsageService().getUserUsage(this.userName);
- return (usage == -1 ? null : usage);
- }
-
- public Long getUserQuota()
- {
- long quota = getContentUsageService().getUserQuota(this.userName);
- return (quota == -1 ? null : quota);
- }
-
- public boolean getUsagesEnabled()
- {
- return getContentUsageService().getEnabled();
- }
-
- public String getPersonDescription()
- {
- ContentService cs = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getContentService();
- ContentReader reader = cs.getReader(this.person.getNodeRef(), ContentModel.PROP_PERSONDESC);
- if (reader != null && reader.exists())
- {
- return Utils.stripUnsafeHTMLTags(reader.getContentString()).replace("\r\n", "
");
- }
- else
- {
- return null;
- }
- }
-
- public String getAvatarUrl()
- {
- String avatarUrl = null;
-
- List refs = getNodeService().getTargetAssocs(this.person.getNodeRef(), ContentModel.ASSOC_AVATAR);
- if (refs.size() == 1)
- {
- NodeRef photoRef = refs.get(0).getTargetRef();
- String name = (String)getNodeService().getProperty(photoRef, ContentModel.PROP_NAME);
- avatarUrl = DownloadContentServlet.generateBrowserURL(photoRef, name);
- }
-
- return avatarUrl;
- }
+ /**
+ * @param confirm The confirm password to set.
+ */
+ public void setConfirm(String confirm)
+ {
+ this.confirm = confirm;
+ }
+
+ /**
+ * @return Returns the password.
+ */
+ public String getPassword()
+ {
+ return this.password;
+ }
+
+ /**
+ * @param password The password to set.
+ */
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ /**
+ * @return Returns the old password.
+ */
+ public String getOldPassword()
+ {
+ return this.oldPassword;
+ }
+
+ /**
+ * @param oldPassword The old password to set.
+ */
+ public void setOldPassword(String oldPassword)
+ {
+ this.oldPassword = oldPassword;
+ }
+
+ /**
+ * @return Returns the person context.
+ */
+ public Node getPerson()
+ {
+ return this.person;
+ }
+
+ /**
+ * @param person The person context to set.
+ */
+ public void setPerson(final Node p)
+ {
+ // perform the set in a txn as certain bean calls require it
+ FacesContext context = FacesContext.getCurrentInstance();
+ RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(context);
+ RetryingTransactionCallback callback = new RetryingTransactionCallback()
+ {
+ public Object execute() throws Throwable
+ {
+ person = p;
+ userName = (String)person.getProperties().get(ContentModel.PROP_USERNAME);
+
+ // rebuild the property immutability map helper object
+ immutabilty = new PropertyImmutabilityMap(
+ getUserRegistrySynchronizer().getPersonMappedProperties(userName));
+
+ return null;
+ }
+ };
+ try
+ {
+ txnHelper.doInTransaction(callback, false);
+ }
+ catch (Throwable e)
+ {
+ // reset the flag so we can re-attempt the operation
+ if (e instanceof ReportedException == false)
+ {
+ Utils.addErrorMessage(e.getMessage(), e);
+ }
+ ReportedException.throwIfNecessary(e);
+ }
+ }
+
+ public Long getUserUsage(String userName)
+ {
+ long usage = getContentUsageService().getUserUsage(userName);
+ return (usage == -1 ? null : usage);
+ }
+
+ public Long getUserUsage()
+ {
+ long usage = getContentUsageService().getUserUsage(this.userName);
+ return (usage == -1 ? null : usage);
+ }
+
+ public Long getUserQuota()
+ {
+ long quota = getContentUsageService().getUserQuota(this.userName);
+ return (quota == -1 ? null : quota);
+ }
+
+ public boolean getUsagesEnabled()
+ {
+ return getContentUsageService().getEnabled();
+ }
+
+ public String getPersonDescription()
+ {
+ ContentService cs = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getContentService();
+ ContentReader reader = cs.getReader(this.person.getNodeRef(), ContentModel.PROP_PERSONDESC);
+ if (reader != null && reader.exists())
+ {
+ return Utils.stripUnsafeHTMLTags(reader.getContentString()).replace("\r\n", "
");
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public String getAvatarUrl()
+ {
+ String avatarUrl = null;
+
+ List refs = getNodeService().getTargetAssocs(this.person.getNodeRef(), ContentModel.ASSOC_AVATAR);
+ if (refs.size() == 1)
+ {
+ NodeRef photoRef = refs.get(0).getTargetRef();
+ String name = (String) getNodeService().getProperty(photoRef, ContentModel.PROP_NAME);
+ avatarUrl = DownloadContentServlet.generateBrowserURL(photoRef, name);
+ }
+
+ return avatarUrl;
+ }
+
+ public Map getImmutability()
+ {
+ return this.immutabilty;
+ }
+
+ /**
+ * Map of person property to immutability
+ * The Map interface is implemented to allow JSF expressions such as
+ * #{DialogBean.bean.properties.immutability.propertyname}
+ */
+ public class PropertyImmutabilityMap implements Map, Serializable
+ {
+ final private Set props;
+
+ PropertyImmutabilityMap(Set props)
+ {
+ this.props = props;
+ }
+
+ public void clear()
+ {
+ }
+
+ public boolean containsKey(Object k)
+ {
+ boolean contains = false;
+ if (k instanceof String && ((String)k).length() != 0)
+ {
+ String s = (String)k;
+ if (s.charAt(0) == '{' && s.indexOf('}') != -1)
+ {
+ contains = this.props.contains(k);
+ }
+ else
+ {
+ // simple property name - assume and apply CM namespace
+ contains = this.props.contains(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, s));
+ }
+ }
+ return contains;
+ }
+
+ public boolean containsValue(Object v)
+ {
+ return false;
+ }
+
+ public Set> entrySet()
+ {
+ return null;
+ }
+
+ public Boolean get(Object k)
+ {
+ return containsKey(k);
+ }
+
+ public boolean isEmpty()
+ {
+ return this.props.size() != 0;
+ }
+
+ public Set keySet()
+ {
+ return null;
+ }
+
+ public Boolean put(String k, Boolean v)
+ {
+ return null;
+ }
+
+ public void putAll(Map extends String, ? extends Boolean> m)
+ {
+ }
+
+ public Boolean remove(Object k)
+ {
+ return null;
+ }
+
+ public int size()
+ {
+ return this.props.size();
+ }
+
+ public Collection values()
+ {
+ return null;
+ }
+ }
}
diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java
index f2d35e2b15..fa4ad3f206 100644
--- a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java
+++ b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java
@@ -464,11 +464,21 @@ public class CreateWebContentWizard extends CreateContentWizard
if (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null)
{
- this.formInstanceData = getFormsService().getFormInstanceData(-1, this.createdPath);
- this.renditions = this.formInstanceData.getRenditions();
- if (logger.isDebugEnabled())
- logger.debug("reset form instance data " + this.formInstanceData.getName() +
- " and " + this.renditions.size() + " rendition(s) to main store");
+ try
+ {
+ this.formInstanceData = getFormsService().getFormInstanceData(-1, this.createdPath);
+ this.renditions = this.formInstanceData.getRenditions();
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("reset form instance data " + this.formInstanceData.getName() +
+ " and " + this.renditions.size() + " rendition(s) to main store");
+ }
+ }
+ catch (FormNotFoundException fnfe)
+ {
+ logger.warn(fnfe);
+ }
}
this.avmBrowseBean.setAvmActionNode(new AVMNode(this.getAvmService().lookup(-1, this.createdPath)));
diff --git a/source/java/org/alfresco/web/bean/wcm/DeleteFileDialog.java b/source/java/org/alfresco/web/bean/wcm/DeleteFileDialog.java
index 6005b33936..8ba3b37734 100644
--- a/source/java/org/alfresco/web/bean/wcm/DeleteFileDialog.java
+++ b/source/java/org/alfresco/web/bean/wcm/DeleteFileDialog.java
@@ -33,6 +33,7 @@ import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.forms.*;
+import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -189,7 +190,6 @@ public class DeleteFileDialog extends BaseDialogBean
node.getName(),
fid.getName(),
fid.getRenditions().size() - 1);
-
}
catch (FileNotFoundException fnfe)
{
@@ -198,11 +198,18 @@ public class DeleteFileDialog extends BaseDialogBean
}
else if (node.hasAspect(WCMAppModel.ASPECT_FORM_INSTANCE_DATA))
{
- final FormInstanceData fid = this.getFormsService().getFormInstanceData(node.getNodeRef());
- return MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(),
- "delete_form_instance_data_confirm"),
- fid.getName(),
- fid.getRenditions().size());
+ try
+ {
+ final FormInstanceData fid = this.getFormsService().getFormInstanceData(node.getNodeRef());
+ return MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(),
+ "delete_form_instance_data_confirm"),
+ fid.getName(),
+ fid.getRenditions().size());
+ }
+ catch (FormNotFoundException fnfe)
+ {
+ // ignore
+ }
}
return MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(),
"delete_avm_file_confirm"),
diff --git a/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java
index fde3d7089b..c4468a5117 100644
--- a/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java
+++ b/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java
@@ -18,10 +18,11 @@
*/
package org.alfresco.web.bean.wcm;
-import java.util.ArrayList;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.avm.locking.AVMLock;
@@ -48,7 +49,7 @@ public class EditWebContentWizard extends CreateWebContentWizard
private AVMNode avmNode;
private Form form;
- protected List locksPresentAtInit = null;
+ protected Set existingLocks = null;
// ------------------------------------------------------------------------------
// Wizard implementation
@@ -67,11 +68,14 @@ public class EditWebContentWizard extends CreateWebContentWizard
logger.debug("path is " + this.avmNode.getPath());
this.createdPath = AVMUtil.getCorrespondingPathInPreviewStore(this.avmNode.getPath());
- this.formInstanceData = this.getFormsService().getFormInstanceData(-1, this.createdPath);
final WebProject webProject = new WebProject(this.createdPath);
+
try
{
+ this.formInstanceData = this.getFormsService().getFormInstanceData(-1, this.createdPath);
this.formName = this.formInstanceData.getForm().getName();
+ this.fileName = this.formInstanceData.getName();
+
this.form = webProject.getForm(this.formName);
}
catch (FormNotFoundException fnfe)
@@ -79,16 +83,15 @@ public class EditWebContentWizard extends CreateWebContentWizard
Utils.addErrorMessage(fnfe.getMessage(), fnfe);
}
this.content = this.getAvmService().getContentReader(-1, this.createdPath).getContentString();
- this.fileName = this.formInstanceData.getName();
this.mimeType = MimetypeMap.MIMETYPE_XML;
// calculate which locks are present at init time
- this.locksPresentAtInit = new ArrayList(4);
+ this.existingLocks = new HashSet(4);
AVMLock lock = this.getAvmLockingService().getLock(AVMUtil.getStoreId(this.createdPath),
AVMUtil.getStoreRelativePath(this.createdPath));
if (lock != null)
{
- this.locksPresentAtInit.add(this.createdPath);
+ this.existingLocks.add(this.createdPath);
if (logger.isDebugEnabled())
logger.debug("Lock exists for xml instance " + this.createdPath + " at initialisation");
@@ -101,7 +104,7 @@ public class EditWebContentWizard extends CreateWebContentWizard
AVMUtil.getStoreRelativePath(path));
if (lock != null)
{
- this.locksPresentAtInit.add(path);
+ this.existingLocks.add(path);
if (logger.isDebugEnabled())
logger.debug("Lock exists for rendition " + path + " at initialisation");
@@ -114,9 +117,9 @@ public class EditWebContentWizard extends CreateWebContentWizard
{
if (this.formInstanceData != null && this.renditions != null)
{
- if (this.locksPresentAtInit.contains(this.createdPath) == false)
+ if (this.existingLocks.contains(this.createdPath) == false)
{
- // there wasn't a lock on the form at the start of the
+ // there wasn't an existing lock on the form at the start of the
// wizard so remove the one present now
if (logger.isDebugEnabled())
logger.debug("removing form instance data lock from " +
@@ -126,12 +129,12 @@ public class EditWebContentWizard extends CreateWebContentWizard
this.getAvmLockingService().removeLock(AVMUtil.getStoreId(this.createdPath),
AVMUtil.getStoreRelativePath(this.createdPath));
}
-
+
for (Rendition r : this.renditions)
{
String path = r.getPath();
- if (this.locksPresentAtInit.contains(path) == false)
+ if (this.existingLocks.contains(path) == false)
{
// there wasn't a lock on the rendition at the start of
// the wizard so remove the one present now
@@ -139,7 +142,7 @@ public class EditWebContentWizard extends CreateWebContentWizard
logger.debug("removing lock from rendition " +
AVMUtil.getCorrespondingPathInMainStore(path) +
" as user chose to cancel and it wasn't present at initialisation");
-
+
this.getAvmLockingService().removeLock(AVMUtil.getStoreId(path),
AVMUtil.getStoreRelativePath(path));
}
@@ -222,8 +225,13 @@ public class EditWebContentWizard extends CreateWebContentWizard
// if the renditions were locked before the regenerate, move the lock back to main store
String path = rr.getPath();
- if (this.locksPresentAtInit.contains(path))
+ if (rr.getExistingLock() != null)
{
+ this.existingLocks.add(path);
+ }
+
+ if (this.existingLocks.contains(path))
+ {
if (logger.isDebugEnabled())
logger.debug("transferring existing lock for " + path +
" back to " + AVMUtil.getCorrespondingMainStoreName(AVMUtil.getStoreName(path)));
@@ -241,14 +249,21 @@ public class EditWebContentWizard extends CreateWebContentWizard
final Rendition r = rr.getRendition();
this.renditions.add(r);
+ String path = r.getPath();
+
+ if (rr.getExistingLock() != null)
+ {
+ this.existingLocks.add(path);
+ }
+
if (logger.isDebugEnabled())
- logger.debug("transferring lock for " + r.getPath() +
- " back to " + AVMUtil.getCorrespondingMainStoreName(AVMUtil.getStoreName(r.getPath())));
+ logger.debug("transferring lock for " + path +
+ " back to " + AVMUtil.getCorrespondingMainStoreName(AVMUtil.getStoreName(path)));
- this.getAvmLockingService().modifyLock(AVMUtil.getStoreId(r.getPath()),
- AVMUtil.getStoreRelativePath(r.getPath()),
+ this.getAvmLockingService().modifyLock(AVMUtil.getStoreId(path),
+ AVMUtil.getStoreRelativePath(path),
null,
- AVMUtil.getCorrespondingMainStoreName(AVMUtil.getStoreName(r.getPath())),
+ AVMUtil.getCorrespondingMainStoreName(AVMUtil.getStoreName(path)),
null,
null);
}
diff --git a/source/java/org/alfresco/web/bean/wcm/PromptForWebFormDialog.java b/source/java/org/alfresco/web/bean/wcm/PromptForWebFormDialog.java
index c3a9dd24b4..67288b6167 100644
--- a/source/java/org/alfresco/web/bean/wcm/PromptForWebFormDialog.java
+++ b/source/java/org/alfresco/web/bean/wcm/PromptForWebFormDialog.java
@@ -144,9 +144,11 @@ public class PromptForWebFormDialog extends BaseDialogBean
WCMAppModel.ASPECT_FORM_INSTANCE_DATA))
{
// build a status message if this is an error case
- final FormInstanceData fid = this.getFormsService().getFormInstanceData(this.getAvmNode().getVersion(), avmPath);
+
+ FormInstanceData fid = null;
try
{
+ fid = this.getFormsService().getFormInstanceData(this.getAvmNode().getVersion(), avmPath);
final Form f = fid.getForm();
this.formName = f.getName();
@@ -162,14 +164,19 @@ public class PromptForWebFormDialog extends BaseDialogBean
? "prompt_for_web_form_form_not_found_error_in_web_project"
: "prompt_for_web_form_form_not_found_error");
msg = Application.getMessage(FacesContext.getCurrentInstance(), msg);
- msg = (fnfe.getWebProject() != null
- ? MessageFormat.format(msg,
- fnfe.getFormName(),
- fid.getName(),
- fnfe.getWebProject().getName())
- : MessageFormat.format(msg,
- fnfe.getFormName(),
- fid.getName()));
+
+ if (fid != null)
+ {
+ msg = (fnfe.getWebProject() != null
+ ? MessageFormat.format(msg,
+ fnfe.getFormName(),
+ fid.getName(),
+ fnfe.getWebProject().getName())
+ : MessageFormat.format(msg,
+ fnfe.getFormName(),
+ fid.getName()));
+ }
+
this.avmBrowseBean.displayStatusMessage(FacesContext.getCurrentInstance(), msg);
}
}
diff --git a/source/java/org/alfresco/web/bean/wcm/RegenerateRenditionsWizard.java b/source/java/org/alfresco/web/bean/wcm/RegenerateRenditionsWizard.java
index a94defbbc8..1550d51d9e 100644
--- a/source/java/org/alfresco/web/bean/wcm/RegenerateRenditionsWizard.java
+++ b/source/java/org/alfresco/web/bean/wcm/RegenerateRenditionsWizard.java
@@ -525,7 +525,16 @@ public class RegenerateRenditionsWizard
{
final String avmPath = AVMNodeConverter.ToAVMVersionPath(row.getNodeRef()).getSecond();
final String previewAvmPath = AVMUtil.getCorrespondingPathInPreviewStore(avmPath);
- result.add(getFormsService().getFormInstanceData(-1, previewAvmPath));
+
+ try
+ {
+ FormInstanceData fid = getFormsService().getFormInstanceData(-1, previewAvmPath);
+ result.add(fid);
+ }
+ catch (final FormNotFoundException fnfe)
+ {
+ // ignore
+ }
}
return result;
@@ -661,9 +670,10 @@ public class RegenerateRenditionsWizard
if (this.regenerateScope.equals(REGENERATE_SCOPE_ALL) ||
this.regenerateScope.equals(REGENERATE_SCOPE_FORM))
{
- final FormInstanceData fid = this.formsService.getFormInstanceData(-1, previewAvmPath);
+ FormInstanceData fid = null;
try
{
+ fid = this.formsService.getFormInstanceData(-1, previewAvmPath);
final List regenResults = fid.regenerateRenditions();
for (final FormInstanceData.RegenerateResult rr : regenResults)
{
@@ -687,7 +697,7 @@ public class RegenerateRenditionsWizard
}
catch (FormNotFoundException fnfe)
{
- logger.warn("regenerating renditions of " + fid.getPath() + ": " + fnfe.getMessage(), fnfe);
+ logger.warn("regenerating renditions of " + previewAvmPath + ": " + fnfe.getMessage(), fnfe);
}
}
else
diff --git a/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java b/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java
index 640141c73d..f0872bd8f2 100644
--- a/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java
+++ b/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java
@@ -59,7 +59,9 @@ import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.BrowseBean;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Repository;
+import org.alfresco.web.forms.Form;
import org.alfresco.web.forms.FormInstanceData;
+import org.alfresco.web.forms.FormNotFoundException;
import org.alfresco.web.forms.FormsService;
import org.alfresco.web.forms.Rendition;
import org.alfresco.web.ui.common.Utils;
@@ -724,7 +726,7 @@ public class SubmitDialog extends BaseDialogBean
for (AVMNodeDescriptor node : selected)
{
- if (AVMWorkflowUtil.isInActiveWorkflow(this.avmBrowseBean.getStagingStore(), node))
+ if (AVMWorkflowUtil.isInActiveWorkflow(AVMUtil.getStoreName(node.getPath()), node))
{
this.warningItems.add(new ItemWrapper(node));
continue;
@@ -750,42 +752,61 @@ public class SubmitDialog extends BaseDialogBean
// item is a form (note: could be deleted) or a rendition
FormInstanceData fid = null;
- if (isRendition)
+ try
{
- // found a generated rendition asset - locate the parent form instance data file
- // and use this to find all generated assets that are appropriate
- // NOTE: this path value is store relative
- fid = getFormsService().getRendition(ref).getPrimaryFormInstanceData(true);
+ if (isRendition)
+ {
+ // found a generated rendition asset - locate the parent form instance data file
+ // and use this to find all generated assets that are appropriate
+ // NOTE: this path value is store relative
+ fid = getFormsService().getRendition(ref).getPrimaryFormInstanceData(true);
+ }
+ else
+ {
+ fid = getFormsService().getFormInstanceData(ref);
+ }
}
- else
+ catch (FormNotFoundException fnfe)
{
- fid = getFormsService().getFormInstanceData(ref);
+ logger.warn(fnfe);
}
- // add the form instance data file to the list for submission
- if (!submittedPaths.contains(fid.getPath()))
+ if (fid != null)
{
- this.submitItems.add(new ItemWrapper(getAvmService().lookup(-1, fid.getPath(), true)));
- submittedPaths.add(fid.getPath());
- }
-
- // locate renditions for this form instance data file and add to list for submission
- for (final Rendition rendition : fid.getRenditions(true))
- {
- final String renditionPath = rendition.getPath();
- if (!submittedPaths.contains(renditionPath))
- {
- this.submitItems.add(new ItemWrapper(getAvmService().lookup(-1, renditionPath, true)));
- submittedPaths.add(renditionPath);
- }
- }
-
- // lookup the workflow defaults for that form and store into the list of available workflows
- WorkflowDefinition defaultWfDef = fid.getForm().getDefaultWorkflow();
- if (defaultWfDef != null)
- {
- this.workflows.add(new FormWorkflowWrapper(defaultWfDef.getName(),
- fid.getForm().getDefaultWorkflowParameters()));
+ // add the form instance data file to the list for submission
+ if (!submittedPaths.contains(fid.getPath()))
+ {
+ this.submitItems.add(new ItemWrapper(getAvmService().lookup(-1, fid.getPath(), true)));
+ submittedPaths.add(fid.getPath());
+ }
+
+ // locate renditions for this form instance data file and add to list for submission
+ for (final Rendition rendition : fid.getRenditions(true))
+ {
+ final String renditionPath = rendition.getPath();
+ if (!submittedPaths.contains(renditionPath))
+ {
+ this.submitItems.add(new ItemWrapper(getAvmService().lookup(-1, renditionPath, true)));
+ submittedPaths.add(renditionPath);
+ }
+ }
+
+ // lookup the workflow defaults for that form and store into the list of available workflows
+ Form f = null;
+ try
+ {
+ f = fid.getForm();
+ WorkflowDefinition defaultWfDef = f.getDefaultWorkflow();
+ if (defaultWfDef != null)
+ {
+ this.workflows.add(new FormWorkflowWrapper(defaultWfDef.getName(),
+ fid.getForm().getDefaultWorkflowParameters()));
+ }
+ }
+ catch (FormNotFoundException fnfe)
+ {
+ logger.warn(fnfe);
+ }
}
// See WCM-1090 ACT-1551
diff --git a/source/java/org/alfresco/web/forms/FormInstanceData.java b/source/java/org/alfresco/web/forms/FormInstanceData.java
index 935fcb369a..f862731c4d 100644
--- a/source/java/org/alfresco/web/forms/FormInstanceData.java
+++ b/source/java/org/alfresco/web/forms/FormInstanceData.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.Serializable;
import java.util.List;
+import org.alfresco.service.cmr.avm.locking.AVMLock;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
@@ -45,25 +46,30 @@ public interface FormInstanceData
private final String path;
private final Rendition r;
private final Exception e;
+ private final AVMLock lock; // existing lock otherwise null
public RegenerateResult(final RenderingEngineTemplate ret,
- final String path,
- final Rendition r)
+ final String path,
+ final Rendition r,
+ final AVMLock lock)
{
this.ret = ret;
this.r = r;
this.e = null;
this.path = path;
+ this.lock = lock;
}
-
+
public RegenerateResult(final RenderingEngineTemplate ret,
final String path,
- final Exception e)
+ final Exception e,
+ final AVMLock lock)
{
this.ret = ret;
this.e = e;
this.r = null;
this.path = path;
+ this.lock = lock;
}
public RenderingEngineTemplate getRenderingEngineTemplate()
@@ -85,6 +91,11 @@ public interface FormInstanceData
{
return this.e;
}
+
+ public AVMLock getExistingLock()
+ {
+ return this.lock;
+ }
}
/////////////////////////////////////////////////////////////////////////////
diff --git a/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java b/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java
index fd2b6bdd89..99b1ac5621 100644
--- a/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java
+++ b/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java
@@ -40,9 +40,11 @@ import org.alfresco.service.cmr.avm.locking.AVMLockingService;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.wcm.AVMUtil;
+import org.alfresco.web.bean.wcm.WebProject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
@@ -60,11 +62,22 @@ import org.xml.sax.SAXException;
private static final Log logger = LogFactory.getLog(RenditionImpl.class);
private final NodeRef nodeRef;
+ private final WebProject webProject;
+
private transient FormsService formsService;
/* package */ FormInstanceDataImpl(final NodeRef nodeRef,
final FormsService formsService)
{
+ this(nodeRef, formsService, null);
+ }
+
+ /* package */ FormInstanceDataImpl(final NodeRef nodeRef,
+ final FormsService formsService,
+ final WebProject webProject)
+ {
+ this.webProject = webProject;
+
if (nodeRef == null)
{
throw new NullPointerException();
@@ -152,6 +165,10 @@ import org.xml.sax.SAXException;
}
catch (FormNotFoundException fnfe)
{
+ if (webProject != null)
+ {
+ throw new FormNotFoundException(parentFormName, webProject, this);
+ }
throw new FormNotFoundException(parentFormName, this);
}
}
@@ -189,7 +206,6 @@ import org.xml.sax.SAXException;
new HashSet(this.getForm().getRenderingEngineTemplates());
final List result = new LinkedList();
// regenerate existing renditions
- boolean renditionLockedBefore = false;
String path = null;
for (final Rendition r : this.getRenditions())
@@ -207,13 +223,15 @@ import org.xml.sax.SAXException;
continue;
}
}
-
}
+
final RenderingEngineTemplate ret = r.getRenderingEngineTemplate();
if (ret == null || !allRets.contains(ret))
{
continue;
}
+
+ AVMLock lock = null;
try
{
if (logger.isDebugEnabled())
@@ -221,13 +239,10 @@ import org.xml.sax.SAXException;
logger.debug("regenerating rendition " + r + " using template " + ret);
}
- renditionLockedBefore = false;
path = r.getPath();
- AVMLock lock = avmLockService.getLock(AVMUtil.getStoreId(path), AVMUtil.getStoreRelativePath(path));
+ lock = avmLockService.getLock(AVMUtil.getStoreId(path), AVMUtil.getStoreRelativePath(path));
if (lock != null)
{
- renditionLockedBefore = true;
-
if (logger.isDebugEnabled())
{
logger.debug("Lock already exists for " + path);
@@ -236,14 +251,14 @@ import org.xml.sax.SAXException;
ret.render(this, r);
allRets.remove(ret);
- result.add(new RegenerateResult(ret, path, r));
+ result.add(new RegenerateResult(ret, path, r, lock));
}
catch (Exception e)
{
- result.add(new RegenerateResult(ret, path, e));
+ result.add(new RegenerateResult(ret, path, e, lock));
// remove lock if there wasn't one before
- if (renditionLockedBefore == false)
+ if (lock == null)
{
avmLockService.removeLock(AVMUtil.getStoreId(path), AVMUtil.getStoreRelativePath(path));
@@ -255,47 +270,84 @@ import org.xml.sax.SAXException;
}
}
+ // get current username for lock checks
+ String username = Application.getCurrentUser(FacesContext.getCurrentInstance()).getUserName();
+
// render all renditions for newly added templates
for (final RenderingEngineTemplate ret : allRets)
{
+ AVMLock lock = null;
+ boolean lockModified = false;
+
try
{
- renditionLockedBefore = false;
- path = ret.getOutputPathForRendition(this, originalParentAvmPath, getName());
-
+ path = ret.getOutputPathForRendition(this, originalParentAvmPath, getName().replaceAll("(.+)\\..*", "$1"));
+
if (logger.isDebugEnabled())
{
logger.debug("regenerating rendition of " + this.getPath() +
" at " + path + " using template " + ret);
}
- AVMLock lock = avmLockService.getLock(AVMUtil.getStoreId(path), AVMUtil.getStoreRelativePath(path));
+ String storeId = AVMUtil.getStoreId(path);
+ String storePath = AVMUtil.getStoreRelativePath(path);
+ String storeName = AVMUtil.getStoreName(path);
+
+ lock = avmLockService.getLock(storeId, storePath);
+
if (lock != null)
{
- renditionLockedBefore = true;
-
if (logger.isDebugEnabled())
{
logger.debug("Lock already exists for " + path);
}
+
+ if (lock.getStore().equals(storeName) == false)
+ {
+ if (lock.getOwners().contains(username))
+ {
+ lockModified = true;
+
+ // lock already exists on path, check it's owned by the current user
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("transferring lock from " + lock.getStore() + " to " + storeName + " for path: " + path);
+ }
+
+ avmLockService.modifyLock(storeId, storePath, null, storeName, null, null);
+ }
+ }
}
- result.add(new RegenerateResult(ret, path, ret.render(this, path)));
+ result.add(new RegenerateResult(ret, path, ret.render(this, path), lock));
}
catch (Exception e)
{
- result.add(new RegenerateResult(ret, path, e));
+ result.add(new RegenerateResult(ret, path, e, lock));
- // remove lock if there wasn't one before
- if (renditionLockedBefore == false)
+ String storeId = AVMUtil.getStoreId(path);
+ String storePath = AVMUtil.getStoreRelativePath(path);
+ String storeName = AVMUtil.getStoreName(path);
+
+ if (lock == null)
{
- avmLockService.removeLock(AVMUtil.getStoreId(path), AVMUtil.getStoreRelativePath(path));
+ // remove lock if there wasn't one before
+ avmLockService.removeLock(storeId, storePath);
if (logger.isDebugEnabled())
{
logger.debug("Removed lock for " + path + " as it failed to generate");
}
}
+ else if (lockModified)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("transferring lock from " + storeName + " to " + lock.getStore() + " for path: " + path);
+ }
+
+ avmLockService.modifyLock(storeId, storePath, null, lock.getStore(), null, null);
+ }
}
}
return result;
diff --git a/source/java/org/alfresco/web/forms/FormsService.java b/source/java/org/alfresco/web/forms/FormsService.java
index a9850d1b93..bdf54752f3 100644
--- a/source/java/org/alfresco/web/forms/FormsService.java
+++ b/source/java/org/alfresco/web/forms/FormsService.java
@@ -30,6 +30,7 @@ import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.policy.Behaviour;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
+import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -290,32 +291,27 @@ public final class FormsService
return result;
}
- public FormInstanceData getFormInstanceData(final int version, final String avmPath)
+ public FormInstanceData getFormInstanceData(final int version, final String avmPath) throws FormNotFoundException
{
return this.getFormInstanceData(AVMNodeConverter.ToNodeRef(version, avmPath));
}
- public FormInstanceData getFormInstanceData(final NodeRef nodeRef)
+ public FormInstanceData getFormInstanceData(final NodeRef nodeRef) throws FormNotFoundException
{
final String avmPath = AVMNodeConverter.ToAVMVersionPath(nodeRef).getSecond();
final WebProject webProject = new WebProject(avmPath);
- return new FormInstanceDataImpl(nodeRef, this)
+
+ FormInstanceData fid = null;
+ try
{
- @Override
- public Form getForm()
- throws FormNotFoundException
- {
- final Form f = super.getForm();
- try
- {
- return webProject.getForm(f.getName());
- }
- catch (FormNotFoundException fnfne)
- {
- throw new FormNotFoundException(f, webProject, this);
- }
- }
- };
+ fid = new FormInstanceDataImpl(nodeRef, this, webProject);
+ return fid;
+ }
+ catch (IllegalArgumentException iae)
+ {
+ // note: FormNotFoundException extends FileNotFoundException
+ throw new FormNotFoundException(iae.getMessage());
+ }
}
public Rendition getRendition(final int version, final String avmPath)
diff --git a/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java b/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java
index 3056a7326e..0d2e46eb88 100644
--- a/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java
+++ b/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java
@@ -36,8 +36,11 @@ import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
+import javax.faces.context.FacesContext;
+
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.Pair;
+import org.alfresco.web.app.Application;
import org.alfresco.web.forms.XMLUtil;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.Pointer;
@@ -1930,7 +1933,7 @@ public class Schema2XForms implements Serializable
// add xforms:repeat section if this element re-occurs
if ((o.isOptional() && (controlType instanceof XSSimpleTypeDefinition || "anyType".equals(controlType.getName()))) ||
- (o.maximum == 1 && o.minimum == 1))
+ (o.maximum == 1 && o.minimum == 1) || (controlType instanceof XSComplexTypeDefinition && pathToRoot.equals("")))
{
return formSection;
}
@@ -2804,6 +2807,9 @@ public class Schema2XForms implements Serializable
final Map enumValues =
new LinkedHashMap(enumFacets.getLength());
+
+ final String nullValue = Application.getMessage(FacesContext.getCurrentInstance(), "please_select");
+ enumValues.put(nullValue, null);
for (int i = 0; i < enumFacets.getLength(); i++)
{
enumValues.put(enumFacets.item(i),
@@ -2824,29 +2830,6 @@ public class Schema2XForms implements Serializable
NamespaceConstants.XFORMS_PREFIX + ":appearance",
appearance);
- // add the "Please select..." instruction item for the combobox
- // and set the isValid attribute on the bind element to check for the "Please select..."
- // item to indicate that is not a valid value
- final String pleaseSelect = "[Select1 " + caption + "]";
- final Element item = this.createXFormsItem(xformsDocument, pleaseSelect, pleaseSelect);
- choices.appendChild(item);
-
- // not(purchaseOrder/state = '[Choose State]')
- //String isValidExpr = "not(" + bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS,"nodeset") + " = '" + pleaseSelect + "')";
- // ->no, not(. = '[Choose State]')
- final String isValidExpr = "not( . = '" + pleaseSelect + "')";
-
- //check if there was a constraint
- String constraint = bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "constraint");
-
- constraint = (constraint != null && constraint.length() != 0
- ? constraint + " and " + isValidExpr
- : isValidExpr);
-
- bindElement.setAttributeNS(NamespaceConstants.XFORMS_NS,
- NamespaceConstants.XFORMS_PREFIX + ":constraint",
- constraint);
-
control.appendChild(choices);
this.addChoicesForSelectControl(xformsDocument, choices, enumValues, resourceBundle);
return control;
@@ -3026,7 +3009,12 @@ public class Schema2XForms implements Serializable
for (int i = 0; lexicalPatterns != null && i < lexicalPatterns.getLength()
&& !SchemaSymbols.ATTVAL_INTEGER.equals(typeName); i++)
{
- constraints.add("chiba:match(., '" + lexicalPatterns.item(i) + "',null)");
+ String pattern = lexicalPatterns.item(i);
+ if (o.isOptional())
+ {
+ pattern= "(" + pattern + ")?";
+ }
+ constraints.add("chiba:match(., '" + pattern + "',null)");
}
}
diff --git a/source/java/org/alfresco/web/ui/repo/tag/PageTag.java b/source/java/org/alfresco/web/ui/repo/tag/PageTag.java
index 7c1be5423f..6625b4e2c6 100644
--- a/source/java/org/alfresco/web/ui/repo/tag/PageTag.java
+++ b/source/java/org/alfresco/web/ui/repo/tag/PageTag.java
@@ -211,7 +211,9 @@ public class PageTag extends TagSupport
out.write("\n");
}
- out.write("");
+ out.write("");
+ out.write("\n");
+ out.write("");
if (this.titleId != null && this.titleId.length() != 0)
{
out.write(Utils.encode(Application.getMessage(pageContext.getSession(), this.titleId)));
@@ -228,7 +230,6 @@ public class PageTag extends TagSupport
out.write("\n");
out.write("\n");
- out.write("\n");
}
// CSS style includes
diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml
index 396f888143..12ae1c2b61 100644
--- a/source/web/WEB-INF/faces-config-beans.xml
+++ b/source/web/WEB-INF/faces-config-beans.xml
@@ -645,6 +645,10 @@
contentUsageService#{ContentUsageService}
+
+ userRegistrySynchronizer
+ #{userRegistrySynchronizer}
+
diff --git a/source/web/jsp/users/edit-user-details.jsp b/source/web/jsp/users/edit-user-details.jsp
index 3ade1b70e1..b217679963 100644
--- a/source/web/jsp/users/edit-user-details.jsp
+++ b/source/web/jsp/users/edit-user-details.jsp
@@ -57,31 +57,31 @@ function updateButtonState()
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -89,11 +89,11 @@ function updateButtonState()
-
+
-
+
diff --git a/source/web/jsp/users/new-user-wizard/person-properties.jsp b/source/web/jsp/users/new-user-wizard/person-properties.jsp
index b286926c8c..a644692759 100644
--- a/source/web/jsp/users/new-user-wizard/person-properties.jsp
+++ b/source/web/jsp/users/new-user-wizard/person-properties.jsp
@@ -53,15 +53,15 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
diff --git a/source/web/jsp/users/user-console.jsp b/source/web/jsp/users/user-console.jsp
index 16969fdb17..6f27f81ef5 100644
--- a/source/web/jsp/users/user-console.jsp
+++ b/source/web/jsp/users/user-console.jsp
@@ -95,7 +95,7 @@
+ rendered="#{!NavigationBean.isGuest && NavigationBean.allowUserConfig && NavigationBean.allowUserChangePassword}" />
diff --git a/source/web/jsp/users/users.jsp b/source/web/jsp/users/users.jsp
index c9b4ed7b37..5e45311eb9 100644
--- a/source/web/jsp/users/users.jsp
+++ b/source/web/jsp/users/users.jsp
@@ -132,7 +132,7 @@
-
+
diff --git a/source/web/scripts/ajax/common.js b/source/web/scripts/ajax/common.js
index 78ef33fc56..6ec218da05 100644
--- a/source/web/scripts/ajax/common.js
+++ b/source/web/scripts/ajax/common.js
@@ -4,6 +4,34 @@
//
+function getIEEngine()
+{
+ var engine = null;
+
+ if (document.documentMode) // IE8
+ engine = document.documentMode;
+ else // IE 5-7
+ {
+ engine = 5; // Assume quirks mode unless proven otherwise
+ if (document.compatMode)
+ {
+ if (document.compatMode == "CSS1Compat")
+ engine = 7; // standards mode
+ }
+ }
+ return engine;
+
+}
+
+function getIEVersion()
+{
+ var rv = -1;
+ var ua = window.navigator.userAgent;
+ var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
+ if (re.exec(ua) != null) rv = parseFloat(RegExp.$1);
+ return rv;
+}
+
// Global Alfresco namespace object
if (typeof Alfresco == "undefined")
{
diff --git a/source/web/scripts/ajax/xforms.js b/source/web/scripts/ajax/xforms.js
index 21fbd916d9..88f54890a1 100644
--- a/source/web/scripts/ajax/xforms.js
+++ b/source/web/scripts/ajax/xforms.js
@@ -31,6 +31,9 @@
// Initiliaze dojo requirements, tinymce, and add a hook to load the xform.
////////////////////////////////////////////////////////////////////////////////
+alfresco.ieVersion = getIEVersion();
+alfresco.ieEngine = alfresco.ieVersion == -1 ? -1 : getIEEngine();
+
djConfig.parseWidgets = false;
dojo.require("dojo.lfx.html");
alfresco.log = alfresco.constants.DEBUG ? log : Class.empty;
@@ -682,8 +685,8 @@ alfresco.xforms.TextField = alfresco.xforms.Widget.extend({
if (this.isReadonly())
{
- this.widget.setAttribute("readonly", this.isReadonly());
- this.widget.setAttribute("disabled", this.isReadonly());
+ this.widget.setAttribute("readonly", true);
+ this.widget.setAttribute("disabled", true);
}
else
{
@@ -835,12 +838,13 @@ alfresco.xforms.PlainTextEditor = alfresco.xforms.Widget.extend({
this.widget.appendChild(document.createTextNode(initialValue));
if (this.isReadonly())
{
- this.widget.setAttribute("readonly", this.isReadonly());
+ this.widget.setAttribute("readonly", true);
}
var borderWidth = (this.widget.offsetWidth - this.widget.clientWidth);
var marginRight = 2;
this.widget.style.marginRight = marginRight + "px";
- this.widget.style.width = (((attach_point.offsetWidth - borderWidth - marginRight) / attach_point.offsetWidth) * 100) + "%";
+ var ow = attach_point.offsetWidth;
+ this.widget.style.width = (((ow - borderWidth - marginRight) / ow) * 100) + "%";
this.widget.onchange =this._textarea_changeHandler.bindAsEventListener(this);
},
@@ -2782,7 +2786,10 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
child.domContainer);
}
- var contentDiv = new Element("div", { "id": child.id + "-content", "class": "xformsGroupItem"});
+ var contentDiv = new Element("div", { "id": child.id + "-content", "class": "xformsGroupItem",
+ "styles": {"left": (child instanceof alfresco.xforms.AbstractGroup
+ ? "0px"
+ : "30%")}});
this._contentDivs[child.id] = contentDiv;
if (!(child instanceof alfresco.xforms.AbstractGroup))
{
@@ -2791,36 +2798,40 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
}
child.domContainer.appendChild(contentDiv);
- contentDiv.style.left = (child instanceof alfresco.xforms.AbstractGroup
- ? "0px"
- : "30%");
var contentDivWidth = "100%";
// the following does avoid devision by zero ... in contentDiv.offsetLeft / child.domContainer.offsetWidth
- if (!(child instanceof alfresco.xforms.AbstractGroup) && child.domContainer.offsetWidth != 0)
+ var ow = child.domContainer.offsetWidth;
+ if (!(child instanceof alfresco.xforms.AbstractGroup) && ow != 0)
{
- contentDivWidth = ((1 - (contentDiv.offsetLeft / child.domContainer.offsetWidth)) * 100) + "%";
+ contentDivWidth = ((1 - (contentDiv.offsetLeft / ow)) * 100) + "%";
}
contentDiv.style.width = contentDivWidth;
child.render(contentDiv);
+
+ var oh = contentDiv.offsetHeight;
+ var mt = contentDiv.getStyle("margin-top").toInt();
if (!(child instanceof alfresco.xforms.AbstractGroup))
{
child.domContainer.style.height =
- Math.max(contentDiv.offsetHeight +
- contentDiv.getStyle("margin-top").toInt() +
+ Math.max(oh +
+ mt +
contentDiv.getStyle("margin-bottom").toInt(),
20) + "px";
}
- alfresco.log(contentDiv.getAttribute("id") + " offsetTop is " + contentDiv.offsetTop);
- contentDiv.style.top = "-" + Math.max(0, contentDiv.offsetTop - contentDiv.getStyle("margin-top").toInt()) + "px";
+ var ot = contentDiv.offsetTop;
+ alfresco.log(contentDiv.getAttribute("id") + " offsetTop is " + ot);
+ var top = Math.max(0, ot - mt);
+ contentDiv.style.top = "-" + top + "px";
+
if (contentDiv.labelNode)
{
// contentDiv.labelNode.style.top = (contentDiv.offsetTop + ((.5 * contentDiv.offsetHeight) -
// (.5 * contentDiv.labelNode.offsetHeight))) + "px";
contentDiv.labelNode.style.position = "relative";
- contentDiv.labelNode.style.top = contentDiv.offsetTop + "px";
- contentDiv.labelNode.style.height = contentDiv.offsetHeight + "px";
+ contentDiv.labelNode.style.top = "0px";
+ contentDiv.labelNode.style.height = oh + "px";
contentDiv.labelNode.style.lineHeight = contentDiv.labelNode.style.height;
}
@@ -2939,18 +2950,19 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
contentDiv.style.position = "static";
contentDiv.style.top = "0px";
- contentDiv.style.left = "0px";
+// contentDiv.style.left = "0px";
contentDiv.style.position = "relative";
contentDiv.style.left = (this._children[i] instanceof alfresco.xforms.AbstractGroup
? "0px"
: "30%");
- if (this._children[i].domContainer.parentNode.offsetWidth != 0)
+ parentOffsetWidth = this._children[i].domContainer.parentNode.offsetWidth;
+ if (parentOffsetWidth != 0)
{
contentDiv.style.width = (this._children[i] instanceof alfresco.xforms.AbstractGroup
? "100%"
: (1 - (contentDiv.offsetLeft /
- this._children[i].domContainer.parentNode.offsetWidth)) * 100 + "%");
+ parentOffsetWidth)) * 100 + "%");
}
else
{
@@ -2964,26 +2976,17 @@ alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
if (!(this._children[i] instanceof alfresco.xforms.AbstractGroup))
{
+ var contentDivMarginTop = contentDiv.getStyle("margin-top").toInt();
this._children[i].domContainer.style.height =
Math.max(contentDiv.offsetHeight +
- contentDiv.getStyle("margin-top").toInt() +
+ contentDivMarginTop +
contentDiv.getStyle("margin-bottom").toInt(),
20) + "px";
}
- contentDiv.style.top = "-" + Math.max(0, contentDiv.offsetTop - contentDiv.getStyle("margin-top").toInt()) + "px";
+ contentDiv.style.top = "-" + Math.max(0, contentDiv.offsetTop -
+ (contentDivMarginTop == undefined ? contentDiv.getStyle("margin-top").toInt() : contentDivMarginTop)) + "px";
- var labelNode = contentDiv.labelNode;
- if (labelNode)
- {
-// labelNode.style.position = "static";
-// labelNode.style.top = "0px";
-// labelNode.style.left = "0px";
-// labelNode.style.position = "relative";
-
-// labelNode.style.top = (contentDiv.offsetTop + ((.5 * contentDiv.offsetHeight) -
-// (.5 * labelNode.offsetHeight))) + "px";
- }
}
},
@@ -3669,7 +3672,9 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
_updateDisplay: function(recursively)
{
- this.parent(recursively);
+ var recurseOnChildren = alfresco.ieVersion != -1 && alfresco.ieEngine < 8;
+ this.parent(recursively && !recurseOnChildren);
+
if (this.getViewRoot().focusedRepeat != null &&
(this.getViewRoot().focusedRepeat == this ||
this.getViewRoot().focusedRepeat.isAncestorOf(this)))
@@ -3699,7 +3704,7 @@ alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
this._repeatControls[i].style.backgroundColor = this._children[i].domContainer.getStyle("background-color");
- if (window.navigator.appName == "Microsoft Internet Explorer")
+ if (recurseOnChildren)
{
this._children[i]._updateDisplay(true);
}
@@ -4242,6 +4247,8 @@ alfresco.xforms.XForm = new Class({
{
if (xformsNode.childNodes[i].nodeType != document.ELEMENT_NODE)
{
+ if (alfresco.ieVersion == -1)
+ {
// fix for ETWOTWO-490, hide elements after rendering (Mozila/Firefox)
if ((i == (xformsNode.childNodes.length - 1)) &&
(parentWidget instanceof alfresco.xforms.SwitchGroup))
@@ -4254,6 +4261,7 @@ alfresco.xforms.XForm = new Class({
}
}
}
+ }
continue;
}
alfresco.log("loading " + xformsNode.childNodes[i].nodeName +