mappings = securityConfigBean.getDomainMappings();
@@ -2256,8 +2245,10 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
*
* @param diskCtx
*/
- public void initialiseRuntimeContext(AlfrescoContext diskCtx)
+ public void initialiseRuntimeContext(String uniqueName, AlfrescoContext diskCtx)
{
+ logger.debug("initialiseRuntimeContext" + diskCtx);
+
if (diskCtx.getStateCache() == null) {
// Set the state cache, use a hard coded standalone cache for now
@@ -2272,9 +2263,9 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
{
if(logger.isDebugEnabled())
{
- logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", shareName: "+ diskCtx.getShareName());
+ logger.debug("start hazelcast cache : " + clusterConfigBean.getClusterName() + ", uniqueName: "+ uniqueName);
}
- GenericConfigElement hazelConfig = createClusterConfig(diskCtx.getShareName());
+ GenericConfigElement hazelConfig = createClusterConfig(uniqueName);
HazelCastClusterFileStateCache hazel = new HazelCastClusterFileStateCache();
hazel.initializeCache(hazelConfig, this);
diskCtx.setStateCache(hazel);
@@ -2287,10 +2278,14 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
filesysConfig.addFileStateCache( diskCtx.getDeviceName(), standaloneCache);
diskCtx.setStateCache( standaloneCache);
}
-
- FileStateLockManager lockMgr = new FileStateLockManager(diskCtx.getStateCache());
- diskCtx.setLockManager(lockMgr);
- diskCtx.setOpLockManager(lockMgr);
+
+ // Register the state cache with the reaper thread
+ // has many side effects including initialisation of the cache
+ filesysConfig.addFileStateCache( diskCtx.getShareName(), diskCtx.getStateCache());
+
+ FileStateLockManager lockMgr = new FileStateLockManager(diskCtx.getStateCache());
+ diskCtx.setLockManager(lockMgr);
+ diskCtx.setOpLockManager(lockMgr);
}
catch ( InvalidConfigurationException ex)
{
@@ -2333,7 +2328,7 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean imp
}
- private GenericConfigElement createClusterConfig(String topicName) throws InvalidConfigurationException
+ private GenericConfigElement createClusterConfig(String topicName) throws InvalidConfigurationException
{
GenericConfigElement config = new GenericConfigElement("hazelcastStateCache");
GenericConfigElement clusterNameCfg = new GenericConfigElement("clusterName");
diff --git a/source/java/org/alfresco/filesys/repo/ContentContext.java b/source/java/org/alfresco/filesys/repo/ContentContext.java
index 6c21052a16..a806a8adc4 100644
--- a/source/java/org/alfresco/filesys/repo/ContentContext.java
+++ b/source/java/org/alfresco/filesys/repo/ContentContext.java
@@ -101,7 +101,7 @@ public class ContentContext extends AlfrescoContext
/**
* Class constructor
*
- *@param filesysName
+ *@param deviceName
* String
* @param storeName
* String
@@ -110,9 +110,9 @@ public class ContentContext extends AlfrescoContext
* @param rootNodeRef
* NodeRef
*/
- public ContentContext(String filesysName, String storeName, String rootPath, NodeRef rootNodeRef)
+ public ContentContext(String deviceName, String storeName, String rootPath, NodeRef rootNodeRef)
{
- setDeviceName(filesysName);
+ setDeviceName(deviceName);
setStoreName(storeName);
setRootPath(rootPath);
setRootNodeRef(rootNodeRef);
diff --git a/source/java/org/alfresco/filesys/repo/HomeShareMapper.java b/source/java/org/alfresco/filesys/repo/HomeShareMapper.java
deleted file mode 100644
index 937eb0c234..0000000000
--- a/source/java/org/alfresco/filesys/repo/HomeShareMapper.java
+++ /dev/null
@@ -1,420 +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.filesys.repo;
-
-import java.util.Enumeration;
-
-import org.alfresco.jlan.server.SrvSession;
-import org.alfresco.jlan.server.auth.ClientInfo;
-import org.alfresco.jlan.server.auth.InvalidUserException;
-import org.alfresco.jlan.server.config.InvalidConfigurationException;
-import org.alfresco.jlan.server.config.ServerConfiguration;
-import org.alfresco.jlan.server.core.InvalidDeviceInterfaceException;
-import org.alfresco.jlan.server.core.ShareMapper;
-import org.alfresco.jlan.server.core.ShareType;
-import org.alfresco.jlan.server.core.SharedDevice;
-import org.alfresco.jlan.server.core.SharedDeviceList;
-import org.alfresco.jlan.server.filesys.DiskSharedDevice;
-import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
-import org.springframework.extensions.config.ConfigElement;
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.filesys.alfresco.AlfrescoClientInfo;
-import org.alfresco.filesys.config.ServerConfigurationBean;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.InitializingBean;
-
-/**
- * Home Share Mapper Class
- *
- * Maps disk share lookup requests to the list of shares defined in the server
- * configuration and provides a dynamic home share mapped to the users home node.
- *
- * @author GKSpencer
- */
-public class HomeShareMapper implements ShareMapper, InitializingBean
-{
- // Logging
-
- private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
-
- // Home folder share name
-
- public static final String HOME_FOLDER_SHARE = "HOME";
-
- // Server configuration and sections
-
- private ServerConfiguration m_config;
- private FilesystemsConfigSection m_filesysConfig;
-
- // Filesystem driver to be used to create home shares
-
- private ContentDiskDriver m_driver;
-
- // Home folder share name
-
- private String m_homeShareName = HOME_FOLDER_SHARE;
-
- // Debug enable flag
-
- private boolean m_debug;
-
- /**
- * Default constructor
- */
- public HomeShareMapper()
- {
- }
-
-
- public void setServerConfiguration(ServerConfiguration config)
- {
- this.m_config = config;
- }
-
- public void setName(String shareName)
- {
- m_homeShareName = shareName;
- }
-
- public void setDebug(boolean debug)
- {
- this.m_debug = debug;
- }
-
- /**
- * Initialize the share mapper
- *
- * @param config ServerConfiguration
- * @param params ConfigElement
- * @exception InvalidConfigurationException
- */
- public void initializeMapper(ServerConfiguration config, ConfigElement params) throws InvalidConfigurationException
- {
- // Save the server configuration
-
- setServerConfiguration(config);
-
- // Check if the home share name has been specified
-
- String homeName = params.getAttribute("name");
- if ( homeName != null && homeName.length() > 0)
- setName(homeName);
-
- // Check if debug is enabled
-
- if (params != null && params.getChild("debug") != null)
- setDebug(true);
-
- // Complete initialization
- afterPropertiesSet();
- }
-
-
- public void afterPropertiesSet()
- {
- // Save the server configuration
- m_filesysConfig = (FilesystemsConfigSection) m_config.getConfigSection(FilesystemsConfigSection.SectionName);
-
- // Search for a filesystem that uses the content driver to use the driver when creating the home shares
-
- SharedDeviceList shares = m_filesysConfig.getShares();
-
- if ( shares != null)
- {
- Enumeration shrEnum = shares.enumerateShares();
-
- while ( shrEnum.hasMoreElements() && m_driver == null)
- {
- try
- {
- SharedDevice curShare = shrEnum.nextElement();
- if ( curShare.getInterface() instanceof ContentDiskDriver)
- m_driver = (ContentDiskDriver) curShare.getInterface();
- }
- catch (InvalidDeviceInterfaceException ex)
- {
- }
- }
- }
- }
-
- /**
- * Check if debug output is enabled
- *
- * @return boolean
- */
- public final boolean hasDebug()
- {
- return m_debug;
- }
-
- /**
- * Return the home folder share name
- *
- * @return String
- */
- public final String getHomeFolderName()
- {
- return m_homeShareName;
- }
-
- /**
- * Return the list of available shares.
- *
- * @param host String
- * @param sess SrvSession
- * @param allShares boolean
- * @return SharedDeviceList
- */
- public SharedDeviceList getShareList(String host, SrvSession sess, boolean allShares)
- {
- // Check if the user has a home folder, and the session does not currently have any
- // dynamic shares defined
-
- if ( sess != null && sess.hasClientInformation() && sess.hasDynamicShares() == false &&
- sess.getClientInformation() instanceof AlfrescoClientInfo)
- {
- AlfrescoClientInfo alfClient = (AlfrescoClientInfo) sess.getClientInformation();
- if ( alfClient.hasHomeFolder())
- {
- // Create the home folder share
-
- DiskSharedDevice homeShare = createHomeDiskShare( alfClient);
- sess.addDynamicShare(homeShare);
-
- // Debug
-
- if ( logger.isDebugEnabled())
- logger.debug("Added " + getHomeFolderName() + " share to list of shares for " + alfClient.getUserName());
- }
- }
-
- // Make a copy of the global share list and add the per session dynamic shares
-
- SharedDeviceList shrList = new SharedDeviceList(m_filesysConfig.getShares());
-
- if ( sess != null && sess.hasDynamicShares()) {
-
- // Add the per session dynamic shares
-
- shrList.addShares(sess.getDynamicShareList());
- }
-
- // Remove unavailable shares from the list and return the list
-
- if ( allShares == false)
- shrList.removeUnavailableShares();
- return shrList;
- }
-
- /**
- * Find a share using the name and type for the specified client.
- *
- * @param host String
- * @param name String
- * @param typ int
- * @param sess SrvSession
- * @param create boolean
- * @return SharedDevice
- * @exception InvalidUserException
- */
- public SharedDevice findShare(String tohost, String name, int typ, SrvSession sess, boolean create)
- throws Exception
- {
-
- // Check for the special HOME disk share
-
- SharedDevice share = null;
-
- if (( typ == ShareType.DISK || typ == ShareType.UNKNOWN) && name.equalsIgnoreCase(getHomeFolderName()) &&
- sess.getClientInformation() != null && m_driver != null) {
-
- // Get the client details
-
- ClientInfo client = sess.getClientInformation();
-
- // DEBUG
-
- if ( logger.isDebugEnabled())
- logger.debug("Map share " + name + ", type=" + ShareType.TypeAsString(typ) + ", client=" + client);
-
- // Check if the user has a home folder node
-
- if ( client != null && client instanceof AlfrescoClientInfo) {
-
- // Access the extended client information
-
- AlfrescoClientInfo alfClient = (AlfrescoClientInfo) client;
-
- if ( alfClient.hasHomeFolder()) {
-
- // Check if the share has already been created for the session
-
- if ( sess.hasDynamicShares()) {
-
- // Check if the required share exists in the sessions dynamic share list
-
- share = sess.getDynamicShareList().findShare(name, typ, false);
-
- // DEBUG
-
- if ( logger.isDebugEnabled())
- logger.debug(" Reusing existing dynamic share for " + name);
- }
-
- // Check if we found a share, if not then create a new dynamic share for the home directory
-
- if ( share == null && create == true) {
-
- // Create the home share mapped to the users home folder
-
- DiskSharedDevice diskShare = createHomeDiskShare( alfClient);
-
- // Add the new share to the sessions dynamic share list
-
- sess.addDynamicShare(diskShare);
- share = diskShare;
-
- // DEBUG
-
- if (logger.isDebugEnabled())
- logger.debug(" Mapped share " + name + " to " + alfClient.getHomeFolder());
- }
- }
- else
- throw new InvalidUserException("No home directory");
- }
- }
- else {
-
- // Find the required share by name/type. Use a case sensitive search first, if that fails use a case
- // insensitive search.
-
- share = m_filesysConfig.getShares().findShare(name, typ, false);
-
- if ( share == null) {
-
- // Try a case insensitive search for the required share
-
- share = m_filesysConfig.getShares().findShare(name, typ, true);
- }
- }
-
- // Check if the share is available
-
- if ( share != null && share.getContext() != null && share.getContext().isAvailable() == false)
- share = null;
-
- // Return the shared device, or null if no matching device was found
-
- return share;
- }
-
- /**
- * Delete temporary shares for the specified session
- *
- * @param sess SrvSession
- */
- public void deleteShares(SrvSession sess)
- {
-
- // Check if the session has any dynamic shares
-
- if ( sess.hasDynamicShares() == false)
- return;
-
- // Delete the dynamic shares
-
- SharedDeviceList shares = sess.getDynamicShareList();
- Enumeration enm = shares.enumerateShares();
-
- while ( enm.hasMoreElements()) {
-
- // Get the current share from the list
-
- SharedDevice shr = enm.nextElement();
-
- // Close the shared device
-
- shr.getContext().CloseContext();
-
- // DEBUG
-
- if (logger.isDebugEnabled())
- logger.debug("Deleted dynamic share " + shr);
- }
-
- // Clear the dynamic share list
-
- shares.removeAllShares();
- }
-
- /**
- * Close the share mapper, release any resources.
- */
- public void closeMapper()
- {
- // TODO Auto-generated method stub
-
- }
-
- /**
- * Create a disk share for the home folder
- *
- * @param alfClient AlfrescoClientInfo
- * @return DiskSharedDevice
- */
- private final DiskSharedDevice createHomeDiskShare(AlfrescoClientInfo alfClient)
- {
- // Make sure the client is an Alfresco client
-
- if ( alfClient != null) {
-
- // Create the disk driver and context
-
- ContentContext diskCtx = new ContentContext( getHomeFolderName(), "", "", alfClient.getHomeFolder());
-
- if(m_config instanceof ServerConfigurationBean)
- {
- ServerConfigurationBean config = (ServerConfigurationBean)m_config;
-
- config.initialiseRuntimeContext(diskCtx);
-
- // Enable file state caching
- // diskCtx.enableStateCache(serverConfigurationBean, true);
- }
- else
- {
- throw new AlfrescoRuntimeException("configuration error, unknown configuration bean");
- }
-
-
- // Create a temporary shared device for the users home directory
-
- return new DiskSharedDevice(getHomeFolderName(), m_driver, diskCtx, SharedDevice.Temporary);
- }
-
- // Invalid client type
-
- return null;
- }
-
-}
diff --git a/source/java/org/alfresco/repo/action/ActionDefinitionImpl.java b/source/java/org/alfresco/repo/action/ActionDefinitionImpl.java
index a6092ac81d..e63f9cafc3 100644
--- a/source/java/org/alfresco/repo/action/ActionDefinitionImpl.java
+++ b/source/java/org/alfresco/repo/action/ActionDefinitionImpl.java
@@ -18,7 +18,7 @@
*/
package org.alfresco.repo.action;
-import java.util.List;
+import java.util.Set;
import org.alfresco.service.cmr.action.ActionDefinition;
import org.alfresco.service.namespace.QName;
@@ -33,7 +33,7 @@ public class ActionDefinitionImpl extends ParameterizedItemDefinitionImpl implem
private static final long serialVersionUID = 4048797883396863026L;
private String ruleActionExecutor;
- private List applicableTypes;
+ private Set applicableTypes;
private boolean trackStatus;
/**
@@ -68,11 +68,11 @@ public class ActionDefinitionImpl extends ParameterizedItemDefinitionImpl implem
}
/**
- * Gets the list of applicable types
+ * Gets the set of applicable types
*
- * @return the list of qnames
+ * @return the set of qnames
*/
- public List getApplicableTypes()
+ public Set getApplicableTypes()
{
return this.applicableTypes;
}
@@ -82,7 +82,7 @@ public class ActionDefinitionImpl extends ParameterizedItemDefinitionImpl implem
*
* @param applicableTypes the applicable types
*/
- public void setApplicableTypes(List applicableTypes)
+ public void setApplicableTypes(Set applicableTypes)
{
this.applicableTypes = applicableTypes;
}
diff --git a/source/java/org/alfresco/repo/action/ActionServiceImpl.java b/source/java/org/alfresco/repo/action/ActionServiceImpl.java
index ddad5a45d0..0c5c3350c9 100644
--- a/source/java/org/alfresco/repo/action/ActionServiceImpl.java
+++ b/source/java/org/alfresco/repo/action/ActionServiceImpl.java
@@ -284,15 +284,24 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A
List result = new ArrayList();
for (ActionDefinition actionDefinition : getActionDefinitions())
{
- List appliciableTypes = actionDefinition.getApplicableTypes();
- if (appliciableTypes != null && appliciableTypes.isEmpty() == false)
+ Set applicableTypes = actionDefinition.getApplicableTypes();
+ if (applicableTypes != null && applicableTypes.isEmpty() == false)
{
- for (QName applicableType : actionDefinition.getApplicableTypes())
+ // First do a short-cut check directly against the type
+ if (applicableTypes.contains(nodeType))
{
- if (this.dictionaryService.isSubClass(nodeType, applicableType))
+ result.add(actionDefinition);
+ }
+ else
+ {
+ // Have to do a check for all subtypes of the applicable types
+ for (QName applicableType : actionDefinition.getApplicableTypes())
{
- result.add(actionDefinition);
- break;
+ if (this.dictionaryService.isSubClass(nodeType, applicableType))
+ {
+ result.add(actionDefinition);
+ break;
+ }
}
}
}
diff --git a/source/java/org/alfresco/repo/action/executer/ActionExecuterAbstractBase.java b/source/java/org/alfresco/repo/action/executer/ActionExecuterAbstractBase.java
index 5b2dab026f..9602f59c23 100644
--- a/source/java/org/alfresco/repo/action/executer/ActionExecuterAbstractBase.java
+++ b/source/java/org/alfresco/repo/action/executer/ActionExecuterAbstractBase.java
@@ -18,13 +18,14 @@
*/
package org.alfresco.repo.action.executer;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
import org.alfresco.repo.action.ActionDefinitionImpl;
import org.alfresco.repo.action.ParameterizedItemAbstractBase;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionDefinition;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -45,6 +46,7 @@ public abstract class ActionExecuterAbstractBase extends ParameterizedItemAbstra
protected ActionDefinition actionDefinition;
private LockService lockService;
private NodeService baseNodeService;
+ private DictionaryService dictionaryService;
/** Indicate if the action status should be tracked or not (default false) */
private boolean trackStatus = false;
@@ -53,7 +55,7 @@ public abstract class ActionExecuterAbstractBase extends ParameterizedItemAbstra
protected boolean publicAction = true;
/** List of types and aspects for which this action is applicable */
- protected List applicableTypes = new ArrayList();
+ protected Set applicableTypes = new HashSet();
/** Default queue name */
private String queueName = "";
@@ -82,6 +84,16 @@ public abstract class ActionExecuterAbstractBase extends ParameterizedItemAbstra
this.baseNodeService = nodeService;
}
+ /**
+ * Set the dictionary service
+ *
+ * @param dictionaryService the dictionary service
+ */
+ public void setDictionaryService(DictionaryService dictionaryService)
+ {
+ this.dictionaryService = dictionaryService;
+ }
+
/**
* Set whether the action is public or not.
*
@@ -122,7 +134,7 @@ public abstract class ActionExecuterAbstractBase extends ParameterizedItemAbstra
/**
* Set the list of types for which this action is applicable
*
- * @param applicableTypes arry of applicable types
+ * @param applicableTypes array of applicable types
*/
public void setApplicableTypes(String[] applicableTypes)
{
@@ -149,6 +161,40 @@ public abstract class ActionExecuterAbstractBase extends ParameterizedItemAbstra
this.ignoreLock = ignoreLock;
}
+ /**
+ * Check if a node is a type or subtype of the of one of the applicable types
+ *
+ * @param actionedUponNodeRef the node to check
+ * @return Returns true if the node is in the list of
+ * {@link #setApplicableTypes(String[]) applicable types} or one of the
+ * subtypes
+ */
+ protected boolean isApplicableType(NodeRef actionedUponNodeRef)
+ {
+ if (this.baseNodeService.exists(actionedUponNodeRef) == true)
+ {
+ QName nodeType = baseNodeService.getType(actionedUponNodeRef);
+ // Quick check in the set
+ if (applicableTypes.contains(nodeType))
+ {
+ return true;
+ }
+ else
+ {
+ // Have to do a long-winded check
+ for (QName type : applicableTypes)
+ {
+ if (this.dictionaryService.isSubClass(nodeType, type))
+ {
+ return true;
+ }
+ // Not a subtype; keep checking
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Get rule action definition
*
diff --git a/source/java/org/alfresco/repo/action/executer/CheckOutActionExecuter.java b/source/java/org/alfresco/repo/action/executer/CheckOutActionExecuter.java
index 703191ef98..a19c1df89b 100644
--- a/source/java/org/alfresco/repo/action/executer/CheckOutActionExecuter.java
+++ b/source/java/org/alfresco/repo/action/executer/CheckOutActionExecuter.java
@@ -89,7 +89,8 @@ public class CheckOutActionExecuter extends ActionExecuterAbstractBase
public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef)
{
if (this.nodeService.exists(actionedUponNodeRef) == true &&
- this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_WORKING_COPY) == false)
+ this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_WORKING_COPY) == false &&
+ isApplicableType(actionedUponNodeRef) == true)
{
// Get the destination details
NodeRef destinationParent = (NodeRef)ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER);
diff --git a/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java b/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
index ea18932679..a0525ee504 100644
--- a/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
@@ -1956,7 +1956,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
@Override
public int purgeNodes(long maxTxnCommitTimeMs)
{
- return deleteNodesByCommitTime(true, maxTxnCommitTimeMs);
+ return deleteNodesByCommitTime(maxTxnCommitTimeMs);
}
/*
@@ -4616,7 +4616,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
Long optionalOldSharedAlcIdInAdditionToNull,
Long newSharedAlcId);
protected abstract int deleteNodeById(Long nodeId);
- protected abstract int deleteNodesByCommitTime(boolean deletedOnly, long maxTxnCommitTimeMs);
+ protected abstract int deleteNodesByCommitTime(long maxTxnCommitTimeMs);
protected abstract NodeEntity selectNodeById(Long id);
protected abstract NodeEntity selectNodeByNodeRef(NodeRef nodeRef);
protected abstract List selectNodesByUuids(Long storeId, SortedSet uuids);
diff --git a/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java b/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
index 035314d927..0b2a31ca21 100644
--- a/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
@@ -89,6 +89,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
private static final String UPDATE_NODE_BULK_TOUCH = "alfresco.node.update_NodeBulkTouch";
private static final String DELETE_NODE_BY_ID = "alfresco.node.delete_NodeById";
private static final String DELETE_NODES_BY_TXN_COMMIT_TIME = "alfresco.node.delete_NodesByTxnCommitTime";
+ private static final String DELETE_NODE_PROPS_BY_TXN_COMMIT_TIME = "alfresco.node.delete_NodePropsByTxnCommitTime";
private static final String SELECT_NODE_BY_ID = "alfresco.node.select_NodeById";
private static final String SELECT_NODE_BY_NODEREF = "alfresco.node.select_NodeByNodeRef";
private static final String SELECT_NODES_BY_UUIDS = "alfresco.node.select_NodesByUuids";
@@ -148,8 +149,8 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
private static final String SELECT_TXN_MAX_ID = "alfresco.node.select_TxnMaxId";
private static final String SELECT_TXN_UNUSED_MIN_COMMIT_TIME = "alfresco.node.select_TxnMinUnusedCommitTime";
- private QNameDAO qnameDAO;
- private DictionaryService dictionaryService;
+ protected QNameDAO qnameDAO;
+ protected DictionaryService dictionaryService;
private SqlSessionTemplate template;
@@ -361,7 +362,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
}
@Override
- protected int deleteNodesByCommitTime(boolean deletedOnly, long maxTxnCommitTimeMs)
+ protected int deleteNodesByCommitTime(long maxTxnCommitTimeMs)
{
// Get the deleted nodes
Pair deletedTypePair = qnameDAO.getQName(ContentModel.TYPE_DELETED);
@@ -373,6 +374,10 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
TransactionQueryEntity query = new TransactionQueryEntity();
query.setTypeQNameId(deletedTypePair.getFirst());
query.setMaxCommitTime(maxTxnCommitTimeMs);
+ // TODO: Fix ALF-16030 Use ON DELETE CASCADE for node aspects and properties
+ // First clean up properties
+ template.delete(DELETE_NODE_PROPS_BY_TXN_COMMIT_TIME, query);
+ // Finally remove the nodes
return template.delete(DELETE_NODES_BY_TXN_COMMIT_TIME, query);
}
@@ -1651,6 +1656,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
*/
public static class MySQL extends NodeDAOImpl
{
+ private static final String DELETE_NODE_PROPS_BY_TXN_COMMIT_TIME_MYSQL = "alfresco.node.delete_NodePropsByTxnCommitTime_MySQL";
private static final String DELETE_TXNS_UNUSED_MYSQL = "alfresco.node.delete_Txns_Unused_MySQL";
private SqlSessionTemplate template;
@@ -1661,6 +1667,26 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
this.template = sqlSessionTemplate;
}
+ @Override
+ protected int deleteNodesByCommitTime(long maxTxnCommitTimeMs)
+ {
+ // Get the deleted nodes
+ Pair deletedTypePair = qnameDAO.getQName(ContentModel.TYPE_DELETED);
+ if (deletedTypePair == null)
+ {
+ // Nothing to do
+ return 0;
+ }
+ TransactionQueryEntity query = new TransactionQueryEntity();
+ query.setTypeQNameId(deletedTypePair.getFirst());
+ query.setMaxCommitTime(maxTxnCommitTimeMs);
+ // TODO: Fix ALF-16030 Use ON DELETE CASCADE for node aspects and properties
+ // First clean up properties
+ template.delete(DELETE_NODE_PROPS_BY_TXN_COMMIT_TIME_MYSQL, query);
+ // Finally remove the nodes
+ return template.delete(DELETE_NODES_BY_TXN_COMMIT_TIME, query);
+ }
+
@Override
public int deleteTxnsUnused(long fromCommitTime, long toCommitTime)
{
diff --git a/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java b/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java
index d7b75f7627..03027e4678 100644
--- a/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java
+++ b/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java
@@ -132,6 +132,7 @@ public class SchemaBootstrap extends AbstractLifecycleBean
private static final String PROPERTY_DEFAULT_BATCH_SIZE = "system.upgrade.default.batchsize";
private static final String MSG_DIALECT_USED = "schema.update.msg.dialect_used";
+ private static final String MSG_DATABASE_USED = "schema.update.msg.database_used";
private static final String MSG_BYPASSING_SCHEMA_UPDATE = "schema.update.msg.bypassing";
private static final String MSG_NORMALIZED_SCHEMA = "schema.update.msg.normalized_schema";
private static final String MSG_NORMALIZED_SCHEMA_PRE = "schema.update.msg.normalized_schema_pre";
@@ -1505,6 +1506,7 @@ public class SchemaBootstrap extends AbstractLifecycleBean
// make sure that we AUTO-COMMIT
connection = dataSource.getConnection();
connection.setAutoCommit(true);
+ LogUtil.info(logger, MSG_DATABASE_USED, connection);
Configuration cfg = localSessionFactory.getConfiguration();
diff --git a/source/java/org/alfresco/repo/model/filefolder/FilenameFilteringInterceptor.java b/source/java/org/alfresco/repo/model/filefolder/FilenameFilteringInterceptor.java
index a079090bcf..a2ccebb6b3 100644
--- a/source/java/org/alfresco/repo/model/filefolder/FilenameFilteringInterceptor.java
+++ b/source/java/org/alfresco/repo/model/filefolder/FilenameFilteringInterceptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2011 Alfresco Software Limited.
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -18,12 +18,15 @@
package org.alfresco.repo.model.filefolder;
import java.util.Iterator;
+import java.util.regex.Pattern;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.model.FileInfo;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
@@ -48,8 +51,16 @@ public class FilenameFilteringInterceptor implements MethodInterceptor
{
private static Log logger = LogFactory.getLog(FilenameFilteringInterceptor.class);
+ private static final String XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
+
+ private static final String MACOS_TEMPORARY_FILE_NAME_PREFIX = "._";
+ private static final Pattern XSL_MACOS_TEMPORARY_FILENAME_FITLER = Pattern.compile("^(\\" + MACOS_TEMPORARY_FILE_NAME_PREFIX + ")?[0-9,a-f]{8}$", Pattern.CASE_INSENSITIVE
+ | Pattern.UNICODE_CASE);
+
private NodeService nodeService;
private PermissionService permissionService;
+
+ private ContentService contentService;
private PatternFilter temporaryFiles;
private PatternFilter systemPaths;
@@ -111,6 +122,16 @@ public class FilenameFilteringInterceptor implements MethodInterceptor
this.permissionService = permissionService;
}
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
+ public ContentService getContentService()
+ {
+ return contentService;
+ }
+
private void checkTemporaryAspect(boolean isTemporary, FileInfo fileInfo)
{
checkTemporaryAspect(isTemporary, fileInfo.getNodeRef());
@@ -239,7 +260,8 @@ public class FilenameFilteringInterceptor implements MethodInterceptor
else
{
// check whether it's a temporary or hidden file
- checkTemporaryAspect(temporaryFiles.isFiltered(filename), (FileInfo)ret);
+ FileInfo sourceInfo = (FileInfo)ret;
+ checkTemporaryAspect(isNameOfTmporaryObject(filename, sourceInfo.getNodeRef()), sourceInfo);
hiddenAspect.checkHidden(fileInfo, false);
}
}
@@ -250,7 +272,7 @@ public class FilenameFilteringInterceptor implements MethodInterceptor
FileInfoImpl fileInfo = (FileInfoImpl)ret;
- checkTemporaryAspect(temporaryFiles.isFiltered(filename), fileInfo);
+ checkTemporaryAspect(isNameOfTmporaryObject(filename, fileInfo.getNodeRef()), fileInfo);
}
}
else if (methodName.startsWith("move"))
@@ -263,7 +285,7 @@ public class FilenameFilteringInterceptor implements MethodInterceptor
{
// Name is changing
// check against all the regular expressions
- checkTemporaryAspect(temporaryFiles.isFiltered(newName), sourceNodeRef);
+ checkTemporaryAspect(isNameOfTmporaryObject(newName, sourceNodeRef), sourceNodeRef);
}
// now do the move
@@ -287,7 +309,7 @@ public class FilenameFilteringInterceptor implements MethodInterceptor
}
// check against all the regular expressions
- checkTemporaryAspect(temporaryFiles.isFiltered(filename), fileInfo);
+ checkTemporaryAspect(isNameOfTmporaryObject(filename, fileInfo.getNodeRef()), fileInfo);
if(getMode() == Mode.ENHANCED)
{
hiddenAspect.checkHidden(fileInfo, true);
@@ -315,7 +337,7 @@ public class FilenameFilteringInterceptor implements MethodInterceptor
}
// check against all the regular expressions
- checkTemporaryAspect(temporaryFiles.isFiltered(newName), sourceNodeRef);
+ checkTemporaryAspect(isNameOfTmporaryObject(newName, sourceNodeRef), sourceNodeRef);
ret = invocation.proceed();
@@ -347,5 +369,36 @@ public class FilenameFilteringInterceptor implements MethodInterceptor
// done
return ret;
}
+
+ /**
+ * Determines whether specified name
matches any pattern of temporary file names. Also it checks special case of new XLS document creation in MacOS. See ALF-14078 (comment added on 04-September-12 04:11 PM) for more details
+ *
+ * @param name - {@link String} value which contains name of node
+ * @param nodeRef - {@link NodeRef} instance of the node
+ * @return {@link Boolean} value. true
if name
is name of temporary object including special case of XLSX in MacOS. false
in other case
+ */
+ private boolean isNameOfTmporaryObject(String name, NodeRef nodeRef)
+ {
+ boolean result = temporaryFiles.isFiltered(name);
+
+ if (!result)
+ {
+ // This pattern must be validated in conjunction with mimetype validation only!
+ result = XSL_MACOS_TEMPORARY_FILENAME_FITLER.matcher(name).matches();
+
+ if (result && !name.startsWith(MACOS_TEMPORARY_FILE_NAME_PREFIX))
+ {
+ ContentReader contentReader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
+
+ if (null != contentReader)
+ {
+ result = XLSX_MIMETYPE.equals(contentReader.getMimetype());
+ }
+ }
+ }
+
+ return result;
+ }
}
diff --git a/source/java/org/alfresco/repo/node/cleanup/TransactionCleanupTest.java b/source/java/org/alfresco/repo/node/cleanup/TransactionCleanupTest.java
index ccef92cfb3..e31a984653 100644
--- a/source/java/org/alfresco/repo/node/cleanup/TransactionCleanupTest.java
+++ b/source/java/org/alfresco/repo/node/cleanup/TransactionCleanupTest.java
@@ -1,14 +1,18 @@
package org.alfresco.repo.node.cleanup;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
+import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.node.Transaction;
import org.alfresco.repo.node.db.DeletedNodeCleanupWorker;
@@ -25,14 +29,22 @@ import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.extensions.webscripts.GUID;
+/**
+ * @author Derek Hulley
+ * @since 4.0
+ */
public class TransactionCleanupTest
{
+ private static Log logger = LogFactory.getLog(TransactionCleanupTest.class);
+
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private TransactionService transactionService;
@@ -40,6 +52,7 @@ public class TransactionCleanupTest
private SearchService searchService;
private MutableAuthenticationService authenticationService;
private NodeDAO nodeDAO;
+ private SimpleCache nodesCache;
private DeletedNodeCleanupWorker worker;
private NodeRef nodeRef1;
@@ -49,6 +62,7 @@ public class TransactionCleanupTest
private NodeRef nodeRef5;
private RetryingTransactionHelper helper;
+ @SuppressWarnings("unchecked")
@Before
public void before()
{
@@ -59,12 +73,13 @@ public class TransactionCleanupTest
this.nodeService = serviceRegistry.getNodeService();
this.searchService = serviceRegistry.getSearchService();
this.nodeDAO = (NodeDAO)ctx.getBean("nodeDAO");
+ this.nodesCache = (SimpleCache) ctx.getBean("node.nodesSharedCache");
this.worker = (DeletedNodeCleanupWorker)ctx.getBean("nodeCleanup.deletedNodeCleanup");
this.worker.setMinPurgeAgeDays(0);
this.helper = transactionService.getRetryingTransactionHelper();
authenticationService.authenticate("admin", "admin".toCharArray());
-
+
StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
NodeRef storeRoot = nodeService.getRootNode(storeRef);
List nodeRefs = searchService.selectNodes(
@@ -93,8 +108,8 @@ public class TransactionCleanupTest
UpdateNode updateNode1 = new UpdateNode(nodeRef1);
UpdateNode updateNode2 = new UpdateNode(nodeRef2);
UpdateNode updateNode3 = new UpdateNode(nodeRef3);
- UpdateNode updateNode4 = new UpdateNode(nodeRef4);
- UpdateNode updateNode5 = new UpdateNode(nodeRef5);
+ DeleteNode deleteNode4 = new DeleteNode(nodeRef4);
+ DeleteNode deleteNode5 = new DeleteNode(nodeRef5);
List txnIds1 = new ArrayList();
List txnIds2 = new ArrayList();
@@ -116,22 +131,16 @@ public class TransactionCleanupTest
String txnId2 = helper.doInTransaction(updateNode2, false, true);
txnIds2.add(txnId2);
}
- if(i == 2)
+ if(i == 1)
{
String txnId3 = helper.doInTransaction(updateNode3, false, true);
txnIds3.add(txnId3);
}
- if(i == 3)
- {
- String txnId4 = helper.doInTransaction(updateNode4, false, true);
- txnIds4.add(txnId4);
- }
- if(i == 4)
- {
- String txnId5 = helper.doInTransaction(updateNode5, false, true);
- txnIds5.add(txnId5);
- }
}
+ String txnId4 = helper.doInTransaction(deleteNode4, false, true);
+ txnIds4.add(txnId4);
+ String txnId5 = helper.doInTransaction(deleteNode5, false, true);
+ txnIds5.add(txnId5);
return txnIds;
}
@@ -165,12 +174,21 @@ public class TransactionCleanupTest
final List txnIds1 = txnIds.get(nodeRef1);
final List txnIds2 = txnIds.get(nodeRef2);
final List txnIds3 = txnIds.get(nodeRef3);
- final List txnIds4 = txnIds.get(nodeRef4);
- final List txnIds5 = txnIds.get(nodeRef5);
+ // Pure delete: final List txnIds4 = txnIds.get(nodeRef4);
+ // Pure delete: final List txnIds5 = txnIds.get(nodeRef5);
+
+ // Double-check that n4 and n5 are present in deleted form
+ nodesCache.clear();
+ assertNotNull("Node 4 is deleted but not purged", nodeDAO.getNodeRefStatus(nodeRef4));
+ assertNotNull("Node 5 is deleted but not purged", nodeDAO.getNodeRefStatus(nodeRef5));
// run the transaction cleaner
worker.setPurgeSize(5); // small purge size
- worker.doClean();
+ List reports = worker.doClean();
+ for (String report : reports)
+ {
+ logger.debug(report);
+ }
// Get transactions committed after the test started
List txns = nodeDAO.getTxnsByCommitTimeAscending(Long.valueOf(start), Long.valueOf(Long.MAX_VALUE), Integer.MAX_VALUE, null, false);
@@ -182,8 +200,7 @@ public class TransactionCleanupTest
expectedUsedTxnIds.add(txnIds1.get(txnIds1.size() - 1));
expectedUsedTxnIds.addAll(txnIds2);
expectedUsedTxnIds.addAll(txnIds3);
- expectedUsedTxnIds.addAll(txnIds4);
- expectedUsedTxnIds.addAll(txnIds5);
+ // 4 and 5 should not be in the list because they are deletes
// check that the correct transactions have been purged i.e. all except the last one to update the node
// i.e. in this case, all but the last one in txnIds1
@@ -211,10 +228,15 @@ public class TransactionCleanupTest
}
}
- assertEquals(5, numFoundUsedTxnIds);
+ assertEquals(3, numFoundUsedTxnIds);
List txnsUnused = nodeDAO.getTxnsUnused(minTxnId, Long.MAX_VALUE, Integer.MAX_VALUE);
assertEquals(0, txnsUnused.size());
+
+ // Double-check that n4 and n5 were removed as well
+ nodesCache.clear();
+ assertNull("Node 4 was not cleaned up", nodeDAO.getNodeRefStatus(nodeRef4));
+ assertNull("Node 5 was not cleaned up", nodeDAO.getNodeRefStatus(nodeRef5));
}
@After
@@ -241,4 +263,24 @@ public class TransactionCleanupTest
return txnId;
}
};
+
+ private class DeleteNode implements RetryingTransactionCallback
+ {
+ private NodeRef nodeRef;
+
+ DeleteNode(NodeRef nodeRef)
+ {
+ this.nodeRef = nodeRef;
+ }
+
+ @Override
+ public String execute() throws Throwable
+ {
+ nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null);
+ nodeService.deleteNode(nodeRef);
+ String txnId = AlfrescoTransactionSupport.getTransactionId();
+
+ return txnId;
+ }
+ };
}
diff --git a/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java b/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java
index 1e8a6bfb63..78702b488c 100644
--- a/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java
+++ b/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java
@@ -451,9 +451,12 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent
try
{
Pair pair = nodeDAO.getNodePair(catRef);
- for (Path path : nodeDAO.getPaths(pair, false))
+ if(pair != null)
{
- aspectPaths.add(new Pair(path, aspDef.getName()));
+ for (Path path : nodeDAO.getPaths(pair, false))
+ {
+ aspectPaths.add(new Pair(path, aspDef.getName()));
+ }
}
}
catch (InvalidNodeRefException e)
diff --git a/source/java/org/alfresco/repo/template/VersionHistoryNode.java b/source/java/org/alfresco/repo/template/VersionHistoryNode.java
index cc3af286d1..840b8591ff 100644
--- a/source/java/org/alfresco/repo/template/VersionHistoryNode.java
+++ b/source/java/org/alfresco/repo/template/VersionHistoryNode.java
@@ -110,6 +110,16 @@ public class VersionHistoryNode extends BaseContentNode implements NamespacePref
return (String)this.getProperties().get(ContentModel.PROP_NAME);
}
+ /**
+ * Helper method to get the item title.
+ *
+ * @return the item name
+ */
+ public String getTitle()
+ {
+ return (String)this.getProperties().get(ContentModel.PROP_TITLE);
+ }
+
/**
* Helper method to get the created date from the version property data.
*
diff --git a/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImplTest.java b/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImplTest.java
index cff694086d..91ecab05d3 100644
--- a/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImplTest.java
+++ b/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImplTest.java
@@ -517,11 +517,14 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
{
receiver.saveContent(transferId, node.getUuid(), new ByteArrayInputStream(dummyContentBytes));
}
+ log.info("testMoreComplexCommit - commit");
receiver.commit(transferId);
+ log.info("testMoreComplexCommit - commited");
}
finally
{
+ log.info("testMoreComplexCommit - end");
receiver.end(transferId);
endTransaction();
}
@@ -529,6 +532,7 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
startNewTransaction();
try
{
+ log.info("testMoreComplexCommit - validate nodes");
assertTrue(nodeService.getAspects(node1.getNodeRef()).contains(ContentModel.ASPECT_ATTACHABLE));
assertFalse(nodeService.getSourceAssocs(node2.getNodeRef(), ContentModel.ASSOC_ATTACHMENTS).isEmpty());
for (TransferManifestNode node : nodes)
diff --git a/source/java/org/alfresco/repo/usage/UserUsageTrackingComponent.java b/source/java/org/alfresco/repo/usage/UserUsageTrackingComponent.java
index 3d9e87505e..3a0769ca0c 100644
--- a/source/java/org/alfresco/repo/usage/UserUsageTrackingComponent.java
+++ b/source/java/org/alfresco/repo/usage/UserUsageTrackingComponent.java
@@ -313,7 +313,7 @@ public class UserUsageTrackingComponent extends AbstractLifecycleBean implements
users.put(username, new NodeRef(personStoreRef, uuid));
}
};
- usageDAO.getUsersWithUsage(personStoreRef, userHandler);
+ usageDAO.getUsersWithUsage(tenantService.getName(personStoreRef), userHandler);
return null;
}
diff --git a/source/java/org/alfresco/repo/wiki/WikiServiceImpl.java b/source/java/org/alfresco/repo/wiki/WikiServiceImpl.java
index 65f1ae43a3..0f8065f190 100644
--- a/source/java/org/alfresco/repo/wiki/WikiServiceImpl.java
+++ b/source/java/org/alfresco/repo/wiki/WikiServiceImpl.java
@@ -142,6 +142,12 @@ public class WikiServiceImpl implements WikiService
{
// The name is based on the title, but with underscores
String name = title.replace(' ', '_');
+ name = name.replaceAll("\"", "%22");
+ name = name.replaceAll("[*]", "%2a");
+ name = name.replaceAll("<", "%3c");
+ name = name.replaceAll(">", "%3e");
+ name = name.replaceAll(":", "%3a");
+ name = name.replaceAll("([.]?[.]+$)", "%2e");
return name;
}
@@ -182,7 +188,7 @@ public class WikiServiceImpl implements WikiService
@Override
- public WikiPageInfo getWikiPage(String siteShortName, String pageName)
+ public WikiPageInfo getWikiPage(String siteShortName, String pageTitle)
{
NodeRef container = getSiteWikiContainer(siteShortName, false);
if (container == null)
@@ -191,6 +197,7 @@ public class WikiServiceImpl implements WikiService
return null;
}
+ String pageName = buildName(pageTitle);
NodeRef link = nodeService.getChildByName(container, ContentModel.ASSOC_CONTAINS, pageName);
if (link != null)
{
diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java
index 52fd37f508..eaa4d12cd2 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java
@@ -179,9 +179,12 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
private static final String ERR_END_UNEXISTING_TASK = "activiti.engine.end.task.unexisting.error";
private static final String ERR_GET_TASK_BY_ID = "activiti.engine.get.task.by.id.error";
private static final String ERR_END_TASK_INVALID_TRANSITION = "activiti.engine.end.task.invalid.transition";
-
+ public static final QName QNAME_INITIATOR = QName.createQName(NamespaceService.DEFAULT_URI, WorkflowConstants.PROP_INITIATOR);
+
private final static String WORKFLOW_TOKEN_SEPERATOR = "\\$";
+
+
private RepositoryService repoService;
private RuntimeService runtimeService;
private TaskService taskService;
@@ -2285,7 +2288,27 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
if (workflowInstanceQuery.getCustomProps() != null)
{
- for (Map.Entry prop : workflowInstanceQuery.getCustomProps().entrySet())
+ Map customProps = workflowInstanceQuery.getCustomProps();
+
+ // CLOUD-667: Extract initiator-property and use 'startedBy' instead
+ Object initiatorObject = customProps.get(QNAME_INITIATOR);
+ if(initiatorObject != null && initiatorObject instanceof NodeRef)
+ {
+ // Extract username from person-node
+ NodeRef initiator = (NodeRef) initiatorObject;
+ if(this.nodeService.exists(initiator))
+ {
+ String initiatorUserName = (String) nodeService.getProperty(initiator, ContentModel.PROP_USERNAME);
+ query.startedBy(initiatorUserName);
+
+ // Clone properties map and remove initiator
+ customProps = new HashMap();
+ customProps.putAll(workflowInstanceQuery.getCustomProps());
+ customProps.remove(QNAME_INITIATOR);
+ }
+ }
+
+ for (Map.Entry prop : customProps.entrySet())
{
String propertyName = factory.mapQNameToName(prop.getKey());
if (prop.getValue() == null)
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMScheduler.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMScheduler.java
index 05d48053bf..572f553e7a 100644
--- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMScheduler.java
+++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMScheduler.java
@@ -18,9 +18,9 @@
*/
package org.alfresco.repo.workflow.jbpm;
-import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.jbpm.job.executor.JobExecutor;
import org.springframework.context.ApplicationEvent;
+import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.springmodules.workflow.jbpm31.JbpmTemplate;
@@ -35,7 +35,7 @@ public class JBPMScheduler extends AbstractLifecycleBean
{
private JobExecutor executor = null;
private JbpmTemplate jbpmTemplate;
-
+ private boolean JbpmEngineEnabled = false;
/**
* @param jbpmTemplate
@@ -44,18 +44,32 @@ public class JBPMScheduler extends AbstractLifecycleBean
{
this.jbpmTemplate = jbpmTemplate;
}
+
+ /**
+ * @param jbpmEngineEnabled whether or not the JBPM-Engine is enables. Please note that we are
+ * not using the WorklfowAdminService since this is only initialized later in the sequence.
+ */
+ public void setJBPMEngineEnabled(boolean jbpmEngineEnabled) {
+ JbpmEngineEnabled = jbpmEngineEnabled;
+ }
@Override
protected void onBootstrap(ApplicationEvent event)
{
- executor = jbpmTemplate.getJbpmConfiguration().getJobExecutor();
- executor.start();
+ if(JbpmEngineEnabled)
+ {
+ executor = jbpmTemplate.getJbpmConfiguration().getJobExecutor();
+ executor.start();
+ }
}
@Override
protected void onShutdown(ApplicationEvent event)
{
- executor.stop();
+ if(JbpmEngineEnabled || executor.isStarted())
+ {
+ executor.stop();
+ }
}
}
diff --git a/source/java/org/alfresco/service/cmr/action/ActionDefinition.java b/source/java/org/alfresco/service/cmr/action/ActionDefinition.java
index 3daa92060c..d417085754 100644
--- a/source/java/org/alfresco/service/cmr/action/ActionDefinition.java
+++ b/source/java/org/alfresco/service/cmr/action/ActionDefinition.java
@@ -18,7 +18,7 @@
*/
package org.alfresco.service.cmr.action;
-import java.util.List;
+import java.util.Set;
import org.alfresco.service.namespace.QName;
@@ -32,9 +32,9 @@ public interface ActionDefinition extends ParameterizedItemDefinition
/**
* Gets a list of the types that this action item is applicable for
*
- * @return list of types
+ * @return set of types never null
*/
- public List getApplicableTypes();
+ public Set getApplicableTypes();
/**
* Get whether the basic action definition supports action tracking