Merged V3.1 to HEAD

- incl. taking Hibernate libs from 3.1 and adding missing file from earlier merge
   13321: Fix ETHREEOH-1407: System error occur during "Undo Selected" action if no items are selected
   13322: ETHREEOH-1206: Throwing Alfresco Exception on OnUpdateProperties behaviour resets Encoding field to Big (first entry)
   13326: (RECORD ONLY) Removed 'dev' from version label.
   13330: Fix ETHREEOH-1408: Incorrect button name at "Manage Task: Submitted" page
   13337: Fix for ETHREEOH-1409 and further fix for ETHREEOH-1408
   13338: Removed svn:mergeinfo
   13346: Make startup bat script check JAVA can be found.
   13351: ETHREEOH-1386 validate ASR and FSR hostname.
   13359: ETHREEOH-1435: Share doesn't extract document metadata correctly
   13360: Fix ETHREEOH-821: SDK dependencies
   13369: Fixed distribute-sdk target for when it's run locally
   13382: ETHREEOH-1437: Container creation induces an unexpected permission allocation in Share
   13391: Shutdown backstop continues if logging throws errors.
   13394: Fix ETHREEOH-1457 - MT coci issue with bootstrap (eg. data dictionary) content
   13400: Activate JAWS-223: Adobe LC Hibernate Dialect Loading
   13401: Support for JAWS-215, mysql and oracle
   13413: Fix ETHREEOH-1458 - MT delete->archive
   ___________________________________________________________________
   Modified: svn:mergeinfo
      Merged /alfresco/BRANCHES/V3.1:r
                           13321-13322,13326-13327,13330,13337-13339,13341-13347,13351,13354-13355,13358-13363,
                           13365,13367,13369,13382,13385-13392,13394,13400-13403,13405-13406,13413


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13617 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-03-13 00:51:43 +00:00
parent 9d65d8feec
commit fec1149d8c
18 changed files with 297 additions and 117 deletions

View File

@@ -5,13 +5,7 @@
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig> <sqlMapConfig>
<!-- note: dialect property is provided by SqlMapClientFactoryBean -->
<!-- NOTE: although we use iBatis here rather than Hibernate, for consistency we make use of single SQL dialect property (hibernate.dialect) for consistency -->
<properties resource="alfresco/domain/hibernate-cfg.properties" />
<!-- SQL Map XML files loaded from the classpath -->
<!-- note: dialect property is set in properties resource above -->
<sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityPost.xml"/> <sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityPost.xml"/>
<sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityFeed.xml"/> <sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityFeed.xml"/>
<sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityFeedControl.xml"/> <sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityFeedControl.xml"/>

View File

@@ -20,7 +20,7 @@
</property> </property>
</bean> </bean>
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean" singleton="true"> <bean id="sqlMapClient" class="org.alfresco.repo.domain.ibatis.AlfrescoSqlMapClientFactoryBean" singleton="true">
<property name="configLocation"><value>classpath:alfresco/activities/activities-SqlMapConfig.xml</value></property> <property name="configLocation"><value>classpath:alfresco/activities/activities-SqlMapConfig.xml</value></property>
<property name="dataSource" ref="iBatisDataSource"/> <property name="dataSource" ref="iBatisDataSource"/>
</bean> </bean>

View File

@@ -187,5 +187,5 @@ INSERT INTO alf_applied_patch
VALUES VALUES
( (
'patch.db-V2.2-ACL-From-2.1-A', 'Manually executed script upgrade V2.2: Update acl schema', 'patch.db-V2.2-ACL-From-2.1-A', 'Manually executed script upgrade V2.2: Update acl schema',
81, 82, -1, 120, null, 'UNKOWN', 1, 1, 'Script completed' 0, 82, -1, 120, null, 'UNKOWN', 1, 1, 'Script completed'
); );

View File

