diff --git a/config/alfresco/extension/mt/mt-admin-context.xml.sample b/config/alfresco/extension/mt/mt-admin-context.xml.sample
index 5163eeeac8..41e5e34a90 100644
--- a/config/alfresco/extension/mt/mt-admin-context.xml.sample
+++ b/config/alfresco/extension/mt/mt-admin-context.xml.sample
@@ -21,7 +21,13 @@
-
+
+
+
+
+
+
+
diff --git a/config/alfresco/messages/tenant-interpreter-help.txt b/config/alfresco/messages/tenant-interpreter-help.txt
index ba6946d92f..7160bc8a91 100755
--- a/config/alfresco/messages/tenant-interpreter-help.txt
+++ b/config/alfresco/messages/tenant-interpreter-help.txt
@@ -32,7 +32,7 @@ ok> show tenant
ok> create []
- Create tenant. By default the tenant will be enabled. It will have an admin
+ Create empty tenant. By default the tenant will be enabled. It will have an admin
user called "admin@" with supplied admin password. All users
that the admin creates, will login using "@".
The root of the contentstore directory can be optionally specified, otherwise
@@ -42,17 +42,7 @@ ok> create []
Examples: create zzz.com l3tm31n /usr/tenantstores/zzz
create yyy.zzz.com g00dby3 /usr/tenantstores/yyy.zzz
create myorg h3ll0
-
-ok> createWithoutWorkflows []
- Same as create, except the default workflows will not be bootstrapped.
-
-ok> bootstrapWorkflows
-
- Bootstrap the default workflows.
-
- Examples: bootstrapWorkflows yyy.zzz.com
-
ok> changeAdminPassword
Useful if the tenant's admin (admin@) has forgotten their password.
@@ -70,6 +60,31 @@ ok> disable
Disable tenant so that is inactive. Existing logins will fail on next usage.
Example: enable yyy.zzz.com
+
+ok> delete
+
+ BETA - Delete tenant.
+
+ Note: This currently requires a server restart to clear the index threads. Also
+ tenant index directories should be deleted manually.
+
+ Example: delete yyy.zzz.com
+
+ok> export
+
+ Export tenant to given destination directory. Export filenames will be suffixed with '_'.
+
+ Example: export yyy.zzz.com /usr/exportdir
+
+ok> import []
+
+ BETA - create tenant by importing the tenant files from the given source directory. The import filenames must
+ be suffixed with '_'.
+
+ Note: If importing into a previously deleted tenant then the server must be stopped after the delete
+ (and tenant indexes manually deleted) before restarting and performing the import.
+
+ Example: import yyy.zzz.com /usr/exportdir /usr/tenantstores/yyy.zzz
##
## end
diff --git a/config/alfresco/workflow-context.xml b/config/alfresco/workflow-context.xml
index 6a7e9d07e3..2a195a15da 100644
--- a/config/alfresco/workflow-context.xml
+++ b/config/alfresco/workflow-context.xml
@@ -109,6 +109,15 @@
+
+
+
+
+
+ /app:company_home/app:dictionary/app:workflow_defs
+
+
+
diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java b/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java
index 9a0ddba465..4003b8aee6 100644
--- a/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java
+++ b/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java
@@ -473,7 +473,13 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda
if ((existingValue != null) && (existingValue.booleanValue() == true))
{
String name = (String)nodeService.getProperty(existingNodeRef, ContentModel.PROP_NAME);
- throw new AlfrescoRuntimeException("Cannot activate '"+modelDefinition.getName()+"' - existing active model: " + name);
+
+ // for MT import, model may have been activated by DictionaryRepositoryBootstrap
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Re-activating '"+modelDefinition.getName()+"' - existing active model: " + name);
+ }
+ //throw new AlfrescoRuntimeException("Cannot activate '"+modelDefinition.getName()+"' - existing active model: " + name);
}
}
}
diff --git a/source/java/org/alfresco/repo/importer/ImporterBootstrap.java b/source/java/org/alfresco/repo/importer/ImporterBootstrap.java
index a483a855e5..2d0d074185 100644
--- a/source/java/org/alfresco/repo/importer/ImporterBootstrap.java
+++ b/source/java/org/alfresco/repo/importer/ImporterBootstrap.java
@@ -498,29 +498,40 @@ public class ImporterBootstrap extends AbstractLifecycleBean
*/
private File getFile(String view)
{
- // Get input stream
- InputStream viewStream = getClass().getClassLoader().getResourceAsStream(view);
- if (viewStream == null)
+ // Try as a file location
+ File file = new File(view);
+ if ((file != null) && (file.exists()))
{
- throw new ImporterException("Could not find view file " + view);
+ return file;
}
-
- // Create output stream
- File tempFile = TempFileProvider.createTempFile("acpImport", ".tmp");
- try
+ else
{
- FileOutputStream os = new FileOutputStream(tempFile);
- FileCopyUtils.copy(viewStream, os);
+ // Try as a classpath location
+
+ // Get input stream
+ InputStream viewStream = getClass().getClassLoader().getResourceAsStream(view);
+ if (viewStream == null)
+ {
+ throw new ImporterException("Could not find view file " + view);
+ }
+
+ // Create output stream
+ File tempFile = TempFileProvider.createTempFile("acpImport", ".tmp");
+ try
+ {
+ FileOutputStream os = new FileOutputStream(tempFile);
+ FileCopyUtils.copy(viewStream, os);
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new ImporterException("Could not import view " + view, e);
+ }
+ catch (IOException e)
+ {
+ throw new ImporterException("Could not import view " + view, e);
+ }
+ return tempFile;
}
- catch (FileNotFoundException e)
- {
- throw new ImporterException("Could not import view " + view, e);
- }
- catch (IOException e)
- {
- throw new ImporterException("Could not import view " + view, e);
- }
- return tempFile;
}
diff --git a/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java b/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java
index 552cd0d5e0..506dd9dcda 100755
--- a/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java
+++ b/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java
@@ -24,6 +24,7 @@
*/
package org.alfresco.repo.tenant;
+import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -45,17 +46,23 @@ import org.alfresco.repo.attributes.MapAttributeValue;
import org.alfresco.repo.attributes.StringAttributeValue;
import org.alfresco.repo.content.TenantRoutingFileContentStore;
import org.alfresco.repo.dictionary.DictionaryComponent;
+import org.alfresco.repo.dictionary.RepositoryLocation;
import org.alfresco.repo.importer.ImporterBootstrap;
import org.alfresco.repo.node.db.DbNodeServiceImpl;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.repo.workflow.WorkflowDefinitionType;
import org.alfresco.repo.workflow.WorkflowDeployer;
import org.alfresco.service.cmr.admin.RepoAdminService;
import org.alfresco.service.cmr.attributes.AttributeService;
+import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.cmr.view.RepositoryExporterService;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowService;
+import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.util.ParameterCheck;
@@ -85,6 +92,11 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten
private PasswordEncoder passwordEncoder;
private TenantRoutingFileContentStore tenantFileContentStore;
private WorkflowService workflowService;
+ private RepositoryExporterService repositoryExporterService;
+ private NamespaceService namespaceService;
+ private SearchService searchService;
+ private RepositoryLocation repoWorkflowDefsLocation;
+ private WorkflowDefinitionType workflowDefinitionType;
protected final static String REGEX_VALID_TENANT_NAME = "^[a-zA-Z0-9]([a-zA-Z0-9]|.[a-zA-Z0-9])*$"; // note: must also be a valid filename
@@ -139,6 +151,32 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten
this.workflowService = workflowService;
}
+ public void setRepositoryExporterService(RepositoryExporterService repositoryExporterService)
+ {
+ this.repositoryExporterService = repositoryExporterService;
+ }
+
+ public void setNamespaceService(NamespaceService namespaceService)
+ {
+ this.namespaceService = namespaceService;
+ }
+
+ public void setSearchService(SearchService searchService)
+ {
+ this.searchService = searchService;
+ }
+
+ public void setRepositoryWorkflowDefsLocations(RepositoryLocation repoWorkflowDefsLocation)
+ {
+ this.repoWorkflowDefsLocation = repoWorkflowDefsLocation;
+ }
+
+ public void setWorkflowDefinitionType(WorkflowDefinitionType workflowDefinitionType)
+ {
+ this.workflowDefinitionType = workflowDefinitionType;
+ }
+
+
public static final String PROTOCOL_STORE_USER = "user";
public static final String PROTOCOL_STORE_WORKSPACE = "workspace";
public static final String PROTOCOL_STORE_SYSTEM = "system";
@@ -154,6 +192,9 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten
private static final String TENANT_ROOT_CONTENT_STORE_DIR = "rootContentStoreDir";
private static final String ADMIN_BASENAME = TenantService.ADMIN_BASENAME;
+
+ public final static String CRITERIA_ALL = "/*"; // immediate children only
+ public final static String defaultSubtypeOfWorkflowDefinitionType = "subtypeOf('bpm:workflowDefinition')";
private List tenantDeployers = new ArrayList();
@@ -275,11 +316,20 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten
tenantFileContentStore.init();
// create tenant-specific stores
- bootstrapUserTenantStore(tenantDomain, tenantAdminRawPassword);
- bootstrapSystemTenantStore(tenantDomain);
- bootstrapVersionTenantStore(tenantDomain);
- bootstrapSpacesArchiveTenantStore(tenantDomain);
- bootstrapSpacesTenantStore(tenantDomain);
+ ImporterBootstrap userImporterBootstrap = (ImporterBootstrap)getApplicationContext().getBean("userBootstrap");
+ bootstrapUserTenantStore(userImporterBootstrap, tenantDomain, tenantAdminRawPassword);
+
+ ImporterBootstrap systemImporterBootstrap = (ImporterBootstrap)getApplicationContext().getBean("systemBootstrap");
+ bootstrapSystemTenantStore(systemImporterBootstrap, tenantDomain);
+
+ ImporterBootstrap versionImporterBootstrap = (ImporterBootstrap)getApplicationContext().getBean("versionBootstrap");
+ bootstrapVersionTenantStore(versionImporterBootstrap, tenantDomain);
+
+ ImporterBootstrap spacesArchiveImporterBootstrap = (ImporterBootstrap)getApplicationContext().getBean("spacesArchiveBootstrap");
+ bootstrapSpacesArchiveTenantStore(spacesArchiveImporterBootstrap, tenantDomain);
+
+ ImporterBootstrap spacesImporterBootstrap = (ImporterBootstrap)getApplicationContext().getBean("spacesBootstrap");
+ bootstrapSpacesTenantStore(spacesImporterBootstrap, tenantDomain);
// notify listeners that tenant has been created & hence enabled
for (TenantDeployer tenantDeployer : tenantDeployers)
@@ -295,6 +345,82 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten
logger.info("Tenant created: " + tenantDomain);
}
+ /**
+ * Export tenant - equivalent to the tenant admin running a 'complete repo' export from the Web Client Admin
+ */
+ public void exportTenant(final String tenantDomain, final File directoryDestination)
+ {
+ AuthenticationUtil.runAs(new RunAsWork