after)
{
- if ((this.nodeService.exists(nodeRef) == true) &&
+ if ((this.nodeService.exists(nodeRef) == true) &&
+ !isLockedOrReadOnly(nodeRef) &&
(this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true) &&
- (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY) == false) &&
- (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE) == false))
+ (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY) == false))
{
onUpdatePropertiesBehaviour.disable();
try
@@ -507,6 +522,21 @@ public class VersionableAspect implements ContentServicePolicies.OnContentUpdate
}
}
}
+
+ /**
+ * Indicates if the node is unlocked or the current user has a WRITE_LOCK
+ *
+ * Ideally this would be a new method on the lockService, but cannot do this at the moment,
+ * as this method is being added as part of a hot fix, so a public service cannot change
+ * as the RM AMP might be installed and it has its own security context which would also need
+ * to reflect this change.
+ */
+ private boolean isLockedOrReadOnly(NodeRef nodeRef)
+ {
+ LockStatus lockStatus = lockService.getLockStatus(nodeRef);
+ LockType lockType = lockService.getLockType(nodeRef);
+ return ! (lockStatus == LockStatus.NO_LOCK || (lockStatus == LockStatus.LOCK_OWNER && lockType == LockType.WRITE_LOCK));
+ }
/**
* On create version implementation method
diff --git a/source/java/org/alfresco/repo/version/VersionableAspectTest.java b/source/java/org/alfresco/repo/version/VersionableAspectTest.java
new file mode 100644
index 0000000000..14d8e6e13c
--- /dev/null
+++ b/source/java/org/alfresco/repo/version/VersionableAspectTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2005-2012 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.repo.version;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.service.cmr.coci.CheckOutCheckInService;
+import org.alfresco.service.cmr.lock.LockService;
+import org.alfresco.service.cmr.lock.LockStatus;
+import org.alfresco.service.cmr.lock.LockType;
+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.StoreRef;
+import org.alfresco.service.cmr.search.ResultSet;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.cmr.security.AuthenticationService;
+import org.alfresco.service.cmr.version.VersionType;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.util.ApplicationContextHelper;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * @author Dmitry Velichkevich
+ */
+public class VersionableAspectTest extends TestCase
+{
+ private static final String NAME_AND_EXT_DELIMETER = ".";
+
+ private static final String NAME_AND_EXT_DELIMETER_REGEXP = "\\" + NAME_AND_EXT_DELIMETER;
+
+
+ private static final String ADMIN_CREDENTIAL = "admin";
+
+ private static final String ROOT_NODE_TERM = "PATH:\"/app\\:company_home\"";
+
+ private static final String DOCUMENT_NAME = "ChildDocumentWithVersionLabel-.txt";
+
+ private static final String PARENT_FOLDER_NAME = "ParentFolder-" + System.currentTimeMillis();
+
+ private static final String TEST_CONTENT_01 = "Test Content version 0.1\n";
+ private static final String TEST_CONTENT_10 = "Test Content version 1.0\n";
+
+
+ private ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext();
+
+ private NodeService nodeService = (NodeService) applicationContext.getBean("nodeService");
+ private LockService lockService = (LockService) applicationContext.getBean("lockService");
+ private SearchService searchService = (SearchService) applicationContext.getBean("searchService");
+ private ContentService contentService = (ContentService) applicationContext.getBean("contentService");
+ private TransactionService transactionService = (TransactionService) applicationContext.getBean("transactionService");
+ private CheckOutCheckInService checkOutCheckInService = (CheckOutCheckInService) applicationContext.getBean("checkOutCheckInService");
+ private AuthenticationService authenticationService = (AuthenticationService) applicationContext.getBean("authenticationService");
+
+ private NodeRef document;
+ private NodeRef parentFolder;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ authenticationService.authenticate(ADMIN_CREDENTIAL, ADMIN_CREDENTIAL.toCharArray());
+
+ ResultSet query = null;
+ NodeRef rootNode = null;
+ try
+ {
+ query = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, SearchService.LANGUAGE_LUCENE, ROOT_NODE_TERM);
+ rootNode = query.getNodeRef(0);
+ }
+ finally
+ {
+ if (null != query)
+ {
+ query.close();
+ }
+ }
+
+ Map properties = new HashMap();
+ properties.put(ContentModel.PROP_NAME, PARENT_FOLDER_NAME);
+ parentFolder = nodeService.createNode(rootNode, ContentModel.ASSOC_CONTAINS, QName.createQName(ContentModel.USER_MODEL_URI, PARENT_FOLDER_NAME),
+ ContentModel.TYPE_FOLDER, properties).getChildRef();
+
+ properties.clear();
+ properties.put(ContentModel.PROP_NAME, DOCUMENT_NAME);
+
+ document = nodeService.createNode(parentFolder, ContentModel.ASSOC_CONTAINS, QName.createQName(ContentModel.USER_MODEL_URI, DOCUMENT_NAME),
+ ContentModel.TYPE_CONTENT, properties).getChildRef();
+ contentService.getWriter(document, ContentModel.PROP_CONTENT, true).putContent(TEST_CONTENT_01);
+
+ if (!nodeService.hasAspect(document, ContentModel.ASPECT_VERSIONABLE))
+ {
+ Map versionProperties = new HashMap();
+ versionProperties.put(ContentModel.PROP_VERSION_LABEL, "0.1");
+ versionProperties.put(ContentModel.PROP_INITIAL_VERSION, true);
+ versionProperties.put(ContentModel.PROP_VERSION_TYPE, VersionType.MINOR);
+ nodeService.addAspect(document, ContentModel.ASPECT_VERSIONABLE, versionProperties);
+ }
+
+ return null;
+ }
+ });
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ if (null != parentFolder)
+ {
+ nodeService.deleteNode(parentFolder);
+ }
+
+ authenticationService.clearCurrentSecurityContext();
+
+ return null;
+ }
+ });
+ }
+
+ public void testAutoVersionIncrementOnPropertiesUpdateAfterCheckInAlf14584() throws Exception
+ {
+ final String name02 = generateDocumentName(DOCUMENT_NAME, "0.2");
+ final String name11 = generateDocumentName(DOCUMENT_NAME, "1.1");
+
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ Map properties = getAndAssertProperties(document, "0.1");
+
+ Serializable autoVersionProps = properties.get(ContentModel.PROP_AUTO_VERSION_PROPS);
+ assertNotNull(("Autoversion property is NULL! NodeRef = '" + document.toString() + "'"), autoVersionProps);
+ assertTrue(("Autoversion must be TRUE! NodeRef = '" + document.toString() + "'"), (Boolean) autoVersionProps);
+
+ nodeService.setProperty(document, ContentModel.PROP_NAME, name02);
+
+ return null;
+ }
+ });
+
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ Map properties = getAndAssertProperties(document, "0.2");
+ assertEquals(name02, properties.get(ContentModel.PROP_NAME));
+
+ NodeRef workingCopy = checkOutCheckInService.checkout(document);
+ contentService.getWriter(workingCopy, ContentModel.PROP_CONTENT, true).putContent(TEST_CONTENT_10);
+
+ Map versionProperties = new HashMap();
+ versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
+ document = checkOutCheckInService.checkin(workingCopy, versionProperties);
+
+ return null;
+ }
+ });
+
+ assertDocumentVersionAndName("1.0", name02);
+
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ nodeService.setProperty(document, ContentModel.PROP_NAME, name11);
+
+ return null;
+ }
+ });
+
+ assertDocumentVersionAndName("1.1", name11);
+ }
+
+ public void testAutoVersionIncrementOnPropertiesUpdateByLockOwnerAlf14584() throws Exception
+ {
+ final String name = generateDocumentName(DOCUMENT_NAME, "0.2");
+
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ Map properties = getAndAssertProperties(document, "0.1");
+
+ Serializable autoVersionProps = properties.get(ContentModel.PROP_AUTO_VERSION_PROPS);
+ assertNotNull(("Autoversion property is NULL! NodeRef = '" + document.toString() + "'"), autoVersionProps);
+ assertTrue(("Autoversion must be TRUE! NodeRef = '" + document.toString() + "'"), (Boolean) autoVersionProps);
+
+ lockService.lock(document, LockType.WRITE_LOCK);
+
+ LockStatus lockStatus = lockService.getLockStatus(document);
+ assertFalse(
+ ("Node with NodeRef = '" + document.toString() + "' must not be locked for " + AuthenticationUtil.getFullyAuthenticatedUser() + " user! The user is lock owner"),
+ isLocked(document));
+ assertEquals(LockStatus.LOCK_OWNER, lockService.getLockStatus(document));
+
+ nodeService.setProperty(document, ContentModel.PROP_NAME, name);
+
+ return null;
+ }
+ });
+
+ assertDocumentVersionAndName("0.2", name);
+ }
+
+ // Copy of code from VersionableAspect which really should be in LockService
+ private boolean isLocked(NodeRef nodeRef)
+ {
+ LockStatus lockStatus = lockService.getLockStatus(nodeRef);
+
+ return (LockStatus.NO_LOCK != lockStatus) && (LockStatus.LOCK_OWNER != lockStatus);
+ }
+
+ private void assertDocumentVersionAndName(final String versionLabel, final String name)
+ {
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ Map properties = getAndAssertProperties(document, versionLabel);
+ assertEquals(name, properties.get(ContentModel.PROP_NAME));
+
+ return null;
+ }
+ }, true);
+ }
+
+ private Map getAndAssertProperties(NodeRef nodeRef, String versionLabel)
+ {
+ assertNotNull("NodeRef of document is NULL!", nodeRef);
+
+ Map properties = nodeService.getProperties(nodeRef);
+
+ assertNotNull(("Properties must not be NULL! NodeRef = '" + nodeRef.toString() + "'"), properties);
+ assertFalse(("Version specific properties can't be found! NodeRef = '" + nodeRef.toString() + "'"), properties.isEmpty());
+ assertEquals(versionLabel, properties.get(ContentModel.PROP_VERSION_LABEL));
+
+ return properties;
+ }
+
+ private String generateDocumentName(String namePattern, String versionLabel)
+ {
+ int i = 0;
+ String[] nameAndExt = namePattern.split(NAME_AND_EXT_DELIMETER_REGEXP);
+ StringBuilder result = new StringBuilder(nameAndExt[i++]).append(versionLabel).append(NAME_AND_EXT_DELIMETER).append(nameAndExt[i++]);
+ return result.toString();
+ }
+}
diff --git a/source/java/org/alfresco/repo/workflow/jscript/JscriptWorkflowTask.java b/source/java/org/alfresco/repo/workflow/jscript/JscriptWorkflowTask.java
index 658f273798..46a31a7fa9 100644
--- a/source/java/org/alfresco/repo/workflow/jscript/JscriptWorkflowTask.java
+++ b/source/java/org/alfresco/repo/workflow/jscript/JscriptWorkflowTask.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
@@ -30,16 +30,19 @@ import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.jscript.ScriptableHashMap;
import org.alfresco.repo.jscript.ScriptableQNameMap;
-import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.security.MutableAuthenticationService;
+import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
+import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.cmr.workflow.WorkflowTransition;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.NamespacePrefixResolverProvider;
+import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
@@ -54,154 +57,37 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
{
static final long serialVersionUID = -8285971359421912313L;
- /** Unique ID for workflow task */
- private final String id;
-
- /** Name for workflow task */
- private final String name;
-
- /** Title for workflow task */
- private final String title;
-
- /** Description of workflow task */
- private final String description;
-
- /** Properties (key/value pairs) for this Workflow Task */
- private ScriptableQNameMap properties;
-
- /** Whether task is complete or not - 'true':complete, 'false':in-progress */
- private boolean complete = false;
-
- /** Whether task is pooled or not */
- private boolean pooled = false;
-
/** Service Registry object */
- private ServiceRegistry serviceRegistry;
-
- /** Available transitions * */
- private ScriptableHashMap transitions;
-
- /** Package resources * */
- private Scriptable packageResources;
-
- /**
- * Creates a new instance of a workflow task (instance of a workflow task definition)
- *
- * @param id
- * workflow task ID
- * @param name
- * workflow task name
- * @param title
- * workflow task title
- * @param description
- * workflow task description
- * @param serviceRegistry
- * Service Registry object
- * @param properties
- * @param transitions
- * @param packageResources
- */
- public JscriptWorkflowTask(final String id, final String name, final String title, final String description, final ServiceRegistry serviceRegistry,
- final ScriptableQNameMap properties, final ScriptableHashMap transitions, Scriptable packageResources,
- Scriptable scope)
- {
- this.id = id;
- this.name = name;
- this.title = title;
- this.description = description;
- this.serviceRegistry = serviceRegistry;
- this.properties = properties;
- this.transitions = transitions;
- this.packageResources = packageResources;
- this.setScope(scope);
- }
+ private final ServiceRegistry serviceRegistry;
+ private final NodeService nodeService;
+ private final WorkflowService workflowService;
+ private final DictionaryService dictionaryService;
+ private MutableAuthenticationService authenticationService;
+ private final DefaultNamespaceProvider namespaceProvider;
+
+ private WorkflowTask task;
+
/**
* Creates a new instance of a workflow task from a WorkflowTask from the CMR workflow object model
*
- * @param cmrWorkflowTask
+ * @param task
* an instance of WorkflowTask from CMR workflow object model
* @param serviceRegistry
* Service Registry object
*/
- public JscriptWorkflowTask(final WorkflowTask cmrWorkflowTask, final ServiceRegistry serviceRegistry, Scriptable scope)
+ public JscriptWorkflowTask(WorkflowTask task,
+ ServiceRegistry serviceRegistry,
+ Scriptable scope)
{
- this.id = cmrWorkflowTask.getId();
- this.name = cmrWorkflowTask.getName();
- this.title = cmrWorkflowTask.getTitle();
- this.description = cmrWorkflowTask.getDescription();
this.serviceRegistry = serviceRegistry;
+ this.namespaceProvider = new DefaultNamespaceProvider(serviceRegistry.getNamespaceService());
+ this.workflowService = serviceRegistry.getWorkflowService();
+ this.nodeService = serviceRegistry.getNodeService();
+ this.dictionaryService = serviceRegistry.getDictionaryService();
+ this.authenticationService = serviceRegistry.getAuthenticationService();
+ this.task = task;
this.setScope(scope);
-
- // instantiate ScriptableQNameMap properties
- // from WorkflowTasks's Map properties
- this.properties = new ScriptableQNameMap(new NamespacePrefixResolverProvider()
- {
- private static final long serialVersionUID = 4218645978524914678L;
-
- public NamespacePrefixResolver getNamespacePrefixResolver()
- {
- return serviceRegistry.getNamespaceService();
- }
- });
-
- Set keys = cmrWorkflowTask.getProperties().keySet();
- for (QName key : keys)
- {
- Serializable value = cmrWorkflowTask.getProperties().get(key);
- this.properties.put(key.toString(), value);
- }
-
- transitions = new ScriptableHashMap();
- for (WorkflowTransition transition : cmrWorkflowTask.getPath().getNode().getTransitions())
- {
- transitions.put(transition.getId(), transition.getTitle());
- }
-
- // build package context .... should be centralised... YUK
- // Needs to match org.alfresco.repo.template.Workflow.WorkflowTaskItem.getPackageResources
-
- List contents = serviceRegistry.getWorkflowService().getPackageContents(cmrWorkflowTask.getId());
- List resources = new ArrayList(contents.size());
-
- NodeService nodeService = serviceRegistry.getNodeService();
- DictionaryService ddService = serviceRegistry.getDictionaryService();
-
- for (NodeRef nodeRef : contents)
- {
- if (nodeRef.getStoreRef().getProtocol().equals(StoreRef.PROTOCOL_AVM))
- {
- resources.add(nodeRef);
- }
- else
- {
- if (nodeService.exists(nodeRef))
- {
- // find it's type so we can see if it's a node we are interested in
- QName type = nodeService.getType(nodeRef);
-
- // make sure the type is defined in the data dictionary
- if (ddService.getType(type) != null)
- {
- // look for content nodes or links to content
- // NOTE: folders within workflow packages are ignored for now
- if (ddService.isSubClass(type, ContentModel.TYPE_CONTENT) || ApplicationModel.TYPE_FILELINK.equals(type))
- {
- resources.add(nodeRef);
- }
- }
- }
- }
- }
-
- Object[] answer = new Object[resources.size()];
- for (int i = 0; i < resources.size(); i++)
- {
- // create our Node representation from the NodeRef
- answer[i] = new ScriptNode(resources.get(i), serviceRegistry, getScope());
- }
- packageResources = Context.getCurrentContext().newArray(getScope(), answer);
-
}
/**
@@ -211,7 +97,7 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public String getId()
{
- return id;
+ return task.getId();
}
/**
@@ -221,7 +107,7 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public String getName()
{
- return name;
+ return task.getName();
}
/**
@@ -231,7 +117,7 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public String getTitle()
{
- return title;
+ return task.getTitle();
}
/**
@@ -241,7 +127,7 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public String getDescription()
{
- return description;
+ return task.getDescription();
}
/**
@@ -251,20 +137,26 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public Scriptable getProperties()
{
+ // instantiate ScriptableQNameMap properties
+ // from WorkflowTasks's Map properties
+ ScriptableQNameMap properties = new ScriptableQNameMap(namespaceProvider);
+ properties.putAll(task.getProperties());
return properties;
}
/**
- * Sets the value of the properties
property
+ * Sets the properties on the underlying {@link WorkflowTask}.
*
* @param properties
* the properties to set
*/
public void setProperties(ScriptableQNameMap properties)
{
- this.properties = properties;
+
+ Map qNameProps = properties.getMapOfQNames();
+ this.task = workflowService.updateTask(task.getId(), qNameProps, null, null);
}
-
+
/**
* Returns whether the task is complete 'true':complete, 'false':in-progress
*
@@ -272,7 +164,7 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public boolean isComplete()
{
- return complete;
+ return task.getState().equals(WorkflowTaskState.COMPLETED);
}
/**
@@ -282,15 +174,13 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public boolean isPooled()
{
- if(properties != null) {
- Collection> actors = (Collection>) properties.get(WorkflowModel.ASSOC_POOLED_ACTORS);
- return actors != null && !actors.isEmpty();
- }
- return false;
+ String authority = authenticationService.getCurrentUserName();
+ return workflowService.isTaskClaimable(task, authority);
}
/**
* @deprecated pooled state cannot be altered.
+ *
*/
@Deprecated
public void setPooled(boolean pooled)
@@ -306,7 +196,7 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public void endTask(String transitionId)
{
- serviceRegistry.getWorkflowService().endTask(this.id, transitionId);
+ workflowService.endTask(task.getId(), transitionId);
}
/**
@@ -316,6 +206,11 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public ScriptableHashMap getTransitions()
{
+ ScriptableHashMap transitions = new ScriptableHashMap();
+ for (WorkflowTransition transition : task.getPath().getNode().getTransitions())
+ {
+ transitions.put(transition.getId(), transition.getTitle());
+ }
return transitions;
}
@@ -326,7 +221,64 @@ public class JscriptWorkflowTask extends BaseScopableProcessorExtension implemen
*/
public Scriptable getPackageResources()
{
- return packageResources;
+ List contents = workflowService.getPackageContents(task.getId());
+ List resources = new ArrayList(contents.size());
+
+ Collection allowedTypes = getAllowedPackageResourceTypes();
+ for (NodeRef node : contents)
+ {
+ if (isAvmResource(node, allowedTypes))
+ {
+ ScriptNode scriptNode = new ScriptNode(node, serviceRegistry, getScope());
+ resources.add(scriptNode);
+ }
+ }
+ return Context.getCurrentContext().newArray(getScope(), resources.toArray());
}
+ private Collection getAllowedPackageResourceTypes()
+ {
+ // look for content nodes or links to content
+ // NOTE: folders within workflow packages are ignored for now
+ Collection allowedTypes = dictionaryService.getSubTypes(ContentModel.TYPE_CONTENT, true);
+ allowedTypes.addAll(dictionaryService.getSubTypes(ApplicationModel.TYPE_FILELINK, true));
+ return allowedTypes;
+ }
+
+ private boolean isAvmResource(NodeRef node, Collection allowedTypes)
+ {
+ if(isAvmNode(node))
+ return true;
+ if (nodeService.exists(node))
+ {
+ //Check if the node is one of the allowedTypes.
+ return allowedTypes.contains(nodeService.getType(node));
+ }
+ return false;
+ }
+
+ private boolean isAvmNode(NodeRef node)
+ {
+ return StoreRef.PROTOCOL_AVM.equals(node.getStoreRef().getProtocol());
+ }
+
+ private static class DefaultNamespaceProvider implements NamespacePrefixResolverProvider
+ {
+ private static final long serialVersionUID = -7015209142379905617L;
+ private final NamespaceService namespaceService;
+
+ public DefaultNamespaceProvider(NamespaceService namespaceService)
+ {
+ this.namespaceService = namespaceService;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NamespacePrefixResolver getNamespacePrefixResolver()
+ {
+ return namespaceService;
+ }
+
+ }
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/util/DatabaseMetaDataHelper.java b/source/java/org/alfresco/util/DatabaseMetaDataHelper.java
new file mode 100644
index 0000000000..8997b3bca1
--- /dev/null
+++ b/source/java/org/alfresco/util/DatabaseMetaDataHelper.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2005-2012 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.util;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Helper class to collect all of our DatabaseMetaData interpretations in one place.
+ *
+ * @author sfrensley
+ *
+ */
+public class DatabaseMetaDataHelper {
+
+ private static Log logger = LogFactory.getLog(DatabaseMetaDataHelper.class);
+
+ /**
+ * Trys to determine the schema name from the DatabaseMetaData obtained from the Connection.
+ * @param connection A database connection
+ * @return
+ */
+ public static String getSchema(Connection connection)
+ {
+
+ if (connection == null) {
+ logger.error("Unable to determine schema due to null connection.");
+ return null;
+ }
+
+ ResultSet schemas = null;
+
+ try
+ {
+ final DatabaseMetaData dbmd = connection.getMetaData();
+
+ // Assume that if there are schemas, we want the one named after the connection user or the one called "dbo" (MS
+ // SQL hack)
+ String schema = null;
+ schemas = dbmd.getSchemas();
+ while (schemas.next())
+ {
+ final String thisSchema = schemas.getString("TABLE_SCHEM");
+ if (thisSchema.equals(dbmd.getUserName()) || thisSchema.equalsIgnoreCase("dbo"))
+ {
+ schema = thisSchema;
+ break;
+ }
+ }
+ return schema;
+ }
+ catch (Exception e)
+ {
+ logger.error("Unable to determine current schema.",e);
+ }
+ finally
+ {
+ if (schemas != null)
+ {
+ try
+ {
+ schemas.close();
+ }
+ catch (Exception e)
+ {
+ //noop
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/source/java/org/alfresco/util/OpenOfficeCommandLine.java b/source/java/org/alfresco/util/OpenOfficeCommandLine.java
index ea8f36cf17..cc0416c726 100644
--- a/source/java/org/alfresco/util/OpenOfficeCommandLine.java
+++ b/source/java/org/alfresco/util/OpenOfficeCommandLine.java
@@ -55,7 +55,7 @@ public class OpenOfficeCommandLine extends AbstractMap>
if (variant.isLibreOffice3Dot5(officeHome))
{
command.add("--accept=" + acceptValue);
- if (variant.isMac())
+ if (variant.isMac() && !variant.isLibreOffice3Dot6(officeHome))
{
command.add("--env:UserInstallation=" + userInstallation);
}
@@ -70,7 +70,9 @@ public class OpenOfficeCommandLine extends AbstractMap>
//command.add("--nolockcheck"); included by JOD
command.add("--nologo");
command.add("--norestore");
- logger.info("Using GNU based LibreOffice command"+(variant.isMac() ? " on Mac" : "")+": "+command);
+ logger.info("Using GNU based LibreOffice "+
+ (variant.isLibreOffice3Dot6(officeHome) ? "3.6" : "3.5")+" command"+
+ (variant.isMac() ? " on Mac" : "")+": "+command);
}
else
{
diff --git a/source/java/org/alfresco/util/OpenOfficeVariant.java b/source/java/org/alfresco/util/OpenOfficeVariant.java
index d645cc72f6..97b7001f4c 100644
--- a/source/java/org/alfresco/util/OpenOfficeVariant.java
+++ b/source/java/org/alfresco/util/OpenOfficeVariant.java
@@ -109,19 +109,31 @@ public class OpenOfficeVariant
public boolean isLibreOffice3Dot5(File officeHome)
{
- logger.debug("System.getProperty(\"os.name\")="+System.getProperty("os.name"));
- logger.debug("officeHome="+(officeHome == null ? null : "'"+officeHome.getAbsolutePath()+"'"));
- logger.debug("basis-link:"+new File(officeHome, "basis-link").isFile());
- logger.debug(" ure-link:"+new File(officeHome, "ure-link").isFile());
- logger.debug("basis-link:"+new File(officeHome, "basis-link").isDirectory());
- logger.debug(" ure-link:"+new File(officeHome, "ure-link").isDirectory());
-
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("System.getProperty(\"os.name\")="+System.getProperty("os.name"));
+ logger.debug("officeHome="+(officeHome == null ? null : "'"+officeHome.getAbsolutePath()+"'"));
+ logger.debug("basis-link:"+new File(officeHome, "basis-link").isFile());
+ logger.debug("basis-link:"+new File(officeHome, "basis-link").isDirectory());
+ logger.debug(" ure-link:"+new File(officeHome, "ure-link").isFile());
+ logger.debug(" ure-link:"+new File(officeHome, "ure-link").isDirectory());
+ logger.debug(" NOTICE:"+new File(officeHome, "NOTICE").isFile());
+ }
return
officeHome != null &&
!new File(officeHome, "basis-link").isFile() &&
(new File(officeHome, "ure-link").isFile() || new File(officeHome, "ure-link").isDirectory());
}
+ public boolean isLibreOffice3Dot6(File officeHome)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(" NOTICE:"+new File(officeHome, "NOTICE").isFile());
+ }
+ return isLibreOffice3Dot5(officeHome) && new File(officeHome, "NOTICE").isFile();
+ }
+
public boolean isLinux()
{
return OS_NAME.startsWith("linux");