@@ -964,7 +964,7 @@ ALTER TABLE t_alf_store RENAME TO alf_store;
-- Modify index and constraint names -- -- Modify index and constraint names --
-- ------------------------------------- -- -------------------------------------
ALTER TABLE alf_attributes DROP INDEX fk_attributes_n_acl, DROP FOREIGN KEY fk_attributes_n_acl; -- (optional) ALTER TABLE alf_attributes DROP INDEX fk_attributes_n_acl, DROP FOREIGN KEY fk_attributes_n_acl; -- (optional)
ALTER TABLE alf_attributes DROP INDEX fk_attr_n_acl; -- (optional) ALTER TABLE alf_attributes DROP INDEX fk_attr_n_acl, DROP FOREIGN KEY fk_attr_n_acl; -- (optional)
ALTER TABLE alf_attributes ALTER TABLE alf_attributes
ADD INDEX fk_alf_attr_acl (acl_id) ADD INDEX fk_alf_attr_acl (acl_id)
; ;

View File

@@ -1,7 +1,11 @@
# #
# Hibernate configuration # Hibernate configuration
# #
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
# The Hibernate Dialect:
# As of V3.1, the dialect is automatically detected.
# It is still possible to set the dialect explicitly, for example:
# hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.jdbc.use_streams_for_binary=true hibernate.jdbc.use_streams_for_binary=true
hibernate.show_sql=false hibernate.show_sql=false
@@ -16,4 +20,9 @@ hibernate.connection.isolation=2
#hibernate.query.substitutions= #hibernate.query.substitutions=
#hibernate.jdbc.use_get_generated_keys=false #hibernate.jdbc.use_get_generated_keys=false
# Oracle Schema Distinction:
# See https://issues.alfresco.com/jira/browse/ETHREEOH-680
# Metadata queries to Oracle have to be limited by schema name
# when multiple instances of Alfresco are installed on an Oracle server.
#hibernate.default_schema= #hibernate.default_schema=

View File

@@ -205,6 +205,12 @@
<default>read_package_item_actions</default> <default>read_package_item_actions</default>
</property> </property>
<!-- List of "hidden" transitions to consider masking from user -->
<property name="bpm:hiddenTransitions">
<type>d:text</type>
<multiple>true</multiple>
<default></default>
</property>
</properties> </properties>
<associations> <associations>

View File

@@ -87,6 +87,9 @@
<entry key="workspace://SpacesStore"><value>archive://SpacesStore</value></entry> <entry key="workspace://SpacesStore"><value>archive://SpacesStore</value></entry>
</map> </map>
</property> </property>
<property name="tenantService">
<ref bean="tenantService" />
</property>
</bean> </bean>
<!-- Wrapper component to handle restore and purge of archived nodes --> <!-- Wrapper component to handle restore and purge of archived nodes -->

View File

@@ -157,6 +157,11 @@
<type name="wcmwf:submittedTask"> <type name="wcmwf:submittedTask">
<parent>wcmwf:workflowTask</parent> <parent>wcmwf:workflowTask</parent>
<overrides>
<property name="bpm:hiddenTransitions">
<default>onsubmit</default>
</property>
</overrides>
<mandatory-aspects> <mandatory-aspects>
<aspect>bpm:assignees</aspect> <aspect>bpm:assignees</aspect>
<aspect>wcmwf:reviewType</aspect> <aspect>wcmwf:reviewType</aspect>
@@ -167,6 +172,11 @@
<type name="wcmwf:submittedDirectTask"> <type name="wcmwf:submittedDirectTask">
<parent>wcmwf:workflowTask</parent> <parent>wcmwf:workflowTask</parent>
<overrides>
<property name="bpm:hiddenTransitions">
<default>onsubmit</default>
</property>
</overrides>
<mandatory-aspects> <mandatory-aspects>
<aspect>wcmwf:submission</aspect> <aspect>wcmwf:submission</aspect>
</mandatory-aspects> </mandatory-aspects>

View File

@@ -28,6 +28,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
/** /**
@@ -39,14 +40,16 @@ public class StoreArchiveMap
{ {
private Map<StoreRef, StoreRef> storeArchiveMap; private Map<StoreRef, StoreRef> storeArchiveMap;
private TenantService tenantService;
public StoreArchiveMap() public StoreArchiveMap()
{ {
storeArchiveMap = new HashMap<StoreRef, StoreRef>(0); storeArchiveMap = new HashMap<StoreRef, StoreRef>(0);
} }
public Map<StoreRef, StoreRef> getArchiveMap() public void setTenantService(TenantService tenantService)
{ {
return storeArchiveMap; this.tenantService = tenantService;
} }
public void setArchiveMap(Map<String, String> archiveMap) public void setArchiveMap(Map<String, String> archiveMap)
@@ -70,4 +73,26 @@ public class StoreArchiveMap
storeArchiveMap.put(storeRefKey, storeRefValue); storeArchiveMap.put(storeRefKey, storeRefValue);
} }
} }
public StoreRef get(StoreRef storeRef)
{
if (tenantService.isEnabled())
{
return tenantService.getName(storeArchiveMap.get(tenantService.getBaseName(storeRef)));
}
else
{
return storeArchiveMap.get(storeRef);
}
}
public void put(StoreRef workStoreRef, StoreRef archiveStoreRef)
{
storeArchiveMap.put(workStoreRef, archiveStoreRef);
}
public void clear()
{
storeArchiveMap.clear();
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -141,7 +141,7 @@ public class ArchiveAndRestoreTest extends TestCase
// Map the work store to the archive store. This will already be wired into the NodeService. // Map the work store to the archive store. This will already be wired into the NodeService.
StoreArchiveMap archiveMap = (StoreArchiveMap) ctx.getBean("storeArchiveMap"); StoreArchiveMap archiveMap = (StoreArchiveMap) ctx.getBean("storeArchiveMap");
archiveMap.getArchiveMap().put(workStoreRef, archiveStoreRef); archiveMap.put(workStoreRef, archiveStoreRef);
TestWithUserUtils.createUser(USER_A, USER_A, workStoreRootNodeRef, nodeService, authenticationService); TestWithUserUtils.createUser(USER_A, USER_A, workStoreRootNodeRef, nodeService, authenticationService);
TestWithUserUtils.createUser(USER_B, USER_B, workStoreRootNodeRef, nodeService, authenticationService); TestWithUserUtils.createUser(USER_B, USER_B, workStoreRootNodeRef, nodeService, authenticationService);
@@ -508,7 +508,7 @@ public class ArchiveAndRestoreTest extends TestCase
// Now force full deletions and creations // Now force full deletions and creations
StoreArchiveMap archiveMap = (StoreArchiveMap) ctx.getBean("storeArchiveMap"); StoreArchiveMap archiveMap = (StoreArchiveMap) ctx.getBean("storeArchiveMap");
archiveMap.getArchiveMap().clear(); archiveMap.clear();
long cumulatedDeleteTimeNs = 0; long cumulatedDeleteTimeNs = 0;
long cumulatedCreateTimeNs = 0; long cumulatedCreateTimeNs = 0;
for (int i = 0; i < iterations; i++) for (int i = 0; i < iterations; i++)

View File

@@ -748,7 +748,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
else else
{ {
StoreRef storeRef = nodeRef.getStoreRef(); StoreRef storeRef = nodeRef.getStoreRef();
archiveStoreRef = storeArchiveMap.getArchiveMap().get(storeRef); archiveStoreRef = storeArchiveMap.get(storeRef);
// get the type and check if we need archiving // get the type and check if we need archiving
TypeDefinition typeDef = dictionaryService.getType(nodeTypeQName); TypeDefinition typeDef = dictionaryService.getType(nodeTypeQName);
if (typeDef == null || !typeDef.isArchive() || archiveStoreRef == null) if (typeDef == null || !typeDef.isArchive() || archiveStoreRef == null)
@@ -2202,7 +2202,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
public NodeRef getStoreArchiveNode(StoreRef storeRef) public NodeRef getStoreArchiveNode(StoreRef storeRef)
{ {
StoreRef archiveStoreRef = storeArchiveMap.getArchiveMap().get(storeRef); StoreRef archiveStoreRef = storeArchiveMap.get(storeRef);
if (archiveStoreRef == null) if (archiveStoreRef == null)
{ {
// no mapping for the given store // no mapping for the given store

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -37,7 +37,6 @@ import javax.transaction.UserTransaction;
import org.alfresco.i18n.I18NUtil; import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.domain.Store;
import org.alfresco.repo.node.BaseNodeServiceTest; import org.alfresco.repo.node.BaseNodeServiceTest;
import org.alfresco.repo.node.StoreArchiveMap; import org.alfresco.repo.node.StoreArchiveMap;
import org.alfresco.repo.node.cleanup.NodeCleanupRegistry; import org.alfresco.repo.node.cleanup.NodeCleanupRegistry;
@@ -465,7 +464,7 @@ public class DbNodeServiceImplTest extends BaseNodeServiceTest
// Ensure that the archive feature is enabled // Ensure that the archive feature is enabled
StoreRef archiveStoreRef = ns.createStore("test", getName() + "-" + System.currentTimeMillis()); StoreRef archiveStoreRef = ns.createStore("test", getName() + "-" + System.currentTimeMillis());
storeArchiveMap.getArchiveMap().put(parentNodeRef.getStoreRef(), archiveStoreRef); storeArchiveMap.put(parentNodeRef.getStoreRef(), archiveStoreRef);
// Delete parent. Cascade is OFF, so children should be left in their current store. // Delete parent. Cascade is OFF, so children should be left in their current store.
ns.deleteNode(parentNodeRef); ns.deleteNode(parentNodeRef);

View File

@@ -128,7 +128,14 @@ public class ShutdownBackstop extends AbstractLifecycleBean
// nothing to do here // nothing to do here
} }
log.error("Alfresco terminating via Shutdown Backstop"); try
{
log.error("Alfresco terminating via Shutdown Backstop");
}
catch (Throwable t)
{
// Do nothing
}
try try
{ {
@@ -149,7 +156,14 @@ public class ShutdownBackstop extends AbstractLifecycleBean
t.printStackTrace(); t.printStackTrace();
} }
log.error("Alfresco terminated"); try
{
log.error("Alfresco terminated");
}
catch (Throwable t)
{
// Do nothing
}
System.exit(1); System.exit(1);
} }

View File

@@ -49,6 +49,7 @@ import org.alfresco.service.cmr.invitation.InvitationSearchCriteria;
import org.alfresco.service.cmr.invitation.InvitationService; import org.alfresco.service.cmr.invitation.InvitationService;
import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType; import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteService;
@@ -450,7 +451,10 @@ public class Site implements Serializable
} }
} }
} }
} }
// Make the "admin" the owner of the node
serviceRegistry.getOwnableService().setOwner(containerNodeRef, AuthenticationUtil.getAdminUserName());
return containerNodeRef; return containerNodeRef;
} }

View File

@@ -51,6 +51,8 @@ import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.site.SiteAVMBootstrap; import org.alfresco.repo.site.SiteAVMBootstrap;
import org.alfresco.repo.usage.UserUsageBootstrapJob;
import org.alfresco.repo.usage.UserUsageTrackingComponent;
import org.alfresco.repo.workflow.WorkflowDeployer; import org.alfresco.repo.workflow.WorkflowDeployer;
import org.alfresco.service.cmr.admin.RepoAdminService; import org.alfresco.service.cmr.admin.RepoAdminService;
import org.alfresco.service.cmr.attributes.AttributeService; import org.alfresco.service.cmr.attributes.AttributeService;
@@ -344,53 +346,56 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
initTenant(tenantDomain, rootContentStoreDir); initTenant(tenantDomain, rootContentStoreDir);
AuthenticationUtil.runAs(new RunAsWork<Object>() try
{ {
public Object doWork() // note: runAs would cause auditable property "creator" to be "admin" instead of "System@xxx"
{ AuthenticationUtil.pushAuthentication();
dictionaryComponent.init(); AuthenticationUtil.setFullyAuthenticatedUser(getSystemUser(tenantDomain));
tenantFileContentStore.init();
dictionaryComponent.init();
// create tenant-specific stores tenantFileContentStore.init();
ImporterBootstrap userImporterBootstrap = (ImporterBootstrap)ctx.getBean("userBootstrap");
bootstrapUserTenantStore(userImporterBootstrap, tenantDomain, tenantAdminRawPassword); // create tenant-specific stores
ImporterBootstrap userImporterBootstrap = (ImporterBootstrap)ctx.getBean("userBootstrap");
ImporterBootstrap systemImporterBootstrap = (ImporterBootstrap)ctx.getBean("systemBootstrap"); bootstrapUserTenantStore(userImporterBootstrap, tenantDomain, tenantAdminRawPassword);
bootstrapSystemTenantStore(systemImporterBootstrap, tenantDomain);
ImporterBootstrap systemImporterBootstrap = (ImporterBootstrap)ctx.getBean("systemBootstrap");
bootstrapSystemTenantStore(systemImporterBootstrap, tenantDomain);
// deprecated // deprecated
ImporterBootstrap versionImporterBootstrap = (ImporterBootstrap)ctx.getBean("versionBootstrap"); ImporterBootstrap versionImporterBootstrap = (ImporterBootstrap)ctx.getBean("versionBootstrap");
bootstrapVersionTenantStore(versionImporterBootstrap, tenantDomain); bootstrapVersionTenantStore(versionImporterBootstrap, tenantDomain);
ImporterBootstrap version2ImporterBootstrap = (ImporterBootstrap)ctx.getBean("version2Bootstrap"); ImporterBootstrap version2ImporterBootstrap = (ImporterBootstrap)ctx.getBean("version2Bootstrap");
bootstrapVersionTenantStore(version2ImporterBootstrap, tenantDomain); bootstrapVersionTenantStore(version2ImporterBootstrap, tenantDomain);
ImporterBootstrap spacesArchiveImporterBootstrap = (ImporterBootstrap)ctx.getBean("spacesArchiveBootstrap"); ImporterBootstrap spacesArchiveImporterBootstrap = (ImporterBootstrap)ctx.getBean("spacesArchiveBootstrap");
bootstrapSpacesArchiveTenantStore(spacesArchiveImporterBootstrap, tenantDomain); bootstrapSpacesArchiveTenantStore(spacesArchiveImporterBootstrap, tenantDomain);
ImporterBootstrap spacesImporterBootstrap = (ImporterBootstrap)ctx.getBean("spacesBootstrap"); ImporterBootstrap spacesImporterBootstrap = (ImporterBootstrap)ctx.getBean("spacesBootstrap");
bootstrapSpacesTenantStore(spacesImporterBootstrap, tenantDomain); bootstrapSpacesTenantStore(spacesImporterBootstrap, tenantDomain);
siteAVMBootstrap.bootstrap(); siteAVMBootstrap.bootstrap();
// notify listeners that tenant has been created & hence enabled // notify listeners that tenant has been created & hence enabled
for (TenantDeployer tenantDeployer : tenantDeployers) for (TenantDeployer tenantDeployer : tenantDeployers)
{ {
tenantDeployer.onEnableTenant(); tenantDeployer.onEnableTenant();
} }
// bootstrap workflows // bootstrap workflows
for (WorkflowDeployer workflowDeployer : workflowDeployers) for (WorkflowDeployer workflowDeployer : workflowDeployers)
{ {
workflowDeployer.init(); workflowDeployer.init();
} }
// bootstrap modules (if any) // bootstrap modules (if any)
moduleService.startModules(); moduleService.startModules();
}
return null; finally
} {
}, getSystemUser(tenantDomain)); AuthenticationUtil.popAuthentication();
}
logger.info("Tenant created: " + tenantDomain); logger.info("Tenant created: " + tenantDomain);
} }
@@ -419,39 +424,42 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
{ {
initTenant(tenantDomain, rootContentStoreDir); initTenant(tenantDomain, rootContentStoreDir);
AuthenticationUtil.runAs(new RunAsWork<Object>() try
{ {
public Object doWork() // note: runAs would cause auditable property "creator" to be "admin" instead of "System@xxx"
{ AuthenticationUtil.pushAuthentication();
dictionaryComponent.init(); AuthenticationUtil.setFullyAuthenticatedUser(getSystemUser(tenantDomain));
tenantFileContentStore.init();
dictionaryComponent.init();
// import tenant-specific stores tenantFileContentStore.init();
importBootstrapUserTenantStore(tenantDomain, directorySource);
importBootstrapSystemTenantStore(tenantDomain, directorySource); // import tenant-specific stores
importBootstrapVersionTenantStore(tenantDomain, directorySource); importBootstrapUserTenantStore(tenantDomain, directorySource);
importBootstrapSpacesArchiveTenantStore(tenantDomain, directorySource); importBootstrapSystemTenantStore(tenantDomain, directorySource);
importBootstrapSpacesModelsTenantStore(tenantDomain, directorySource); importBootstrapVersionTenantStore(tenantDomain, directorySource);
importBootstrapSpacesTenantStore(tenantDomain, directorySource); importBootstrapSpacesArchiveTenantStore(tenantDomain, directorySource);
importBootstrapSpacesModelsTenantStore(tenantDomain, directorySource);
// notify listeners that tenant has been created & hence enabled importBootstrapSpacesTenantStore(tenantDomain, directorySource);
for (TenantDeployer tenantDeployer : tenantDeployers)
{ // notify listeners that tenant has been created & hence enabled
tenantDeployer.onEnableTenant(); for (TenantDeployer tenantDeployer : tenantDeployers)
} {
tenantDeployer.onEnableTenant();
// bootstrap workflows }
for (WorkflowDeployer workflowDeployer : workflowDeployers)
{ // bootstrap workflows
workflowDeployer.init(); for (WorkflowDeployer workflowDeployer : workflowDeployers)
} {
workflowDeployer.init();
// bootstrap modules (if any) }
moduleService.startModules();
// bootstrap modules (if any)
return null; moduleService.startModules();
} }
}, getSystemUser(tenantDomain)); finally
{
AuthenticationUtil.popAuthentication();
}
logger.info("Tenant imported: " + tenantDomain); logger.info("Tenant imported: " + tenantDomain);
} }
@@ -919,11 +927,9 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
spacesImporterBootstrap.bootstrap(); spacesImporterBootstrap.bootstrap();
/* TODO - pending fix for ETHREEOH-283
// calculate any missing usages // calculate any missing usages
UserUsageTrackingComponent userUsageTrackingComponent = (UserUsageTrackingComponent)ctx.getBean(UserUsageBootstrapJob.KEY_COMPONENT); UserUsageTrackingComponent userUsageTrackingComponent = (UserUsageTrackingComponent)ctx.getBean(UserUsageBootstrapJob.KEY_COMPONENT);
userUsageTrackingComponent.bootstrapInternal(); userUsageTrackingComponent.bootstrapInternal();
*/
logger.debug("Bootstrapped store: " + tenantService.getBaseName(bootstrapStoreRef)); logger.debug("Bootstrapped store: " + tenantService.getBaseName(bootstrapStoreRef));
} }
@@ -968,8 +974,7 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
{ {
try try
{ {
// switch to admin in order to deploy within context of tenant domain // deploy within context of tenant domain
// assumes each tenant has default "admin" user
AuthenticationUtil.runAs(new RunAsWork<Object>() AuthenticationUtil.runAs(new RunAsWork<Object>()
{ {
public Object doWork() public Object doWork()
@@ -1036,8 +1041,7 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
{ {
try try
{ {
// switch to admin in order to deploy within context of tenant domain // undeploy within context of tenant domain
// assumes each tenant has default "admin" user
AuthenticationUtil.runAs(new RunAsWork<Object>() AuthenticationUtil.runAs(new RunAsWork<Object>()
{ {
public Object doWork() public Object doWork()

View File

@@ -42,6 +42,7 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
@@ -85,6 +86,7 @@ public class MultiTDemoTest extends TestCase
private TenantService tenantService; private TenantService tenantService;
private AuthorityService authorityService; private AuthorityService authorityService;
private CategoryService categoryService; private CategoryService categoryService;
private CheckOutCheckInService cociService;
public static int NUM_TENANTS = 11; public static int NUM_TENANTS = 11;
@@ -140,6 +142,7 @@ public class MultiTDemoTest extends TestCase
ownableService = (OwnableService) ctx.getBean("OwnableService"); ownableService = (OwnableService) ctx.getBean("OwnableService");
authorityService = (AuthorityService) ctx.getBean("AuthorityService"); authorityService = (AuthorityService) ctx.getBean("AuthorityService");
categoryService = (CategoryService) ctx.getBean("CategoryService"); categoryService = (CategoryService) ctx.getBean("CategoryService");
cociService = (CheckOutCheckInService) ctx.getBean("CheckoutCheckinService");
} }
@Override @Override
@@ -572,6 +575,85 @@ public class MultiTDemoTest extends TestCase
} }
} }
public void testCOCIandSearch()
{
logger.info("Test checkout/checkin and search");
for (final String tenantDomain : tenants)
{
final String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
AuthenticationUtil.runAs(new RunAsWork<Object>()
{
public Object doWork() throws Exception
{
// search for local copy of bootstrapped file 'invite_user_email.ftl' (see email_templates.acp)
String origText = "You have been invited to";
String query = "+PATH:\"/app:company_home/app:dictionary/app:email_templates/*\" +TEXT:\""+origText+"\"";
ResultSet resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
assertEquals(1, resultSet.length());
NodeRef nodeRef = resultSet.getNodeRef(0);
// checkout, update and checkin
NodeRef workingCopyNodeRef = cociService.checkout(nodeRef);
ContentWriter writer = contentService.getWriter(workingCopyNodeRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setEncoding("UTF-8");
String updateText = "Updated by "+tenantAdminName;
writer.putContent(updateText);
cociService.checkin(workingCopyNodeRef, null);
query = "+PATH:\"/app:company_home/app:dictionary/app:email_templates/*\" +TEXT:\""+origText+"\"";
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
assertEquals(0, resultSet.length());
query = "+PATH:\"/app:company_home/app:dictionary/app:email_templates/*\" +TEXT:\""+updateText+"\"";
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
assertEquals(1, resultSet.length());
return null;
}
}, tenantAdminName);
}
}
public void testDeleteArchiveAndRestoreContent()
{
logger.info("test delete/archive & restore content");
for (final String tenantDomain : tenants)
{
final String tenantUserName = tenantService.getDomainUser(TEST_USER1, tenantDomain);
AuthenticationUtil.runAs(new RunAsWork<Object>()
{
public Object doWork() throws Exception
{
NodeRef homeSpaceRef = getHomeSpaceFolderNode(tenantUserName);
NodeRef contentRef = addTextContent(homeSpaceRef, tenantUserName+" tqbfjotld.txt", "The quick brown fox jumps over the lazy dog (tenant " + tenantDomain + ")");
NodeRef storeArchiveNode = nodeService.getStoreArchiveNode(contentRef.getStoreRef());
nodeService.deleteNode(contentRef);
// deduce archived nodeRef
StoreRef archiveStoreRef = storeArchiveNode.getStoreRef();
NodeRef archivedContentRef = new NodeRef(archiveStoreRef, contentRef.getId());
nodeService.restoreNode(archivedContentRef, null, null, null);
return null;
}
}, tenantUserName);
}
}
private void createGroup(String shortName, String parentShortName) private void createGroup(String shortName, String parentShortName)
{ {
// create new Group using authority Service // create new Group using authority Service

View File

@@ -344,7 +344,7 @@ public class ContentUsageImpl implements ContentUsageService,
private void incrementUserUsage(String userName, long contentSize, NodeRef contentNodeRef) private void incrementUserUsage(String userName, long contentSize, NodeRef contentNodeRef)
{ {
if (! userName.equals(authenticationComponent.getSystemUserName())) if (! authenticationComponent.isSystemUserName(userName))
{ {
// increment usage - add positive delta // increment usage - add positive delta
if (logger.isDebugEnabled()) logger.debug("incrementUserUsage: username="+userName+", contentSize="+contentSize+", contentNodeRef="+contentNodeRef); if (logger.isDebugEnabled()) logger.debug("incrementUserUsage: username="+userName+", contentSize="+contentSize+", contentNodeRef="+contentNodeRef);
@@ -366,14 +366,17 @@ public class ContentUsageImpl implements ContentUsageService,
throw new ContentQuotaException("User quota exceeded"); throw new ContentQuotaException("User quota exceeded");
} }
NodeRef personNodeRef = personService.getPerson(userName); NodeRef personNodeRef = getPerson(userName);
usageService.insertDelta(personNodeRef, contentSize); if (personNodeRef != null)
{
usageService.insertDelta(personNodeRef, contentSize);
}
} }
} }
private void decrementUserUsage(String userName, long contentSize, NodeRef contentNodeRef) private void decrementUserUsage(String userName, long contentSize, NodeRef contentNodeRef)
{ {
if (! userName.equals(authenticationComponent.getSystemUserName())) if (! authenticationComponent.isSystemUserName(userName))
{ {
// decrement usage - add negative delta // decrement usage - add negative delta
if (logger.isDebugEnabled()) logger.debug("decrementUserUsage: username="+userName+", contentSize="+contentSize+", contentNodeRef="+contentNodeRef); if (logger.isDebugEnabled()) logger.debug("decrementUserUsage: username="+userName+", contentSize="+contentSize+", contentNodeRef="+contentNodeRef);
@@ -390,8 +393,11 @@ public class ContentUsageImpl implements ContentUsageService,
} }
} }
NodeRef personNodeRef = personService.getPerson(userName); NodeRef personNodeRef = getPerson(userName);
usageService.insertDelta(personNodeRef, (-contentSize)); if (personNodeRef != null)
{
usageService.insertDelta(personNodeRef, (-contentSize));
}
} }
} }
@@ -424,7 +430,7 @@ public class ContentUsageImpl implements ContentUsageService,
{ {
long currentUsage = -1; long currentUsage = -1;
NodeRef personNodeRef = personService.getPerson(userName); NodeRef personNodeRef = getPerson(userName);
if (personNodeRef != null) if (personNodeRef != null)
{ {
currentUsage = getUserStoredUsage(personNodeRef); currentUsage = getUserStoredUsage(personNodeRef);
@@ -457,7 +463,7 @@ public class ContentUsageImpl implements ContentUsageService,
*/ */
public void setUserQuota(String userName, long currentQuota) public void setUserQuota(String userName, long currentQuota)
{ {
NodeRef personNodeRef = personService.getPerson(userName); NodeRef personNodeRef = getPerson(userName);
if (personNodeRef != null) if (personNodeRef != null)
{ {
nodeService.setProperty(personNodeRef, ContentModel.PROP_SIZE_QUOTA, new Long(currentQuota)); nodeService.setProperty(personNodeRef, ContentModel.PROP_SIZE_QUOTA, new Long(currentQuota));
@@ -468,7 +474,7 @@ public class ContentUsageImpl implements ContentUsageService,
{ {
Long currentQuota = null; Long currentQuota = null;
NodeRef personNodeRef = personService.getPerson(userName); NodeRef personNodeRef = getPerson(userName);
if (personNodeRef != null) if (personNodeRef != null)
{ {
currentQuota = (Long)nodeService.getProperty(personNodeRef, ContentModel.PROP_SIZE_QUOTA); currentQuota = (Long)nodeService.getProperty(personNodeRef, ContentModel.PROP_SIZE_QUOTA);
@@ -481,4 +487,27 @@ public class ContentUsageImpl implements ContentUsageService,
{ {
return enabled; return enabled;
} }
private NodeRef getPerson(String userName)
{
NodeRef personNodeRef = null;
try
{
personNodeRef = personService.getPerson(userName);
}
catch (RuntimeException e)
{
// workaround for ETHREEOH-1457 where existing tenants (created using 3.0.1) may have been bootstrapped with creator set
// to super admin (eg. "admin") rather than "System@xxx". This workaround should remain until we patch any such existing tenants
if (tenantService.isEnabled())
{
personNodeRef = null;
}
else
{
throw e;
}
}
return personNodeRef;
}
} }

View File

@@ -58,6 +58,7 @@ public interface WorkflowModel
static final QName PROP_OUTCOME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "outcome"); static final QName PROP_OUTCOME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "outcome");
static final QName PROP_PACKAGE_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageActionGroup"); static final QName PROP_PACKAGE_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageActionGroup");
static final QName PROP_PACKAGE_ITEM_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageItemActionGroup"); static final QName PROP_PACKAGE_ITEM_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageItemActionGroup");
static final QName PROP_HIDDEN_TRANSITIONS = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "hiddenTransitions");
static final QName ASSOC_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"); static final QName ASSOC_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package");
// workflow task contstants // workflow task contstants