diff --git a/config/alfresco/avm-services-context.xml b/config/alfresco/avm-services-context.xml
index 518779a809..f335103458 100644
--- a/config/alfresco/avm-services-context.xml
+++ b/config/alfresco/avm-services-context.xml
@@ -332,6 +332,9 @@
+
+
+
diff --git a/config/alfresco/script-services-context.xml b/config/alfresco/script-services-context.xml
index e610ce2e7a..dd17c8b969 100644
--- a/config/alfresco/script-services-context.xml
+++ b/config/alfresco/script-services-context.xml
@@ -147,9 +147,6 @@
-
-
-
diff --git a/config/alfresco/template-services-context.xml b/config/alfresco/template-services-context.xml
index 7887d0c3cf..2768b21cc4 100644
--- a/config/alfresco/template-services-context.xml
+++ b/config/alfresco/template-services-context.xml
@@ -46,9 +46,6 @@
-
-
-
diff --git a/config/alfresco/wcm-services-context.xml b/config/alfresco/wcm-services-context.xml
index b68ddefdaf..3c25e90d56 100644
--- a/config/alfresco/wcm-services-context.xml
+++ b/config/alfresco/wcm-services-context.xml
@@ -3,6 +3,8 @@
+
+
@@ -49,22 +51,90 @@
-
+
+
+
+
+
+
+
+ org.alfresco.wcm.sandbox.SandboxService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${server.transaction.mode.readOnly}
+ ${server.transaction.mode.readOnly}
+ ${server.transaction.mode.readOnly}
+ ${server.transaction.mode.readOnly}
+ ${server.transaction.mode.default}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
webprojects
-
-
-
-
-
-
+
diff --git a/source/java/org/alfresco/repo/avm/AVMExpiredContentProcessor.java b/source/java/org/alfresco/repo/avm/AVMExpiredContentProcessor.java
index 5ce429af86..ae2b609d60 100644
--- a/source/java/org/alfresco/repo/avm/AVMExpiredContentProcessor.java
+++ b/source/java/org/alfresco/repo/avm/AVMExpiredContentProcessor.java
@@ -44,7 +44,7 @@ import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.workflow.WorkflowModel;
-import org.alfresco.sandbox.SandboxConstants;
+import org.alfresco.wcm.sandbox.SandboxConstants;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
@@ -66,9 +66,8 @@ import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
-import org.alfresco.util.DNSNameMangler;
-import org.alfresco.util.GUID;
import org.alfresco.util.Pair;
+import org.alfresco.wcm.sandbox.SandboxFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -97,6 +96,7 @@ public class AVMExpiredContentProcessor
protected TransactionService transactionService;
protected VirtServerRegistry virtServerRegistry;
protected SearchService searchService;
+ private SandboxFactory sandboxFactory;
private static Log logger = LogFactory.getLog(AVMExpiredContentProcessor.class);
@@ -171,6 +171,11 @@ public class AVMExpiredContentProcessor
{
this.avmLockingAwareService = avmLockingAwareService;
}
+
+ public void setSandboxFactory(SandboxFactory sandboxFactory)
+ {
+ this.sandboxFactory = sandboxFactory;
+ }
/**
* Executes the expired content processor.
@@ -425,7 +430,7 @@ public class AVMExpiredContentProcessor
NodeRef assignee = this.personService.getPerson(userName);
// create a workflow store layered over the users store
- String workflowStoreName = createUserWorkflowSandbox(storeName, userStore);
+ String workflowStoreName = sandboxFactory.createUserWorkflowSandbox(storeName, userStore);
// create a workflow package with all the expired items
NodeRef workflowPackage = setupWorkflowPackage(workflowStoreName, expiredContent);
@@ -453,124 +458,6 @@ public class AVMExpiredContentProcessor
}
}
}
-
- /**
- * Creates a workflow sandbox for the given user store. This will create a
- * workflow sandbox layered over the user's main store.
- *
- * @param stagingStore The name of the staging store the user sandbox is layered over
- * @param userStore The name of the user store to create the workflow for
- * @return The store name of the main store in the workflow sandbox
- */
- private String createUserWorkflowSandbox(String stagingStore, String userStore)
- {
- // create the workflow 'main' store
- String packageName = "workflow-" + GUID.generate();
- String workflowStoreName = userStore + STORE_SEPARATOR + packageName;
-
- this.avmService.createStore(workflowStoreName);
-
- if (logger.isDebugEnabled())
- logger.debug("Created user workflow sandbox store: " + workflowStoreName);
-
- // create a layered directory pointing to 'www' in the users store
- this.avmService.createLayeredDirectory(
- userStore + ":/" + JNDIConstants.DIR_DEFAULT_WWW,
- workflowStoreName + ":/", JNDIConstants.DIR_DEFAULT_WWW);
-
- // tag the store with the store type
- this.avmService.setStoreProperty(workflowStoreName,
- SandboxConstants.PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN,
- new PropertyValue(DataTypeDefinition.TEXT, null));
-
- // tag the store with the name of the author's store this one is layered over
- this.avmService.setStoreProperty(workflowStoreName,
- SandboxConstants.PROP_AUTHOR_NAME,
- new PropertyValue(DataTypeDefinition.TEXT, userStore));
-
- // tag the store, oddly enough, with its own store name for querying.
- this.avmService.setStoreProperty(workflowStoreName,
- QName.createQName(null, SandboxConstants.PROP_SANDBOX_STORE_PREFIX + workflowStoreName),
- new PropertyValue(DataTypeDefinition.TEXT, null));
-
- // tag the store with the DNS name property
- String path = workflowStoreName + ":/" + JNDIConstants.DIR_DEFAULT_WWW +
- "/" + JNDIConstants.DIR_DEFAULT_APPBASE;
- // DNS name mangle the property name - can only contain value DNS characters!
- String dnsProp = SandboxConstants.PROP_DNS + DNSNameMangler.MakeDNSName(stagingStore, packageName);
- this.avmService.setStoreProperty(workflowStoreName, QName.createQName(null, dnsProp),
- new PropertyValue(DataTypeDefinition.TEXT, path));
-
- // the main workflow store depends on the main user store (dist=1)
- String prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + userStore;
- this.avmService.setStoreProperty(workflowStoreName, QName.createQName(null, prop_key),
- new PropertyValue(DataTypeDefinition.INT, 1));
-
- // The main workflow store depends on the main staging store (dist=2)
- prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + stagingStore;
- this.avmService.setStoreProperty(workflowStoreName, QName.createQName(null, prop_key),
- new PropertyValue(DataTypeDefinition.INT, 2));
-
- // snapshot the store
- this.avmService.createSnapshot(workflowStoreName, null, null);
-
- // create the workflow 'preview' store
- String previewStoreName = workflowStoreName + STORE_SEPARATOR + "preview";
- this.avmService.createStore(previewStoreName);
-
- if (logger.isDebugEnabled())
- logger.debug("Created user workflow sandbox preview store: " + previewStoreName);
-
- // create a layered directory pointing to 'www' in the workflow 'main' store
- this.avmService.createLayeredDirectory(
- workflowStoreName + ":/" + JNDIConstants.DIR_DEFAULT_WWW,
- previewStoreName + ":/", JNDIConstants.DIR_DEFAULT_WWW);
-
- // tag the store with the store type
- this.avmService.setStoreProperty(previewStoreName, SandboxConstants.PROP_SANDBOX_WORKFLOW_PREVIEW,
- new PropertyValue(DataTypeDefinition.TEXT, null));
-
- // tag the store with its own store name for querying.
- avmService.setStoreProperty(previewStoreName,
- QName.createQName(null, SandboxConstants.PROP_SANDBOX_STORE_PREFIX + previewStoreName),
- new PropertyValue(DataTypeDefinition.TEXT, null));
-
- // tag the store with the DNS name property
- path = previewStoreName + ":/" + JNDIConstants.DIR_DEFAULT_WWW +
- "/" + JNDIConstants.DIR_DEFAULT_APPBASE;
- // DNS name mangle the property name - can only contain value DNS characters!
- dnsProp = SandboxConstants.PROP_DNS + DNSNameMangler.MakeDNSName(userStore, packageName, "preview");
- this.avmService.setStoreProperty(previewStoreName, QName.createQName(null, dnsProp),
- new PropertyValue(DataTypeDefinition.TEXT, path));
-
- // The preview worfkflow store depends on the main workflow store (dist=1)
- prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + workflowStoreName;
- this.avmService.setStoreProperty(previewStoreName, QName.createQName(null, prop_key),
- new PropertyValue(DataTypeDefinition.INT, 1));
-
- // The preview workflow store depends on the main user store (dist=2)
- prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + userStore;
- this.avmService.setStoreProperty(previewStoreName, QName.createQName(null, prop_key),
- new PropertyValue(DataTypeDefinition.INT, 2));
-
- // The preview workflow store depends on the main staging store (dist=3)
- prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + stagingStore;
- this.avmService.setStoreProperty(previewStoreName, QName.createQName(null, prop_key),
- new PropertyValue(DataTypeDefinition.INT, 3));
-
- // snapshot the store
- this.avmService.createSnapshot(previewStoreName, null, null);
-
- // tag all related stores to indicate that they are part of a single sandbox
- QName sandboxIdProp = QName.createQName(SandboxConstants.PROP_SANDBOXID + GUID.generate());
- this.avmService.setStoreProperty(workflowStoreName, sandboxIdProp,
- new PropertyValue(DataTypeDefinition.TEXT, null));
- this.avmService.setStoreProperty(previewStoreName, sandboxIdProp,
- new PropertyValue(DataTypeDefinition.TEXT, null));
-
- // return the main workflow store name
- return workflowStoreName;
- }
/**
* Sets up a workflow package from the given main workflow store and applies
diff --git a/source/java/org/alfresco/repo/jscript/AVM.java b/source/java/org/alfresco/repo/jscript/AVM.java
index f084d40317..51bab1342a 100644
--- a/source/java/org/alfresco/repo/jscript/AVM.java
+++ b/source/java/org/alfresco/repo/jscript/AVM.java
@@ -24,22 +24,17 @@
*/
package org.alfresco.repo.jscript;
-import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import org.alfresco.config.JNDIConstants;
import org.alfresco.repo.avm.AVMNodeConverter;
-import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
-import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
-import org.alfresco.service.cmr.avmsync.AVMDifference;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.util.NameMatcher;
import org.alfresco.util.ParameterCheck;
+import org.alfresco.wcm.sandbox.SandboxService;
+import org.alfresco.wcm.util.WCMUtil;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
@@ -52,8 +47,6 @@ public final class AVM extends BaseScopableProcessorExtension
{
/** Repository Service Registry */
private ServiceRegistry services;
-
- private NameMatcher matcher;
/**
* Set the service registry
@@ -64,11 +57,6 @@ public final class AVM extends BaseScopableProcessorExtension
{
this.services = serviceRegistry;
}
-
- public void setNameMatcher(NameMatcher matcher)
- {
- this.matcher = matcher;
- }
/**
* @return a array of all AVM stores in the system
@@ -163,28 +151,17 @@ public final class AVM extends BaseScopableProcessorExtension
ParameterCheck.mandatoryString("Username", username);
ParameterCheck.mandatoryString("Webapp", webapp);
- List items;
-
- AVMService avmService = this.services.getAVMService();
-
- // build the paths to the stores to compare - filter by current webapp
- String userStore = userSandboxStore(storeId, username);
- String userStorePath = getStoreRootWebappPath(userStore, webapp);
- String stagingStore = stagingStore(storeId);
- String stagingStorePath = getStoreRootWebappPath(stagingStore, webapp);
+ SandboxService sbService = this.services.getSandboxService();
- List diffs = this.services.getAVMSyncService().compare(
- -1, userStorePath, -1, stagingStorePath, this.matcher);
- items = new ArrayList(diffs.size());
- for (AVMDifference diff : diffs)
+ // get modified items - not including deleted
+ List nodes = sbService.listChangedItemsWebApp(storeId, webapp, false);
+
+ List items = new ArrayList(nodes.size());
+
+ for (AVMNodeDescriptor node : nodes)
{
- // convert each diff record into an AVM Node template wrapper
- String sourcePath = diff.getSourcePath();
- AVMNodeDescriptor node = avmService.lookup(-1, sourcePath);
- if (node != null)
- {
- items.add(new AVMNode(node.getPath(), -1, this.services, getScope()));
- }
+ // convert each diff/node record into an AVM Node wrapper
+ items.add(new AVMNode(node.getPath(), -1, this.services, getScope()));
}
return items;
@@ -197,8 +174,7 @@ public final class AVM extends BaseScopableProcessorExtension
*/
public static String stagingStore(String storeId)
{
- ParameterCheck.mandatoryString("Store ID", storeId);
- return storeId;
+ return WCMUtil.buildStagingStoreName(storeId);
}
/**
@@ -209,9 +185,7 @@ public final class AVM extends BaseScopableProcessorExtension
*/
public static String userSandboxStore(String storeId, String username)
{
- ParameterCheck.mandatoryString("Store ID", storeId);
- ParameterCheck.mandatoryString("Username", username);
- return storeId + "--" + username;
+ return WCMUtil.buildUserMainStoreName(storeId, username);
}
/**
@@ -221,9 +195,7 @@ public final class AVM extends BaseScopableProcessorExtension
*/
public String websiteStagingUrl(String storeId)
{
- ParameterCheck.mandatoryString("Store ID", storeId);
- return MessageFormat.format(JNDIConstants.PREVIEW_SANDBOX_URL,
- lookupStoreDNS(storeId), getVServerDomain(), getVServerPort());
+ return WCMUtil.buildStoreUrl(this.services.getAVMService(), storeId, getVServerDomain(), getVServerPort());
}
/**
@@ -247,25 +219,7 @@ public final class AVM extends BaseScopableProcessorExtension
*/
public String assetUrl(String store, String assetPath)
{
- ParameterCheck.mandatoryString("Store", store);
- ParameterCheck.mandatoryString("Asset Path", assetPath);
-
- if (assetPath.startsWith('/' + JNDIConstants.DIR_DEFAULT_WWW +
- '/' + JNDIConstants.DIR_DEFAULT_APPBASE))
- {
- assetPath = assetPath.substring(('/' + JNDIConstants.DIR_DEFAULT_WWW +
- '/' + JNDIConstants.DIR_DEFAULT_APPBASE).length());
- }
- if (assetPath.startsWith("/ROOT"))
- {
- assetPath = assetPath.substring(("/ROOT").length());
- }
- if (assetPath.length() == 0 || assetPath.charAt(0) != '/')
- {
- assetPath = '/' + assetPath;
- }
- return MessageFormat.format(JNDIConstants.PREVIEW_ASSET_URL,
- lookupStoreDNS(store), getVServerDomain(), getVServerPort(), assetPath);
+ return WCMUtil.buildAssetUrl(assetPath, getVServerDomain(), getVServerPort(), WCMUtil.lookupStoreDNS(this.services.getAVMService(), store));
}
/**
@@ -315,27 +269,6 @@ public final class AVM extends BaseScopableProcessorExtension
*/
public static String getWebappsFolderPath()
{
- return '/' + JNDIConstants.DIR_DEFAULT_WWW +
- '/' + JNDIConstants.DIR_DEFAULT_APPBASE;
+ return JNDIConstants.DIR_DEFAULT_WWW_APPBASE;
}
-
- private static String getStoreRootPath(String store)
- {
- return store + ":" + getWebappsFolderPath();
- }
-
- private static String getStoreRootWebappPath(String store, String webapp)
- {
- return getStoreRootPath(store) + '/' + webapp;
- }
-
- private String lookupStoreDNS(String store)
- {
- Map props =
- this.services.getAVMService().queryStorePropertyKey(store, QName.createQName(null, PROP_DNS + '%'));
- return (props.size() == 1
- ? props.keySet().iterator().next().getLocalName().substring(PROP_DNS.length()) : null);
- }
-
- private final static String PROP_DNS = ".dns.";
}
diff --git a/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java b/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java
index 496c537c36..13a2872f7f 100644
--- a/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java
+++ b/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java
@@ -69,6 +69,7 @@ import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.wcm.sandbox.SandboxService;
import org.alfresco.wcm.webproject.WebProjectService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
@@ -466,6 +467,13 @@ public class ServiceDescriptorRegistry
* @see org.alfresco.service.ServiceRegistry#getWebProjectService()
*/
public WebProjectService getWebProjectService() {
- return (WebProjectService) getService(WEBPROJECT_SERVICE);
+ return (WebProjectService)getService(WEBPROJECT_SERVICE);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.ServiceRegistry#getSandboxService()
+ */
+ public SandboxService getSandboxService() {
+ return (SandboxService)getService(SANDBOX_SERVICE);
}
}
diff --git a/source/java/org/alfresco/repo/template/AVM.java b/source/java/org/alfresco/repo/template/AVM.java
index 9f3fe48fa1..1c4498624f 100644
--- a/source/java/org/alfresco/repo/template/AVM.java
+++ b/source/java/org/alfresco/repo/template/AVM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,21 +24,16 @@
*/
package org.alfresco.repo.template;
-import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import org.alfresco.config.JNDIConstants;
-import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
-import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
-import org.alfresco.service.cmr.avmsync.AVMDifference;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.util.NameMatcher;
import org.alfresco.util.ParameterCheck;
+import org.alfresco.wcm.sandbox.SandboxService;
+import org.alfresco.wcm.util.WCMUtil;
/**
* AVM root object access for a template model.
@@ -48,7 +43,6 @@ import org.alfresco.util.ParameterCheck;
public class AVM extends BaseTemplateProcessorExtension
{
private ServiceRegistry services;
- private NameMatcher matcher;
/**
* Sets the service registry
@@ -60,11 +54,6 @@ public class AVM extends BaseTemplateProcessorExtension
this.services = services;
}
- public void setNameMatcher(NameMatcher matcher)
- {
- this.matcher = matcher;
- }
-
/**
* @return a list of all AVM stores in the system
*/
@@ -152,28 +141,17 @@ public class AVM extends BaseTemplateProcessorExtension
ParameterCheck.mandatoryString("Username", username);
ParameterCheck.mandatoryString("Webapp", webapp);
- List items;
-
- AVMService avmService = this.services.getAVMService();
-
- // build the paths to the stores to compare - filter by current webapp
- String userStore = userSandboxStore(storeId, username);
- String userStorePath = getStoreRootWebappPath(userStore, webapp);
- String stagingStore = stagingStore(storeId);
- String stagingStorePath = getStoreRootWebappPath(stagingStore, webapp);
+ SandboxService sbService = this.services.getSandboxService();
- List diffs = this.services.getAVMSyncService().compare(
- -1, userStorePath, -1, stagingStorePath, this.matcher);
- items = new ArrayList(diffs.size());
- for (AVMDifference diff : diffs)
+ // get modified items - not including deleted
+ List nodes = sbService.listChangedItemsWebApp(storeId, webapp, false);
+
+ List items = new ArrayList(nodes.size());
+
+ for (AVMNodeDescriptor node : nodes)
{
- // convert each diff record into an AVM Node template wrapper
- String sourcePath = diff.getSourcePath();
- AVMNodeDescriptor node = avmService.lookup(-1, sourcePath);
- if (node != null)
- {
- items.add(new AVMTemplateNode(node, this.services, getTemplateImageResolver()));
- }
+ // convert each diff/node record into an AVM Node template wrapper
+ items.add(new AVMTemplateNode(node, this.services, getTemplateImageResolver()));
}
return items;
@@ -186,8 +164,7 @@ public class AVM extends BaseTemplateProcessorExtension
*/
public static String stagingStore(String storeId)
{
- ParameterCheck.mandatoryString("Store ID", storeId);
- return storeId;
+ return WCMUtil.buildStagingStoreName(storeId);
}
/**
@@ -198,9 +175,7 @@ public class AVM extends BaseTemplateProcessorExtension
*/
public static String userSandboxStore(String storeId, String username)
{
- ParameterCheck.mandatoryString("Store ID", storeId);
- ParameterCheck.mandatoryString("Username", username);
- return storeId + "--" + username;
+ return WCMUtil.buildUserMainStoreName(storeId, username);
}
/**
@@ -210,9 +185,7 @@ public class AVM extends BaseTemplateProcessorExtension
*/
public String websiteStagingUrl(String storeId)
{
- ParameterCheck.mandatoryString("Store ID", storeId);
- return MessageFormat.format(JNDIConstants.PREVIEW_SANDBOX_URL,
- lookupStoreDNS(storeId), getVServerDomain(), getVServerPort());
+ return WCMUtil.buildStoreUrl(this.services.getAVMService(), storeId, getVServerDomain(), getVServerPort());
}
/**
@@ -236,25 +209,7 @@ public class AVM extends BaseTemplateProcessorExtension
*/
public String assetUrl(String store, String assetPath)
{
- ParameterCheck.mandatoryString("Store", store);
- ParameterCheck.mandatoryString("Asset Path", assetPath);
-
- if (assetPath.startsWith('/' + JNDIConstants.DIR_DEFAULT_WWW +
- '/' + JNDIConstants.DIR_DEFAULT_APPBASE))
- {
- assetPath = assetPath.substring(('/' + JNDIConstants.DIR_DEFAULT_WWW +
- '/' + JNDIConstants.DIR_DEFAULT_APPBASE).length());
- }
- if (assetPath.startsWith("/ROOT"))
- {
- assetPath = assetPath.substring(("/ROOT").length());
- }
- if (assetPath.length() == 0 || assetPath.charAt(0) != '/')
- {
- assetPath = '/' + assetPath;
- }
- return MessageFormat.format(JNDIConstants.PREVIEW_ASSET_URL,
- lookupStoreDNS(store), getVServerDomain(), getVServerPort(), assetPath);
+ return WCMUtil.buildAssetUrl(assetPath, getVServerDomain(), getVServerPort(), WCMUtil.lookupStoreDNS(this.services.getAVMService(), store));
}
/**
@@ -304,27 +259,6 @@ public class AVM extends BaseTemplateProcessorExtension
*/
public static String getWebappsFolderPath()
{
- return '/' + JNDIConstants.DIR_DEFAULT_WWW +
- '/' + JNDIConstants.DIR_DEFAULT_APPBASE;
+ return JNDIConstants.DIR_DEFAULT_WWW_APPBASE;
}
-
- private static String getStoreRootPath(String store)
- {
- return store + ":" + getWebappsFolderPath();
- }
-
- private static String getStoreRootWebappPath(String store, String webapp)
- {
- return getStoreRootPath(store) + '/' + webapp;
- }
-
- private String lookupStoreDNS(String store)
- {
- Map props =
- this.services.getAVMService().queryStorePropertyKey(store, QName.createQName(null, PROP_DNS + '%'));
- return (props.size() == 1
- ? props.keySet().iterator().next().getLocalName().substring(PROP_DNS.length()) : null);
- }
-
- private final static String PROP_DNS = ".dns.";
}
diff --git a/source/java/org/alfresco/service/ServiceRegistry.java b/source/java/org/alfresco/service/ServiceRegistry.java
index 8515ffc46e..e5343ef4df 100644
--- a/source/java/org/alfresco/service/ServiceRegistry.java
+++ b/source/java/org/alfresco/service/ServiceRegistry.java
@@ -33,6 +33,7 @@ import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.attributes.AttributeService;
import org.alfresco.service.cmr.audit.AuditService;
import org.alfresco.service.cmr.avm.AVMService;
+import org.alfresco.service.cmr.avm.deploy.DeploymentService;
import org.alfresco.service.cmr.avm.locking.AVMLockingService;
import org.alfresco.service.cmr.avmsync.AVMSyncService;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
@@ -62,12 +63,12 @@ import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.view.ExporterService;
import org.alfresco.service.cmr.view.ImporterService;
-import org.alfresco.service.cmr.avm.deploy.DeploymentService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.wcm.sandbox.SandboxService;
import org.alfresco.wcm.webproject.WebProjectService;
@@ -129,6 +130,7 @@ public interface ServiceRegistry
static final QName TAGGING_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TaggingService");
static final QName DEPLOYMENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DeploymentService");
static final QName WEBPROJECT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "WebProjectService");
+ static final QName SANDBOX_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SandboxService");
/**
* Get the list of services provided by the Repository
@@ -429,4 +431,11 @@ public interface ServiceRegistry
*/
@NotAuditable
WebProjectService getWebProjectService();
+
+ /**
+ * Get the Sandbox Service
+ * @return
+ */
+ @NotAuditable
+ SandboxService getSandboxService();
}
diff --git a/source/java/org/alfresco/wcm/WCMTestSuite.java b/source/java/org/alfresco/wcm/WCMTestSuite.java
new file mode 100644
index 0000000000..169a66060b
--- /dev/null
+++ b/source/java/org/alfresco/wcm/WCMTestSuite.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005-2008 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.wcm;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.alfresco.wcm.sandbox.SandboxServiceImplTest;
+import org.alfresco.wcm.webproject.WebProjectServiceImplTest;
+
+/**
+ * WCM test suite
+ *
+ * @author janv
+ */
+public class WCMTestSuite extends TestSuite
+{
+ /**
+ * Creates the test suite
+ *
+ * @return the test suite
+ */
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite();
+
+ suite.addTestSuite(WebProjectServiceImplTest.class);
+ suite.addTestSuite(SandboxServiceImplTest.class);
+
+ return suite;
+ }
+}
diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxConstants.java b/source/java/org/alfresco/wcm/sandbox/SandboxConstants.java
index 9857eb7d3a..c4afed6536 100644
--- a/source/java/org/alfresco/wcm/sandbox/SandboxConstants.java
+++ b/source/java/org/alfresco/wcm/sandbox/SandboxConstants.java
@@ -43,6 +43,7 @@ public class SandboxConstants
public final static String PROP_DNS = ".dns.";
public final static String PROP_SANDBOX_STORE_PREFIX = ".sandbox.store.";
+ // sandbox type
public final static QName PROP_SANDBOX_STAGING_MAIN = QName.createQName(null, ".sandbox.staging.main");
public final static QName PROP_SANDBOX_STAGING_PREVIEW = QName.createQName(null, ".sandbox.staging.preview");
public final static QName PROP_SANDBOX_AUTHOR_MAIN = QName.createQName(null, ".sandbox.author.main");
@@ -51,6 +52,7 @@ public class SandboxConstants
public final static QName PROP_SANDBOX_WORKFLOW_PREVIEW = QName.createQName(null, ".sandbox.workflow.preview");
public final static QName PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN = QName.createQName(null, ".sandbox.author.workflow.main");
public final static QName PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW = QName.createQName(null, ".sandbox.author.workflow.preview");
+
public final static QName PROP_WEBSITE_NAME = QName.createQName(null, ".website.name");
public final static QName PROP_AUTHOR_NAME = QName.createQName(null, ".author.name");
public final static QName PROP_WEB_PROJECT_NODE_REF = QName.createQName(null, ".web_project.noderef");
diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxFactory.java b/source/java/org/alfresco/wcm/sandbox/SandboxFactory.java
index c9f082c927..21fde3cb21 100644
--- a/source/java/org/alfresco/wcm/sandbox/SandboxFactory.java
+++ b/source/java/org/alfresco/wcm/sandbox/SandboxFactory.java
@@ -24,24 +24,29 @@
*/
package org.alfresco.wcm.sandbox;
+import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import java.util.Map;
import org.alfresco.config.JNDIConstants;
-import org.alfresco.model.WCMAppModel;
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.mbeans.VirtServerRegistry;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.avm.AVMService;
+import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
+import org.alfresco.service.cmr.avm.locking.AVMLockingService;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
-import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
-import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.DNSNameMangler;
import org.alfresco.util.GUID;
+import org.alfresco.util.ParameterCheck;
import org.alfresco.wcm.util.WCMUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -57,9 +62,11 @@ public final class SandboxFactory extends WCMUtil
private static Log logger = LogFactory.getLog(SandboxFactory.class);
/** Services */
+ private NodeService nodeService;
private PermissionService permissionService;
private AVMService avmService;
- private NodeService nodeService;
+ private AVMLockingService avmLockingService;
+ private VirtServerRegistry virtServerRegistry;
public void setNodeService(NodeService nodeService)
{
@@ -76,6 +83,17 @@ public final class SandboxFactory extends WCMUtil
this.avmService = avmService;
}
+ public void setAvmLockingService(AVMLockingService avmLockingService)
+ {
+ this.avmLockingService = avmLockingService;
+ }
+
+ public void setVirtServerRegistry(VirtServerRegistry virtServerRegistry)
+ {
+ this.virtServerRegistry = virtServerRegistry;
+ }
+
+
/**
* Private constructor
*/
@@ -109,7 +127,7 @@ public final class SandboxFactory extends WCMUtil
if (logger.isDebugEnabled())
{
- logger.debug("Created staging sandbox store: " + stagingStoreName);
+ logger.debug("Created staging sandbox: " + stagingStoreName);
}
// we can either branch from an existing staging store or create a new structure
@@ -200,27 +218,100 @@ public final class SandboxFactory extends WCMUtil
dumpStoreProperties(avmService, previewStoreName);
}
- return new SandboxInfo( new String[] { stagingStoreName, previewStoreName } );
+ return getSandbox(stagingStoreName);
+ }
+
+ /**
+ * Get sandbox info for given sandbox store id
+ *
+ * @param sandboxId
+ * @return SandboxInfo returns sandbox info or null if sandbox does not exist or is not visible
+ */
+ public SandboxInfo getSandbox(String sandboxId)
+ {
+ AVMStoreDescriptor storeDesc = avmService.getStore(sandboxId);
+ if (storeDesc == null)
+ {
+ return null;
+ }
+
+ String wpStoreId = WCMUtil.getWebProjectStoreId(sandboxId);
+
+ String[] storeNames = null;
+
+ // Check sandbox type
+ Map props = avmService.getStoreProperties(sandboxId);
+ QName sandboxType = null;
+
+ // derive name for now
+ String name = null;
+
+ if (props.containsKey(SandboxConstants.PROP_SANDBOX_STAGING_MAIN))
+ {
+ sandboxType = SandboxConstants.PROP_SANDBOX_STAGING_MAIN;
+ name = sandboxId;
+ storeNames = new String[] {sandboxId, WCMUtil.getCorrespondingPreviewStoreName(sandboxId)};
+ }
+ else if ( props.containsKey( SandboxConstants.PROP_SANDBOX_STAGING_PREVIEW))
+ {
+ sandboxType = SandboxConstants.PROP_SANDBOX_STAGING_PREVIEW;
+ storeNames = new String[] {WCMUtil.getCorrespondingMainStoreName(sandboxId), sandboxId};
+ }
+ else if (props.containsKey(SandboxConstants.PROP_SANDBOX_AUTHOR_MAIN))
+ {
+ sandboxType = SandboxConstants.PROP_SANDBOX_AUTHOR_MAIN;
+ name = WCMUtil.getUserName(sandboxId);
+ storeNames = new String[] {sandboxId, WCMUtil.getCorrespondingPreviewStoreName(sandboxId)};
+ }
+ else if (props.containsKey(SandboxConstants.PROP_SANDBOX_AUTHOR_PREVIEW))
+ {
+ sandboxType = SandboxConstants.PROP_SANDBOX_AUTHOR_PREVIEW;
+ name = WCMUtil.getUserName(sandboxId);
+ storeNames = new String[] {WCMUtil.getCorrespondingMainStoreName(sandboxId), sandboxId};
+ }
+ else if (props.containsKey(SandboxConstants.PROP_SANDBOX_WORKFLOW_MAIN))
+ {
+ sandboxType = SandboxConstants.PROP_SANDBOX_WORKFLOW_MAIN;
+ name = WCMUtil.getWorkflowId(sandboxId);
+ storeNames = new String[] {sandboxId, WCMUtil.getCorrespondingPreviewStoreName(sandboxId)};
+ }
+ else if (props.containsKey(SandboxConstants.PROP_SANDBOX_WORKFLOW_PREVIEW))
+ {
+ sandboxType = SandboxConstants.PROP_SANDBOX_WORKFLOW_PREVIEW;
+ name = WCMUtil.getWorkflowId(sandboxId);
+ storeNames = new String[] {WCMUtil.getCorrespondingMainStoreName(sandboxId), sandboxId};
+ }
+
+ if ((storeNames == null) || (storeNames.length == 0))
+ {
+ throw new AlfrescoRuntimeException("Must have at least one store");
+ }
+
+ if ((storeNames.length == 1) && (! sandboxType.equals(SandboxConstants.PROP_SANDBOX_STAGING_MAIN)))
+ {
+ throw new AlfrescoRuntimeException("Main store must be of type: " + SandboxConstants.PROP_SANDBOX_STAGING_MAIN);
+ }
+
+ return new SandboxInfoImpl(wpStoreId, sandboxId, sandboxType, name, storeNames, new Date(storeDesc.getCreateDate()), storeDesc.getCreator());
}
- protected void setStagingPermissions(String storeId, NodeRef webProjectNodeRef)
+ protected void setStagingPermissions(String storeId, NodeRef wpNodeRef)
{
- String storeName = WCMUtil.buildStagingStoreName(storeId);
- NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName));
-
- // Apply sepcific user permissions as set on the web project
- // All these will be masked out
- List userInfoRefs = nodeService.getChildAssocs(
- webProjectNodeRef, WCMAppModel.ASSOC_WEBUSER, RegexQNamePattern.MATCH_ALL);
+ String storeName = WCMUtil.buildStagingStoreName(storeId);
+ NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName));
- for (ChildAssociationRef ref : userInfoRefs)
- {
- NodeRef userInfoRef = ref.getChildRef();
- String username = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME);
- String userrole = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERROLE);
+ // Apply specific user permissions as set on the web project
+ // All these will be masked out
- permissionService.setPermission(dirRef, username, userrole, true);
- }
+ Map userRoles = WCMUtil.listWebUsers(nodeService, wpNodeRef);
+
+ for (Map.Entry userRole : userRoles.entrySet())
+ {
+ String username = userRole.getKey();
+ String userrole = userRole.getValue();
+
+ permissionService.setPermission(dirRef, username, userrole, true);
+ }
}
public void setStagingPermissionMasks(String storeId)
@@ -238,7 +329,7 @@ public final class SandboxFactory extends WCMUtil
permissionService.setPermission(dirRef, PermissionService.ALL_AUTHORITIES, PermissionService.READ, true);
}
- public void updateStagingAreaManagers(String storeId, NodeRef webProjectNodeRef, final List managers)
+ private void updateStagingAreaManagers(String storeId, NodeRef webProjectNodeRef, final List managers)
{
// The stores have the mask set in updateSandboxManagers
String storeName = WCMUtil.buildStagingStoreName(storeId);
@@ -256,10 +347,10 @@ public final class SandboxFactory extends WCMUtil
}
}
- public void addStagingAreaUser(String storeId, String authority, String role)
+ public void addStagingAreaUser(String wpStoreId, String authority, String role)
{
// The stores have the mask set in updateSandboxManagers
- String storeName = WCMUtil.buildStagingStoreName(storeId);
+ String storeName = WCMUtil.buildStagingStoreName(wpStoreId);
NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName));
permissionService.setPermission(dirRef, authority, role, true);
@@ -293,20 +384,23 @@ public final class SandboxFactory extends WCMUtil
String userStoreName = WCMUtil.buildUserMainStoreName(storeId, username);
String previewStoreName = WCMUtil.buildUserPreviewStoreName(storeId, username);
- if (avmService.getStore(userStoreName) != null)
+ SandboxInfo userSandboxInfo = getSandbox(userStoreName);
+ if (userSandboxInfo != null)
{
- if (logger.isDebugEnabled())
- {
- logger.debug("Not creating as store already exists: " + userStoreName);
- }
- return new SandboxInfo( new String[] { userStoreName, previewStoreName } );
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Not creating author sandbox as it already exists: " + userStoreName);
+ }
+ return userSandboxInfo;
}
avmService.createStore(userStoreName);
String stagingStoreName = WCMUtil.buildStagingStoreName(storeId);
+
if (logger.isDebugEnabled())
- logger.debug("Created user sandbox store: " + userStoreName +
- " above staging store " + stagingStoreName);
+ {
+ logger.debug("Created user sandbox: " + userStoreName + " above staging store " + stagingStoreName);
+ }
// create a layered directory pointing to 'www' in the staging area
avmService.createLayeredDirectory(WCMUtil.buildStoreRootPath(stagingStoreName),
@@ -417,7 +511,8 @@ public final class SandboxFactory extends WCMUtil
dumpStoreProperties(avmService, userStoreName);
dumpStoreProperties(avmService, previewStoreName);
}
- return new SandboxInfo( new String[] { userStoreName, previewStoreName } );
+
+ return getSandbox(userStoreName);
}
/**
@@ -533,7 +628,232 @@ public final class SandboxFactory extends WCMUtil
dumpStoreProperties(avmService, mainStoreName);
dumpStoreProperties(avmService, previewStoreName);
}
- return new SandboxInfo( new String[] { mainStoreName, previewStoreName } );
+
+ return getSandbox(mainStoreName);
+ }
+
+ /**
+ * Creates a workflow sandbox for the given user store. This will create a
+ * workflow sandbox layered over the user's main store.
+ *
+ * @param stagingStore The name of the staging store the user sandbox is layered over
+ * @param userStore The name of the user store to create the workflow for
+ * @return The store name of the main store in the workflow sandbox
+ */
+ // TODO refactor AVMExpiredContentProcessor ...
+ public String createUserWorkflowSandbox(String stagingStore, String userStore)
+ {
+ // create the workflow 'main' store
+ String packageName = "workflow-" + GUID.generate();
+ String workflowStoreName = userStore + STORE_SEPARATOR + packageName;
+
+ this.avmService.createStore(workflowStoreName);
+
+ if (logger.isDebugEnabled())
+ logger.debug("Created user workflow sandbox store: " + workflowStoreName);
+
+ // create a layered directory pointing to 'www' in the users store
+ this.avmService.createLayeredDirectory(
+ userStore + ":/" + JNDIConstants.DIR_DEFAULT_WWW,
+ workflowStoreName + ":/", JNDIConstants.DIR_DEFAULT_WWW);
+
+ // tag the store with the store type
+ this.avmService.setStoreProperty(workflowStoreName,
+ SandboxConstants.PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN,
+ new PropertyValue(DataTypeDefinition.TEXT, null));
+
+ // tag the store with the name of the author's store this one is layered over
+ this.avmService.setStoreProperty(workflowStoreName,
+ SandboxConstants.PROP_AUTHOR_NAME,
+ new PropertyValue(DataTypeDefinition.TEXT, userStore));
+
+ // tag the store, oddly enough, with its own store name for querying.
+ this.avmService.setStoreProperty(workflowStoreName,
+ QName.createQName(null, SandboxConstants.PROP_SANDBOX_STORE_PREFIX + workflowStoreName),
+ new PropertyValue(DataTypeDefinition.TEXT, null));
+
+ // tag the store with the DNS name property
+ String path = workflowStoreName + ":/" + JNDIConstants.DIR_DEFAULT_WWW +
+ "/" + JNDIConstants.DIR_DEFAULT_APPBASE;
+ // DNS name mangle the property name - can only contain value DNS characters!
+ String dnsProp = SandboxConstants.PROP_DNS + DNSNameMangler.MakeDNSName(stagingStore, packageName);
+ this.avmService.setStoreProperty(workflowStoreName, QName.createQName(null, dnsProp),
+ new PropertyValue(DataTypeDefinition.TEXT, path));
+
+ // the main workflow store depends on the main user store (dist=1)
+ String prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + userStore;
+ this.avmService.setStoreProperty(workflowStoreName, QName.createQName(null, prop_key),
+ new PropertyValue(DataTypeDefinition.INT, 1));
+
+ // The main workflow store depends on the main staging store (dist=2)
+ prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + stagingStore;
+ this.avmService.setStoreProperty(workflowStoreName, QName.createQName(null, prop_key),
+ new PropertyValue(DataTypeDefinition.INT, 2));
+
+ // snapshot the store
+ this.avmService.createSnapshot(workflowStoreName, null, null);
+
+ // create the workflow 'preview' store
+ String previewStoreName = workflowStoreName + STORE_SEPARATOR + "preview";
+ this.avmService.createStore(previewStoreName);
+
+ if (logger.isDebugEnabled())
+ logger.debug("Created user workflow sandbox preview store: " + previewStoreName);
+
+ // create a layered directory pointing to 'www' in the workflow 'main' store
+ this.avmService.createLayeredDirectory(
+ workflowStoreName + ":/" + JNDIConstants.DIR_DEFAULT_WWW,
+ previewStoreName + ":/", JNDIConstants.DIR_DEFAULT_WWW);
+
+ // tag the store with the store type
+ this.avmService.setStoreProperty(previewStoreName, SandboxConstants.PROP_SANDBOX_WORKFLOW_PREVIEW,
+ new PropertyValue(DataTypeDefinition.TEXT, null));
+
+ // tag the store with its own store name for querying.
+ avmService.setStoreProperty(previewStoreName,
+ QName.createQName(null, SandboxConstants.PROP_SANDBOX_STORE_PREFIX + previewStoreName),
+ new PropertyValue(DataTypeDefinition.TEXT, null));
+
+ // tag the store with the DNS name property
+ path = previewStoreName + ":/" + JNDIConstants.DIR_DEFAULT_WWW +
+ "/" + JNDIConstants.DIR_DEFAULT_APPBASE;
+ // DNS name mangle the property name - can only contain value DNS characters!
+ dnsProp = SandboxConstants.PROP_DNS + DNSNameMangler.MakeDNSName(userStore, packageName, "preview");
+ this.avmService.setStoreProperty(previewStoreName, QName.createQName(null, dnsProp),
+ new PropertyValue(DataTypeDefinition.TEXT, path));
+
+ // The preview worfkflow store depends on the main workflow store (dist=1)
+ prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + workflowStoreName;
+ this.avmService.setStoreProperty(previewStoreName, QName.createQName(null, prop_key),
+ new PropertyValue(DataTypeDefinition.INT, 1));
+
+ // The preview workflow store depends on the main user store (dist=2)
+ prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + userStore;
+ this.avmService.setStoreProperty(previewStoreName, QName.createQName(null, prop_key),
+ new PropertyValue(DataTypeDefinition.INT, 2));
+
+ // The preview workflow store depends on the main staging store (dist=3)
+ prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + stagingStore;
+ this.avmService.setStoreProperty(previewStoreName, QName.createQName(null, prop_key),
+ new PropertyValue(DataTypeDefinition.INT, 3));
+
+ // snapshot the store
+ this.avmService.createSnapshot(previewStoreName, null, null);
+
+ // tag all related stores to indicate that they are part of a single sandbox
+ QName sandboxIdProp = QName.createQName(SandboxConstants.PROP_SANDBOXID + GUID.generate());
+ this.avmService.setStoreProperty(workflowStoreName, sandboxIdProp,
+ new PropertyValue(DataTypeDefinition.TEXT, null));
+ this.avmService.setStoreProperty(previewStoreName, sandboxIdProp,
+ new PropertyValue(DataTypeDefinition.TEXT, null));
+
+ // return the main workflow store name
+ return workflowStoreName;
+ }
+
+ public List listSandboxes(final String wpStoreId, String userName)
+ {
+ ParameterCheck.mandatoryString("wpStoreId", wpStoreId);
+ ParameterCheck.mandatoryString("userName", userName);
+
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork>()
+ {
+ public List doWork() throws Exception
+ {
+ List stores = avmService.getStores();
+
+ List sbInfos = new ArrayList();
+ for (AVMStoreDescriptor store : stores)
+ {
+ String storeName = store.getName();
+
+ // list main stores - not preview stores or workflow stores
+ if ((storeName.startsWith(wpStoreId)) &&
+ (! WCMUtil.isPreviewStore(storeName)) &&
+ (! WCMUtil.isWorkflowStore(storeName)))
+ {
+ sbInfos.add(getSandbox(storeName));
+ }
+ }
+
+ return sbInfos;
+ }
+ }, userName);
+ }
+
+ public void deleteSandbox(String sbStoreId)
+ {
+ SandboxInfo sbInfo = getSandbox(sbStoreId);
+
+ if (sbInfo != null)
+ {
+ String mainSandboxStore = sbInfo.getMainStoreName();
+
+ // found the sandbox to remove - remove the main store (eg. user main store, staging main store, workflow main store)
+ String path = WCMUtil.buildSandboxRootPath(mainSandboxStore);
+
+ // Notify virtualisation server about removing this sandbox.
+ //
+ // Implementation note:
+ //
+ // Because the removal of virtual webapps in the
+ // virtualization server is recursive, it only
+ // needs to be given the name of the main store.
+ //
+ // This notification must occur *prior* to purging content
+ // within the AVM because the virtualization server must list
+ // the avm_webapps dir in each store to discover which
+ // virtual webapps must be unloaded. The virtualization
+ // server traverses the sandbox's stores in most-to-least
+ // dependent order, so clients don't have to worry about
+ // accessing a preview layer whose main layer has been torn
+ // out from under it.
+
+ WCMUtil.removeAllVServerWebapps(virtServerRegistry, path, true);
+
+ // TODO: Use the .sandbox-id. property to delete all sandboxes,
+ // rather than assume a sandbox always had a single preview
+ // layer attached.
+
+ // purge stores, eg. main store followed by preview store
+ String[] avmStoreNames = sbInfo.getStoreNames();
+
+ for (String avmStoreName : avmStoreNames)
+ {
+ // check it exists before we try to remove it
+ if (avmService.getStore(avmStoreName) != null)
+ {
+ // purge store from the system
+ avmService.purgeStore(avmStoreName);
+ }
+
+ // remove any locks this user may have
+ avmLockingService.removeStoreLocks(avmStoreName);
+ }
+ }
+ }
+
+ public void updateSandboxManagers(final String wpStoreId, NodeRef wpNodeRef, List managers)
+ {
+ // walk existing user sandboxes and reapply manager permissions to include new manager user
+ List sbInfos = AuthenticationUtil.runAs(new RunAsWork>()
+ {
+ public List doWork() throws Exception
+ {
+ return listSandboxes(wpStoreId, AuthenticationUtil.getSystemUserName());
+ }
+ }, AuthenticationUtil.getSystemUserName());
+
+ for (SandboxInfo sbInfo : sbInfos)
+ {
+ if (sbInfo.getSandboxType().equals(SandboxConstants.PROP_SANDBOX_AUTHOR_MAIN))
+ {
+ String username = sbInfo.getName();
+ updateUserSandboxManagers(wpStoreId, managers, username);
+ }
+ }
+
+ updateStagingAreaManagers(wpStoreId, wpNodeRef, managers);
}
/**
@@ -545,7 +865,7 @@ public final class SandboxFactory extends WCMUtil
* @param managers The list of authorities who have ContentManager role in the web project
* @param username Username of the user sandbox to update
*/
- public void updateSandboxManagers(final String storeId, final List managers, final String username)
+ private void updateUserSandboxManagers(final String storeId, final List managers, final String username)
{
final String userStoreName = WCMUtil.buildUserMainStoreName(storeId, username);
final String previewStoreName = WCMUtil.buildUserPreviewStoreName(storeId, username);
diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxInfo.java b/source/java/org/alfresco/wcm/sandbox/SandboxInfo.java
index 80202b7b7c..d7c6c6bc79 100644
--- a/source/java/org/alfresco/wcm/sandbox/SandboxInfo.java
+++ b/source/java/org/alfresco/wcm/sandbox/SandboxInfo.java
@@ -24,23 +24,43 @@
*/
package org.alfresco.wcm.sandbox;
-import java.io.Serializable;
+import java.util.Date;
+
+import org.alfresco.service.namespace.QName;
/**
* Provides information about a WCM sandbox created by SandboxFactory.
*/
-public final class SandboxInfo implements Serializable
+public interface SandboxInfo
{
- private static final long serialVersionUID = 3615436375385857404L;
-
- String [] store_names_;
- public SandboxInfo(String [] store_names)
- {
- store_names_ = store_names;
- }
-
/**
- * A list of names of the stores within this sandbox.
+ * Get the name
+ *
+ * @return String name
+ */
+ public String getName();
+
+ /**
+ * The sandbox store id
+ */
+ public String getSandboxId();
+
+ /**
+ * The web project store id
+ */
+ public String getWebProjectId();
+
+ /**
+ * The sandbox type ... for now a QName, based on existing SandboxConstants
+ */
+ public QName getSandboxType();
+
+ public Date getCreatedDate();
+
+ public String getCreator();
+
+ /**
+ * A list of ids of the stores within this sandbox.
* The "main" store should come first in this list;
* any other stores should appear in the order that
* they are overlaid on "main" (e.g.: any "preview"
@@ -48,10 +68,10 @@ public final class SandboxInfo implements Serializable
*
* Note: all sandboxes must have a "main" layer.
*/
- public String [] getStoreNames() { return store_names_; }
+ public String[] getStoreNames();
/**
- * The name of the "main" store within this sandbox.
+ * The id of the "main" store within this sandbox.
*/
- public String getMainStoreName() { return store_names_[0]; }
+ public String getMainStoreName();
}
diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxInfoImpl.java b/source/java/org/alfresco/wcm/sandbox/SandboxInfoImpl.java
new file mode 100644
index 0000000000..4640f6e50a
--- /dev/null
+++ b/source/java/org/alfresco/wcm/sandbox/SandboxInfoImpl.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2005-2008 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.wcm.sandbox;
+
+import java.util.Date;
+
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Provides information about a WCM sandbox created by Sandbox Service/Factory
+ */
+public class SandboxInfoImpl implements SandboxInfo
+{
+ private String wpStoreId;
+ private String sbStoreId;
+ private QName sandboxType;
+ private String name;
+ private String[] storeNames;
+ private Date createdDate;
+ private String creator;
+
+ /* package */ SandboxInfoImpl(String wpStoreId, String sbStoreId, QName sandboxType, String name, String[] storeNames, Date createdDate, String creator)
+ {
+ this.wpStoreId = wpStoreId;
+ this.sbStoreId = sbStoreId;
+ this.sandboxType = sandboxType;
+ this.name = name;
+ this.storeNames = storeNames;
+ this.createdDate = createdDate;
+ this.creator = creator;
+ }
+
+ // note: currently derived - for author sandbox this is the username, for staging sandbox this is the sandbox id
+ public String getName()
+ {
+ return this.name;
+ }
+
+ public String getWebProjectId()
+ {
+ return this.wpStoreId;
+ }
+
+ public String getSandboxId()
+ {
+ return this.sbStoreId;
+ }
+
+ public QName getSandboxType()
+ {
+ return this.sandboxType;
+ }
+
+ public Date getCreatedDate()
+ {
+ return this.createdDate;
+ }
+
+ public String getCreator()
+ {
+ return this.creator;
+ }
+
+ /**
+ * A list of names of the stores within this sandbox.
+ * The "main" store should come first in this list;
+ * any other stores should appear in the order that
+ * they are overlaid on "main" (e.g.: any "preview"
+ * layers should come afterward, in "lowest first" order).
+ *
+ * Note: all sandboxes must have a "main" layer.
+ */
+ public String [] getStoreNames() { return storeNames; }
+
+ /**
+ * The name of the "main" store within this sandbox.
+ */
+ public String getMainStoreName()
+ {
+ return storeNames[0];
+ }
+}
diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxService.java b/source/java/org/alfresco/wcm/sandbox/SandboxService.java
new file mode 100644
index 0000000000..17142d94fc
--- /dev/null
+++ b/source/java/org/alfresco/wcm/sandbox/SandboxService.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2005-2008 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.wcm.sandbox;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
+import org.alfresco.service.cmr.avm.VersionDescriptor;
+import org.alfresco.service.namespace.QName;
+
+
+/**
+ * Sandbox Service fundamental API.
+ *
+ * This service API is designed to support the public facing Sandbox APIs.
+ *
+ * @author janv
+ */
+public interface SandboxService
+{
+ /**
+ * Create author/user sandbox within a web project for the current user
+ *
+ * If the author sandbox already exists for this web project then it will be returned
+ *
+ * @param wpStoreId web project store id
+ * @return SandboxInfo the created user sandbox info
+ */
+ public SandboxInfo createAuthorSandbox(String wpStoreId);
+
+ /**
+ * Create author/user sandbox within a web project for the given user
+ *
+ * If the author sandbox already exists for this web project then it will be returned
+ *
+ * Current user must be a content manager for the web project
+ *
+ * @param wpStoreId web project store id
+ * @param userName user name
+ * @return SandboxInfo the created user sandbox info
+ */
+ public SandboxInfo createAuthorSandbox(String wpStoreId, String userName);
+
+ /**
+ * List the available sandboxes for the current user and given web project
+ *
+ * @param wpStoreId web project store id
+ * @return List list of sandbox info
+ */
+ public List listSandboxes(String wpStoreId);
+
+ /**
+ * List the available sandboxes for the given user and web project
+ *
+ * Current user must be a content manager for the web project
+ *
+ * @param wpStoreId web project store id
+ * @param userName user name
+ * @return List list of sandbox info
+ */
+ public List listSandboxes(String wpStoreId, String userName);
+
+ /**
+ * Return true if sandbox is visible to user and is of given type
+ *
+ * eg. isSandboxType("test123--myusername", SandboxConstants.PROP_SANDBOX_AUTHOR_MAIN)
+ *
+ * @param sbStoreId sandbox store id
+ * @param sandboxType sandbox type (see SandboxConstants)
+ * @return boolean true, if sandbox exists with given type
+ */
+ public boolean isSandboxType(String sbStoreId, QName sandboxType);
+
+ /**
+ * Get sandbox info
+ *
+ * @param sbStoreId sandbox store id
+ * @return SandboxInfo null if sandbox does not exist or is not visible to the current user
+ */
+ public SandboxInfo getSandbox(String sbStoreId);
+
+ /**
+ * Gets author/user sandbox info for the current user
+ *
+ * Returns null if the author sandbox can not be found
+ *
+ * @param wpStoreId web project store id
+ * @return SandboxInfo author sandbox info
+ */
+ public SandboxInfo getAuthorSandbox(String wpStoreId);
+
+ /**
+ * Gets author/user sandbox info for the given user
+ *
+ * Returns null if the user sandbox can not be found
+ *
+ * Current user must be a content manager for the web project
+ *
+ * @param wpStoreId web project store id
+ * @param userName userName
+ * @return SandboxInfo author sandbox info
+ */
+ public SandboxInfo getAuthorSandbox(String wpStoreId, String userName);
+
+ /**
+ * Gets staging sandbox info
+ *
+ * Returns null if the staging sandbox can not be found
+ *
+ * @param wpStoreId web project store id
+ * @return SandboxInfo staging sandbox info
+ */
+ public SandboxInfo getStagingSandbox(String wpStoreId);
+
+ /**
+ * Delete the sandbox
+ *
+ * If the sandbox does not exist, will log a warning and succeed
+ *
+ * Current user must be a content manager for the web project (associated with the sandbox)
+ *
+ * @param sbStoreId sandbox store id
+ */
+ public void deleteSandbox(String sbStoreId);
+
+ /**
+ * List changed items for given sandbox (eg. for user sandbox compared to staging sandbox)
+ *
+ * Note: This will list new/modified/deleted items from the root directory and below, including all web apps
+ *
+ * @param sbStoreId sandbox store id
+ * @param includeDeleted if true, include deleted items as well as new/modified items
+ * @return List list of changed items
+ */
+ public List listChangedItems(String sbStoreId, boolean includeDeleted);
+
+ /**
+ * List changed items for given sandbox and web app (eg. in user sandbox)
+ *
+ * Note: This will list new/modified/deleted items for the given web app
+ *
+ * @param sbStoreId sandbox store id
+ * @param webApp web app to filter by
+ * @param includeDeleted if true, include deleted items as well as new/modified items
+ * @return List list of changed items
+ */
+ public List listChangedItemsWebApp(String sbStoreId, String webApp, boolean includeDeleted);
+
+ /**
+ * List changed items for given sandbox path (eg. between user sandbox and staging sandbox)
+ *
+ * Note: This will list new/modified/deleted items from the directory and below. The destination path will be dervied.
+ *
+ * @param avmSrcPath source sandbox path (an AVM path)
+ * @param includeDeleted if true, include deleted items as well as new/modified items
+ * @return List list of changed items
+ */
+ public List listChangedItemsDir(String avmSrcPath, boolean includeDeleted);
+
+ /**
+ * List changed (new/modified/deleted) items between any two sandbox paths
+ *
+ * @param avmSrcPath source sandbox path (an AVM path)
+ * @param avmDstPath destination sandbox path (an AVM path)
+ * @param includeDeleted if true, include deleted items as well as new/modified items
+ * @return List list of changed items
+ */
+ public List listChangedItems(String avmSrcPath, String avmDstPath, boolean includeDeleted);
+
+ /**
+ * Submit all changed items for given sandbox (eg. from user sandbox to staging sandbox)
+ *
+ * Note: This will submit new/modified/deleted items from the root directory and below, including all web apps
+ *
+ * @param sbStoreId sandbox store id
+ */
+ public void submitAll(String sbStoreId, String submitLabel, String submitComment);
+
+ /**
+ * Submit all changed items for given sandbox and web app (eg. in user sandbox)
+ *
+ * Note: This will submit new/modified/deleted items for the given web app
+ *
+ * @param sbStoreId sandbox store id
+ * @param webApp web app to filter by
+ */
+ public void submitAllWebApp(String sbStoreId, String webApp, String submitLabel, String submitComment);
+
+ /**
+ * Submit all changed items for given sandbox path (eg. in user sandbox)
+ *
+ * Note: This will submit new/modified/deleted items from the directory and below
+ *
+ * @param avmDirectoryPath path to filter by
+ */
+ public void submitAllDir(String avmDirectoryPath, String submitLabel, String submitComment);
+
+ /**
+ * Submit list of changed items for given sandbox (eg. from user sandbox to staging sandbox)
+ *
+ * @param sbStoreId sandbox store id
+ * @param items list of AVM node descriptors
+ */
+ public void submitList(String sbStoreId, List items, String submitLabel, String submitComment);
+
+ /**
+ * Submit list of changed items for given sandbox (eg. from user sandbox to staging sandbox)
+ *
+ * @param sbStoreId sandbox store id
+ * @param items list of AVM node descriptors
+ * @param expirationDates map of for those items set with an expiration date, or can be null (if no expiration dates)
+ */
+ public void submitList(String sbStoreId, List items, Map expirationDates, final String submitLabel, final String submitComment);
+
+ /**
+ * Revert all changed items for given sandbox (eg. in user sandbox)
+ *
+ * Note: This will revert new/modified/deleted items from the root directory and below, including all web apps
+ *
+ * @param sbStoreId sandbox store id
+ */
+ public void revertAll(String sbStoreId);
+
+ /**
+ * Revert all changed items for given sandbox and web app (eg. in user sandbox)
+ *
+ * Note: This will revert new/modified/deleted items for the given web app
+ *
+ * @param sbStoreId sandbox store id
+ * @param webApp web app to filter by
+ */
+ public void revertAllWebApp(String sbStoreId, String webApp);
+
+ /**
+ * Revert all changed items for given sandbox path (eg. in user sandbox)
+ *
+ * Note: This will revert new/modified/deleted items from the directory and below
+ *
+ * @param avmDirectoryPath path to filter by
+ */
+ public void revertAllDir(String avmDirectoryPath);
+
+ /**
+ * Revert list of changed items for given sandbox (eg. in user sandbox)
+ *
+ * @param items list of AVM node descriptors
+ */
+ public void revertList(String sbStoreId, List items);
+
+ /**
+ * Revert sandbox to a specific snapshot version ID (ie. for staging sandbox)
+ *
+ * Current user must be a content manager for the web project
+ *
+ * @param sbStoreId staging sandbox store id
+ * @param version version
+ */
+ public void revertSnapshot(String sbStoreId, int version);
+
+ /**
+ * List all snapshots (sandbox versions) for the given sandbox (ie. for staging sandbox)
+ *
+ * Current user must be a content manager for the web project
+ *
+ * @param sbStoreId staging sandbox store id
+ * @param includeSystemGenerated if false will ignore system generated snapshots else true to get all snapshots
+ * @return List list of AVM version descriptors
+ */
+ public List listSnapshots(String sbStoreId, boolean includeSystemGenerated);
+
+ /**
+ * List snapshots (sandbox versions) for the given sandbox between given dates (ie. for staging sandbox)
+ *
+ * Current user must be a content manager for the web project
+ *
+ * @param sbStoreId staging sandbox store id
+ * @param from from date
+ * @param to to date
+ * @param includeSystemGenerated if false will ignore system generated snapshots else true to get all snapshots
+ * @return List list of AVM version descriptors
+ */
+ public List listSnapshots(String sbStoreId, Date from, Date to, boolean includeSystemGenerated);
+
+}
diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java b/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java
new file mode 100644
index 0000000000..2a5f5b4660
--- /dev/null
+++ b/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java
@@ -0,0 +1,858 @@
+/*
+ * Copyright (C) 2005-2008 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.wcm.sandbox;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.mbeans.VirtServerRegistry;
+import org.alfresco.model.WCMAppModel;
+import org.alfresco.repo.avm.AVMDAOs;
+import org.alfresco.repo.avm.AVMNodeConverter;
+import org.alfresco.repo.avm.actions.AVMRevertStoreAction;
+import org.alfresco.repo.avm.actions.AVMUndoSandboxListAction;
+import org.alfresco.repo.domain.PropertyValue;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.permissions.AccessDeniedException;
+import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
+import org.alfresco.repo.transaction.TransactionListenerAdapter;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.action.ActionService;
+import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
+import org.alfresco.service.cmr.avm.AVMService;
+import org.alfresco.service.cmr.avm.VersionDescriptor;
+import org.alfresco.service.cmr.avm.locking.AVMLockingService;
+import org.alfresco.service.cmr.avmsync.AVMDifference;
+import org.alfresco.service.cmr.avmsync.AVMSyncService;
+import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.workflow.WorkflowService;
+import org.alfresco.service.cmr.workflow.WorkflowTask;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.NameMatcher;
+import org.alfresco.util.Pair;
+import org.alfresco.util.ParameterCheck;
+import org.alfresco.util.VirtServerUtils;
+import org.alfresco.wcm.util.WCMUtil;
+import org.alfresco.wcm.util.WCMWorkflowUtil;
+import org.alfresco.wcm.webproject.WebProjectInfo;
+import org.alfresco.wcm.webproject.WebProjectService;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * Sandbox Service fundamental API.
+ *
+ * This service API is designed to support the public facing Sandbox APIs.
+ *
+ * @author janv
+ */
+public class SandboxServiceImpl extends WCMUtil implements SandboxService
+{
+ /** Logger */
+ private static Log logger = LogFactory.getLog(SandboxServiceImpl.class);
+
+ private WebProjectService wpService;
+ private SandboxFactory sandboxFactory;
+ private AVMService avmService;
+ private AVMLockingService avmLockingService;
+ private AVMSyncService avmSyncService;
+ private NameMatcher nameMatcher;
+ private VirtServerRegistry virtServerRegistry;
+ private ActionService actionService;
+ private WorkflowService workflowService;
+
+ public void setWebProjectService(WebProjectService wpService)
+ {
+ this.wpService = wpService;
+ }
+
+ public void setSandboxFactory(SandboxFactory sandboxFactory)
+ {
+ this.sandboxFactory = sandboxFactory;
+ }
+
+ public void setAvmService(AVMService avmService)
+ {
+ this.avmService = avmService;
+ }
+
+ public void setAvmLockingService(AVMLockingService avmLockingService)
+ {
+ this.avmLockingService = avmLockingService;
+ }
+
+ public void setAvmSyncService(AVMSyncService avmSyncService)
+ {
+ this.avmSyncService = avmSyncService;
+ }
+
+ public void setNameMatcher(NameMatcher nameMatcher)
+ {
+ this.nameMatcher = nameMatcher;
+ }
+
+ public void setVirtServerRegistry(VirtServerRegistry virtServerRegistry)
+ {
+ this.virtServerRegistry = virtServerRegistry;
+ }
+
+ public void setActionService(ActionService actionService)
+ {
+ this.actionService = actionService;
+ }
+
+ public void setWorkflowService(WorkflowService workflowService)
+ {
+ this.workflowService = workflowService;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.alfresco.wcm.sandbox.SandboxService#createAuthorSandbox(java.lang.String)
+ */
+ public SandboxInfo createAuthorSandbox(String wpStoreId)
+ {
+ ParameterCheck.mandatoryString("wpStoreId", wpStoreId);
+
+ String currentUserName = AuthenticationUtil.getCurrentEffectiveUserName();
+ SandboxInfo sbInfo = null;
+
+ if (! wpService.isWebUser(wpStoreId, currentUserName))
+ {
+ throw new AccessDeniedException("Only web project users may create their own (author) sandbox for '"+currentUserName+"' (store id: "+wpStoreId+")");
+ }
+ else
+ {
+ sbInfo = createAuthorSandboxImpl(wpStoreId, currentUserName);
+ }
+
+ return sbInfo;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.wcm.sandbox.SandboxService#createAuthorSandbox(java.lang.String, java.lang.String)
+ */
+ public SandboxInfo createAuthorSandbox(String wpStoreId, String userName)
+ {
+ ParameterCheck.mandatoryString("wpStoreId", wpStoreId);
+ ParameterCheck.mandatoryString("userName", userName);
+
+ // is the current user a content manager for this web project ?
+ if (! wpService.isContentManager(wpStoreId))
+ {
+ throw new AccessDeniedException("Only content managers may create author sandbox for '"+userName+"' (store id: "+wpStoreId+")");
+ }
+
+ return createAuthorSandboxImpl(wpStoreId, userName);
+ }
+
+ private SandboxInfo createAuthorSandboxImpl(String wpStoreId, String userName)
+ {
+ WebProjectInfo wpInfo = wpService.getWebProject(wpStoreId);
+
+ final NodeRef wpNodeRef = wpInfo.getNodeRef();
+ final List managers = new ArrayList(4);
+
+ AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork