Merged V3.2 to HEAD

19507: ALF-955: deletion of dynamic custom model
   19553: Follow-on to r19507 (ALF-955) - fix testAutoRemovalOfVersionHistory


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19569 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jan Vonka
2010-03-25 09:30:11 +00:00
parent fcffbe3af8
commit f3b8452415
10 changed files with 563 additions and 169 deletions

View File

@@ -84,7 +84,7 @@
<bean id="storeArchiveMap" class="org.alfresco.repo.node.StoreArchiveMap"> <bean id="storeArchiveMap" class="org.alfresco.repo.node.StoreArchiveMap">
<property name="archiveMap"> <property name="archiveMap">
<map> <map>
<entry key="workspace://SpacesStore"><value>archive://SpacesStore</value></entry> <entry key="workspace://SpacesStore"><value>${spaces.archive.store}</value></entry>
</map> </map>
</property> </property>
<property name="tenantService"> <property name="tenantService">
@@ -228,11 +228,19 @@
<ref bean="avmNodeService"/> <ref bean="avmNodeService"/>
</property> </property>
<property name="nodeIndexer"> <property name="nodeIndexer">
<ref bean="nodeIndexer" /> <ref bean="nodeIndexer"/>
</property> </property>
<property name="cascadeInTransaction"> <property name="cascadeInTransaction">
<value>${system.cascadeDeleteInTransaction}</value> <value>${system.cascadeDeleteInTransaction}</value>
</property> </property>
<property name="tenantService">
<ref bean="tenantService"/>
</property>
<property name="storesToIgnorePolicies">
<list>
<value>${spaces.archive.store}</value>
</list>
</property>
</bean> </bean>
<bean id="nodeAuditor" class="org.alfresco.repo.node.NodeAuditor"> <bean id="nodeAuditor" class="org.alfresco.repo.node.NodeAuditor">

View File

@@ -27,18 +27,31 @@ package org.alfresco.repo.admin;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.cmr.admin.RepoAdminService; import org.alfresco.service.cmr.admin.RepoAdminService;
import org.alfresco.service.cmr.dictionary.ClassDefinition; import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.ApplicationContextHelper;
@@ -61,6 +74,11 @@ public class RepoAdminServiceImplTest extends TestCase
private DictionaryService dictionaryService; private DictionaryService dictionaryService;
private TransactionService transactionService; private TransactionService transactionService;
private NodeService nodeService;
private ContentService contentService;
private SearchService searchService;
private NamespaceService namespaceService;
final String modelPrefix = "model-"; final String modelPrefix = "model-";
final static String MKR = "{MKR}"; final static String MKR = "{MKR}";
@@ -107,6 +125,11 @@ public class RepoAdminServiceImplTest extends TestCase
dictionaryService = (DictionaryService) ctx.getBean("DictionaryService"); dictionaryService = (DictionaryService) ctx.getBean("DictionaryService");
transactionService = (TransactionService) ctx.getBean("TransactionService"); transactionService = (TransactionService) ctx.getBean("TransactionService");
nodeService = (NodeService) ctx.getBean("NodeService");
contentService = (ContentService) ctx.getBean("ContentService");
searchService = (SearchService) ctx.getBean("SearchService");
namespaceService = (NamespaceService) ctx.getBean("NamespaceService");
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
} }
@@ -125,9 +148,140 @@ public class RepoAdminServiceImplTest extends TestCase
// Test custom model management // Test custom model management
// //
public void testSimpleDynamicModel() throws Exception public void testSimpleDynamicModelViaNodeService() throws Exception
{ {
final int X = 0; final String X = "A";
final String modelFileName = modelPrefix+X+".xml";
final QName typeName = QName.createQName("{http://www.alfresco.org/test/testmodel"+X+"/1.0}base");
final QName modelName = QName.createQName("{http://www.alfresco.org/test/testmodel"+X+"/1.0}testModel"+X);
try
{
if (isModelDeployed(modelFileName))
{
// undeploy model
repoAdminService.undeployModel(modelFileName);
}
StoreRef storeRef = StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
assertNull(dictionaryService.getClass(typeName));
final int defaultModelCnt = dictionaryService.getAllModels().size();
// deploy custom model
String model = MODEL_MKR_XML.replace(MKR, X+"");
InputStream modelStream = new ByteArrayInputStream(model.getBytes("UTF-8"));
List<NodeRef> nodeRefs = searchService.selectNodes(rootNodeRef, "/app:company_home/app:dictionary/app:models", null, namespaceService, false);
assertEquals(1, nodeRefs.size());
NodeRef modelsNodeRef = nodeRefs.get(0);
// create model node
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>();
contentProps.put(ContentModel.PROP_NAME, modelFileName);
NodeRef model1 = nodeService.createNode(
modelsNodeRef,
ContentModel.ASSOC_CONTAINS,
modelName,
ContentModel.TYPE_DICTIONARY_MODEL,
contentProps).getChildRef();
// add titled aspect (for Web Client display)
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>();
titledProps.put(ContentModel.PROP_TITLE, modelFileName);
titledProps.put(ContentModel.PROP_DESCRIPTION, modelFileName);
nodeService.addAspect(model1, ContentModel.ASPECT_TITLED, titledProps);
ContentWriter writer = contentService.getWriter(model1, ContentModel.PROP_CONTENT, true);
writer.setMimetype(MimetypeMap.MIMETYPE_XML);
writer.setEncoding("UTF-8");
writer.putContent(modelStream); // also invokes policies for DictionaryModelType - e.g. onContentUpdate
modelStream.close();
// activate the model
nodeService.setProperty(model1, ContentModel.PROP_MODEL_ACTIVE, new Boolean(true));
assertEquals(defaultModelCnt+1, dictionaryService.getAllModels().size());
ClassDefinition myType = dictionaryService.getClass(typeName);
assertNotNull(myType);
assertEquals(modelName, myType.getModel().getName());
// create node with custom type
NodeRef node1 = nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("http://www.alfresco.org/model/system/1.0", "node1"),
typeName,
null).getChildRef();
// try to delete the model
try
{
nodeService.deleteNode(model1);
fail();
}
catch (AlfrescoRuntimeException are)
{
// expected
assertTrue(are.getMessage().contains("Failed to validate model delete"));
}
nodeService.deleteNode(node1);
assertFalse(nodeService.exists(node1));
NodeRef archiveRootNode = nodeService.getStoreArchiveNode(storeRef);
NodeRef archiveNode1 = new NodeRef(archiveRootNode.getStoreRef(), node1.getId());
assertTrue(nodeService.exists(archiveNode1));
// try to delete the model
try
{
nodeService.deleteNode(model1);
fail();
}
catch (AlfrescoRuntimeException are)
{
// expected
assertTrue(are.getMessage().contains("Failed to validate model delete"));
}
nodeService.deleteNode(archiveNode1);
assertFalse(nodeService.exists(archiveNode1));
// delete model
nodeService.deleteNode(model1);
assertEquals(defaultModelCnt, dictionaryService.getAllModels().size());
assertNull(dictionaryService.getClass(typeName));
NodeRef archiveModel1 = new NodeRef(archiveRootNode.getStoreRef(), model1.getId());
// restore model
nodeService.restoreNode(archiveModel1, null, null, null);
assertEquals(defaultModelCnt+1, dictionaryService.getAllModels().size());
assertNotNull(dictionaryService.getClass(typeName));
// delete for good
nodeService.deleteNode(model1);
nodeService.deleteNode(archiveModel1);
}
finally
{
// NOOP
}
}
public void testSimpleDynamicModelViaRepoAdminService() throws Exception
{
final String X = "B";
final String modelFileName = modelPrefix+X+".xml"; final String modelFileName = modelPrefix+X+".xml";
final QName typeName = QName.createQName("{http://www.alfresco.org/test/testmodel"+X+"/1.0}base"); final QName typeName = QName.createQName("{http://www.alfresco.org/test/testmodel"+X+"/1.0}base");
final QName modelName = QName.createQName("{http://www.alfresco.org/test/testmodel"+X+"/1.0}testModel"+X); final QName modelName = QName.createQName("{http://www.alfresco.org/test/testmodel"+X+"/1.0}testModel"+X);
@@ -180,6 +334,7 @@ public class RepoAdminServiceImplTest extends TestCase
{ {
// expected // expected
assertTrue(are.getMessage().contains("Model deactivation failed")); assertTrue(are.getMessage().contains("Model deactivation failed"));
assertTrue(are.getCause().getMessage().contains("is already deactivated"));
} }
// re-activate model // re-activate model
@@ -202,9 +357,57 @@ public class RepoAdminServiceImplTest extends TestCase
{ {
// expected // expected
assertTrue(are.getMessage().contains("Model activation failed")); assertTrue(are.getMessage().contains("Model activation failed"));
assertTrue(are.getCause().getMessage().contains("is already activated"));
} }
// undeploy model StoreRef storeRef = StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
// create node with custom type
NodeRef node1 = nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("http://www.alfresco.org/model/system/1.0", "node1"),
typeName,
null).getChildRef();
// try to undeploy model
try
{
repoAdminService.undeployModel(modelFileName);
fail();
}
catch (AlfrescoRuntimeException are)
{
// expected
assertTrue(are.getMessage().contains("Model undeployment failed"));
assertTrue(are.getCause().getMessage().contains("Failed to validate model delete"));
}
nodeService.deleteNode(node1);
assertFalse(nodeService.exists(node1));
NodeRef archiveRootNode = nodeService.getStoreArchiveNode(storeRef);
NodeRef archiveNode1 = new NodeRef(archiveRootNode.getStoreRef(), node1.getId());
assertTrue(nodeService.exists(archiveNode1));
// try to undeploy model
try
{
repoAdminService.undeployModel(modelFileName);
fail();
}
catch (AlfrescoRuntimeException are)
{
// expected
assertTrue(are.getMessage().contains("Model undeployment failed"));
assertTrue(are.getCause().getMessage().contains("Failed to validate model delete"));
}
nodeService.deleteNode(archiveNode1);
assertFalse(nodeService.exists(archiveNode1));
// undeploy
repoAdminService.undeployModel(modelFileName); repoAdminService.undeployModel(modelFileName);
assertFalse(isModelDeployed(modelFileName)); assertFalse(isModelDeployed(modelFileName));
@@ -221,6 +424,7 @@ public class RepoAdminServiceImplTest extends TestCase
{ {
// expected // expected
assertTrue(are.getMessage().contains("Model undeployment failed")); assertTrue(are.getMessage().contains("Model undeployment failed"));
assertTrue(are.getCause().getMessage().contains("Could not find custom model"));
} }
} }
finally finally

View File

@@ -123,6 +123,11 @@ public class DictionaryBootstrap implements DictionaryListener
{ {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
if (logger.isTraceEnabled())
{
logger.trace("onDictionaryInit: ["+Thread.currentThread()+"]");
}
Collection<QName> modelsBefore = dictionaryDAO.getModels(); // note: on first bootstrap will init empty dictionary Collection<QName> modelsBefore = dictionaryDAO.getModels(); // note: on first bootstrap will init empty dictionary
int modelsBeforeCnt = (modelsBefore != null ? modelsBefore.size() : 0); int modelsBeforeCnt = (modelsBefore != null ? modelsBefore.size() : 0);
@@ -158,7 +163,7 @@ public class DictionaryBootstrap implements DictionaryListener
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Model count: before="+modelsBeforeCnt+", load="+models.size()+", after="+modelsAfterCnt+" in "+(System.currentTimeMillis()-startTime)+" msecs"); logger.debug("Model count: before="+modelsBeforeCnt+", load="+models.size()+", after="+modelsAfterCnt+" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"]");
} }
} }
} }

View File

@@ -162,8 +162,8 @@ public class DictionaryDAOImpl implements DictionaryDAO
} }
destroy(); destroy();
init(); init();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("... resetting dictionary completed"); logger.debug("... resetting dictionary completed");
@@ -175,17 +175,19 @@ public class DictionaryDAOImpl implements DictionaryDAO
{ {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
if (logger.isDebugEnabled())
{
logger.debug("Init Dictionary: ["+Thread.currentThread()+"] "+(tenantDomain.equals(TenantService.DEFAULT_DOMAIN) ? "" : " (Tenant: "+tenantDomain+")"));
}
try try
{ {
return AuthenticationUtil.runAs(new RunAsWork<DictionaryRegistry>() return AuthenticationUtil.runAs(new RunAsWork<DictionaryRegistry>()
{ {
public DictionaryRegistry doWork() public DictionaryRegistry doWork()
{ {
try try
{ {
// create threadlocal, if needed
createDataDictionaryLocal(tenantDomain);
DictionaryRegistry dictionaryRegistry = initDictionaryRegistry(tenantDomain); DictionaryRegistry dictionaryRegistry = initDictionaryRegistry(tenantDomain);
if (dictionaryRegistry == null) if (dictionaryRegistry == null)
@@ -221,24 +223,32 @@ public class DictionaryDAOImpl implements DictionaryDAO
readLock.unlock(); readLock.unlock();
} }
} }
} }
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain)); }, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain));
} }
finally finally
{ {
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
{ {
logger.info("Init Dictionary: model count = "+(getModels() != null ? getModels().size() : 0) +" in "+(System.currentTimeMillis()-startTime)+" msecs "+(tenantDomain.equals(TenantService.DEFAULT_DOMAIN) ? "" : " (Tenant: "+tenantDomain+")")); logger.info("Init Dictionary: model count = "+(getModels() != null ? getModels().size() : 0) +" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"] "+(tenantDomain.equals(TenantService.DEFAULT_DOMAIN) ? "" : " (Tenant: "+tenantDomain+")"));
} }
} }
} }
private DictionaryRegistry initDictionaryRegistry(String tenantDomain) private DictionaryRegistry initDictionaryRegistry(String tenantDomain)
{ {
getDictionaryRegistry(tenantDomain).setCompiledModels(new HashMap<QName,CompiledModel>()); // create threadlocal, if needed
getDictionaryRegistry(tenantDomain).setUriToModels(new HashMap<String, List<CompiledModel>>()); DictionaryRegistry dictionaryRegistry = createDataDictionaryLocal(tenantDomain);
// initialise empty dictionary & namespaces dictionaryRegistry.setCompiledModels(new HashMap<QName,CompiledModel>());
dictionaryRegistry.setUriToModels(new HashMap<String, List<CompiledModel>>());
if (logger.isTraceEnabled())
{
logger.trace("Empty dictionary initialised: "+dictionaryRegistry+" - "+defaultDictionaryRegistryThreadLocal+" ["+Thread.currentThread()+"]");
}
// initialise empty namespaces
namespaceDAO.init(); namespaceDAO.init();
// populate the dictionary based on registered sources // populate the dictionary based on registered sources
@@ -253,7 +263,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
dictionaryListener.afterDictionaryInit(); dictionaryListener.afterDictionaryInit();
} }
return getDictionaryRegistryLocal(tenantDomain); return dictionaryRegistry;
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -1018,7 +1028,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
} }
// create threadlocal // create threadlocal
private void createDataDictionaryLocal(String tenantDomain) private DictionaryRegistry createDataDictionaryLocal(String tenantDomain)
{ {
// create threadlocal, if needed // create threadlocal, if needed
DictionaryRegistry dictionaryRegistry = getDictionaryRegistryLocal(tenantDomain); DictionaryRegistry dictionaryRegistry = getDictionaryRegistryLocal(tenantDomain);
@@ -1035,6 +1045,8 @@ public class DictionaryDAOImpl implements DictionaryDAO
dictionaryRegistryThreadLocal.set(dictionaryRegistry); dictionaryRegistryThreadLocal.set(dictionaryRegistry);
} }
} }
return dictionaryRegistry;
} }
// get threadlocal // get threadlocal

View File

@@ -92,9 +92,6 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda
/** Key to the removed "workingcopy" aspect */ /** Key to the removed "workingcopy" aspect */
private static final String KEY_WORKING_COPY = "dictionaryModelType.workingCopy"; private static final String KEY_WORKING_COPY = "dictionaryModelType.workingCopy";
/** Key to the removed "archived" aspect */
private static final String KEY_ARCHIVED = "dictionaryModelType.archived";
/** The dictionary DAO */ /** The dictionary DAO */
private DictionaryDAO dictionaryDAO; private DictionaryDAO dictionaryDAO;
@@ -235,37 +232,37 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda
// Register interest in the onContentUpdate policy for the dictionary model type // Register interest in the onContentUpdate policy for the dictionary model type
policyComponent.bindClassBehaviour( policyComponent.bindClassBehaviour(
ContentServicePolicies.ON_CONTENT_UPDATE, ContentServicePolicies.ON_CONTENT_UPDATE,
ContentModel.TYPE_DICTIONARY_MODEL, ContentModel.TYPE_DICTIONARY_MODEL,
new JavaBehaviour(this, "onContentUpdate")); new JavaBehaviour(this, "onContentUpdate"));
// Register interest in the onUpdateProperties policy for the dictionary model type // Register interest in the onUpdateProperties policy for the dictionary model type
policyComponent.bindClassBehaviour( policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
ContentModel.TYPE_DICTIONARY_MODEL, ContentModel.TYPE_DICTIONARY_MODEL,
new JavaBehaviour(this, "onUpdateProperties")); new JavaBehaviour(this, "onUpdateProperties"));
// Register interest in the beforeDeleteNode policy for the dictionary model type // Register interest in the beforeDeleteNode policy for the dictionary model type
policyComponent.bindClassBehaviour( policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"), QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
ContentModel.TYPE_DICTIONARY_MODEL, ContentModel.TYPE_DICTIONARY_MODEL,
new JavaBehaviour(this, "beforeDeleteNode")); new JavaBehaviour(this, "beforeDeleteNode"));
// Register interest in the onDeleteNode policy for the dictionary model type // Register interest in the onDeleteNode policy for the dictionary model type
policyComponent.bindClassBehaviour( policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"), QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"),
ContentModel.TYPE_DICTIONARY_MODEL, ContentModel.TYPE_DICTIONARY_MODEL,
new JavaBehaviour(this, "onDeleteNode")); new JavaBehaviour(this, "onDeleteNode"));
// Register interest in the onRemoveAspect policy // Register interest in the onRemoveAspect policy
policyComponent.bindClassBehaviour( policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"), QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"),
this, this,
new JavaBehaviour(this, "onRemoveAspect")); new JavaBehaviour(this, "onRemoveAspect"));
// Register interest in the onCreateNode policy // Register interest in the onCreateNode policy
policyComponent.bindClassBehaviour( policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"), QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"),
this, this,
new JavaBehaviour(this, "onCreateNode")); new JavaBehaviour(this, "onCreateNode"));
// Create the transaction listener // Create the transaction listener
@@ -349,12 +346,6 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda
{ {
AlfrescoTransactionSupport.bindResource(KEY_WORKING_COPY, nodeRef); AlfrescoTransactionSupport.bindResource(KEY_WORKING_COPY, nodeRef);
} }
// restore removes the "archived" aspect prior to restoring (via delete/move) the node - hence need to track here
if (aspect.equals(ContentModel.ASPECT_ARCHIVED))
{
AlfrescoTransactionSupport.bindResource(KEY_ARCHIVED, nodeRef);
}
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -367,17 +358,10 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda
workingCopy = true; workingCopy = true;
} }
boolean archived = nodeService.hasAspect(nodeRef, ContentModel.ASPECT_ARCHIVED);
NodeRef aNodeRef = (NodeRef)AlfrescoTransactionSupport.getResource(KEY_ARCHIVED);
if ((aNodeRef != null) && (aNodeRef.equals(nodeRef)))
{
archived = true;
}
boolean isVersionNode = nodeRef.getStoreRef().getIdentifier().equals(Version2Model.STORE_ID); boolean isVersionNode = nodeRef.getStoreRef().getIdentifier().equals(Version2Model.STORE_ID);
// Ignore if the node is a working copy, archived or version node // Ignore if the node is a working copy or version node
if (! (workingCopy || archived || isVersionNode)) if (! (workingCopy || isVersionNode))
{ {
QName modelName = (QName)this.nodeService.getProperty(nodeRef, ContentModel.PROP_MODEL_NAME); QName modelName = (QName)this.nodeService.getProperty(nodeRef, ContentModel.PROP_MODEL_NAME);
@@ -407,7 +391,7 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda
{ {
if (logger.isTraceEnabled()) if (logger.isTraceEnabled())
{ {
logger.trace("beforeDeleteNode: nodeRef="+nodeRef+ " ignored ("+(workingCopy ? " workingCopy " : "")+(archived ? " archived " : "")+(isVersionNode ? " isVersionNode " : "")+") ["+AlfrescoTransactionSupport.getTransactionId()+"]"); logger.trace("beforeDeleteNode: nodeRef="+nodeRef+ " ignored ("+(workingCopy ? " workingCopy " : "")+(isVersionNode ? " isVersionNode " : "")+") ["+AlfrescoTransactionSupport.getTransactionId()+"]");
} }
} }
} }
@@ -606,8 +590,8 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda
isActive = value.booleanValue(); isActive = value.booleanValue();
} }
// Ignore if the node is a working copy or archived // Ignore if the node is a working copy
if (! (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) || nodeService.hasAspect(nodeRef, ContentModel.ASPECT_ARCHIVED))) if (! (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)))
{ {
if (isActive == true) if (isActive == true)
{ {

View File

@@ -33,7 +33,6 @@ import org.alfresco.repo.i18n.MessageService;
import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.tenant.TenantAdminService;
import org.alfresco.repo.tenant.TenantDeployer; import org.alfresco.repo.tenant.TenantDeployer;
import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.tenant.TenantService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
@@ -211,6 +210,11 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme
{ {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
if (logger.isTraceEnabled())
{
logger.trace("onDictionaryInit: ["+Thread.currentThread()+"]");
}
Collection<QName> modelsBefore = dictionaryDAO.getModels(); Collection<QName> modelsBefore = dictionaryDAO.getModels();
int modelsBeforeCnt = (modelsBefore != null ? modelsBefore.size() : 0); int modelsBeforeCnt = (modelsBefore != null ? modelsBefore.size() : 0);
@@ -220,6 +224,11 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme
{ {
Map<String, Pair<RepositoryLocation, M2Model>> modelMap = new HashMap<String, Pair<RepositoryLocation, M2Model>>(); Map<String, Pair<RepositoryLocation, M2Model>> modelMap = new HashMap<String, Pair<RepositoryLocation, M2Model>>();
if (logger.isTraceEnabled())
{
logger.trace("onDictionaryInit: locations="+this.repositoryModelsLocations);
}
// Register the models found in the repository // Register the models found in the repository
for (RepositoryLocation repositoryLocation : this.repositoryModelsLocations) for (RepositoryLocation repositoryLocation : this.repositoryModelsLocations)
@@ -289,14 +298,14 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme
if (modelsAfterCnt != (modelsBeforeCnt + loadedModels.size())) if (modelsAfterCnt != (modelsBeforeCnt + loadedModels.size()))
{ {
String tenantDomain = tenantAdminService.getCurrentUserDomain(); String tenantDomain = tenantAdminService.getCurrentUserDomain();
logger.warn("Model count: before="+modelsBeforeCnt+", load="+loadedModels.size()+", after="+modelsAfterCnt+" ["+AlfrescoTransactionSupport.getTransactionId()+"] in "+(System.currentTimeMillis()-startTime)+" msecs "+(tenantDomain.equals(TenantService.DEFAULT_DOMAIN) ? "" : " (Tenant: "+tenantDomain+")")); logger.warn("Model count: before="+modelsBeforeCnt+", load="+loadedModels.size()+", after="+modelsAfterCnt+" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"] "+(tenantDomain.equals(TenantService.DEFAULT_DOMAIN) ? "" : " (Tenant: "+tenantDomain+")"));
} }
else else
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
String tenantDomain = tenantAdminService.getCurrentUserDomain(); String tenantDomain = tenantAdminService.getCurrentUserDomain();
logger.debug("Model count: before="+modelsBeforeCnt+", load="+loadedModels.size()+", after="+modelsAfterCnt+" ["+AlfrescoTransactionSupport.getTransactionId()+"] in "+(System.currentTimeMillis()-startTime)+" msecs "+(tenantDomain.equals(TenantService.DEFAULT_DOMAIN) ? "" : " (Tenant: "+tenantDomain+")")); logger.debug("Model count: before="+modelsBeforeCnt+", load="+loadedModels.size()+", after="+modelsAfterCnt+" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"] "+(tenantDomain.equals(TenantService.DEFAULT_DOMAIN) ? "" : " (Tenant: "+tenantDomain+")"));
} }
} }
} }

View File

@@ -64,6 +64,8 @@ public interface NamespaceDAO extends NamespacePrefixResolver
*/ */
public void init(); public void init();
public void afterDictionaryInit();
/** /**
* Destroy Namespaces * Destroy Namespaces
*/ */

View File

@@ -38,7 +38,7 @@ import org.apache.commons.logging.LogFactory;
/** /**
* Simple in-memory namespace DAO * Simple in-memory namespace DAO
*/ */
public class NamespaceDAOImpl implements NamespaceDAO public class NamespaceDAOImpl implements NamespaceDAO, DictionaryListener
{ {
private static final Log logger = LogFactory.getLog(NamespaceDAOImpl.class); private static final Log logger = LogFactory.getLog(NamespaceDAOImpl.class);
@@ -74,15 +74,78 @@ public class NamespaceDAOImpl implements NamespaceDAO
public void registerDictionary(DictionaryDAO dictionaryDAO) public void registerDictionary(DictionaryDAO dictionaryDAO)
{ {
this.dictionaryDAO = dictionaryDAO; this.dictionaryDAO = dictionaryDAO;
this.dictionaryDAO.register(this);
} }
public void afterDictionaryDestroy()
{
// TODO Auto-generated method stub
}
public void onDictionaryInit()
{
// TODO Auto-generated method stub
}
/**
* Complete the initialisation
*/
public void afterDictionaryInit()
{
String tenantDomain = getTenantDomain();
try
{
NamespaceRegistry namespaceRegistry = getNamespaceRegistryLocal(tenantDomain);
if (namespaceRegistry == null)
{
// unexpected
throw new AlfrescoRuntimeException("Failed to init namespaceRegistry " + tenantDomain);
}
try
{
writeLock.lock();
namespaceRegistryCache.put(tenantDomain, namespaceRegistry);
}
finally
{
writeLock.unlock();
}
}
finally
{
try
{
readLock.lock();
if (namespaceRegistryCache.get(tenantDomain) != null)
{
removeNamespaceLocal(tenantDomain);
}
}
finally
{
readLock.unlock();
}
}
}
/** /**
* Initialise empty namespaces * Initialise empty namespaces
*/ */
public void init() public void init()
{ {
initNamespace(getTenantDomain()); String tenantDomain = getTenantDomain();
NamespaceRegistry namespaceRegistry = initNamespaceRegistry(tenantDomain);
if (namespaceRegistry == null)
{
// unexpected
throw new AlfrescoRuntimeException("Failed to init namespaceRegistry " + tenantDomain);
}
} }
/** /**
@@ -128,60 +191,20 @@ public class NamespaceDAOImpl implements NamespaceDAO
return namespaceRegistry; return namespaceRegistry;
} }
private NamespaceRegistry initNamespace(String tenantDomain)
{
try
{
createNamespaceLocal(tenantDomain);
NamespaceRegistry namespaceRegistry = initNamespaceRegistry(tenantDomain);
if (namespaceRegistry == null)
{
// unexpected
throw new AlfrescoRuntimeException("Failed to init namespaceRegistry " + tenantDomain);
}
try
{
writeLock.lock();
namespaceRegistryCache.put(tenantDomain, namespaceRegistry);
}
finally
{
writeLock.unlock();
}
return namespaceRegistry;
}
finally
{
try
{
readLock.lock();
if (namespaceRegistryCache.get(tenantDomain) != null)
{
removeNamespaceLocal(tenantDomain);
}
}
finally
{
readLock.unlock();
}
}
}
private NamespaceRegistry initNamespaceRegistry(String tenantDomain) private NamespaceRegistry initNamespaceRegistry(String tenantDomain)
{ {
getNamespaceRegistry(tenantDomain).setUrisCache(new ArrayList<String>()); // create threadlocal, if needed
getNamespaceRegistry(tenantDomain).setPrefixesCache(new HashMap<String, String>()); NamespaceRegistry namespaceRegistry = createNamespaceLocal(tenantDomain);
namespaceRegistry.setUrisCache(new ArrayList<String>());
namespaceRegistry.setPrefixesCache(new HashMap<String, String>());
if (logger.isTraceEnabled()) if (logger.isTraceEnabled())
{ {
logger.trace("Empty namespaces initialised"); logger.trace("Empty namespaces initialised: "+namespaceRegistry+" - "+namespaceRegistryThreadLocal+" ["+Thread.currentThread()+"]");
} }
return getNamespaceRegistryLocal(tenantDomain); return namespaceRegistry;
} }
@@ -242,7 +265,7 @@ public class NamespaceDAOImpl implements NamespaceDAO
// overridden, hence skip this default prefix // overridden, hence skip this default prefix
continue; continue;
} }
prefixesFiltered.add(prefix); prefixesFiltered.add(prefix);
} }
// default (non-overridden) + tenant-specific // default (non-overridden) + tenant-specific
@@ -427,7 +450,7 @@ public class NamespaceDAOImpl implements NamespaceDAO
} }
// create threadlocal // create threadlocal
private void createNamespaceLocal(String tenantDomain) private NamespaceRegistry createNamespaceLocal(String tenantDomain)
{ {
// create threadlocal, if needed // create threadlocal, if needed
NamespaceRegistry namespaceRegistry = getNamespaceRegistryLocal(tenantDomain); NamespaceRegistry namespaceRegistry = getNamespaceRegistryLocal(tenantDomain);
@@ -435,17 +458,17 @@ public class NamespaceDAOImpl implements NamespaceDAO
{ {
namespaceRegistry = new NamespaceRegistry(tenantDomain); namespaceRegistry = new NamespaceRegistry(tenantDomain);
if (! tenantDomain.equals(TenantService.DEFAULT_DOMAIN)) if (tenantDomain.equals(TenantService.DEFAULT_DOMAIN))
{
defaultNamespaceRegistryThreadLocal.set(namespaceRegistry);
}
else
{ {
namespaceRegistryThreadLocal.set(namespaceRegistry); namespaceRegistryThreadLocal.set(namespaceRegistry);
} }
if (defaultNamespaceRegistryThreadLocal.get() == null)
{
namespaceRegistry = new NamespaceRegistry(TenantService.DEFAULT_DOMAIN);
defaultNamespaceRegistryThreadLocal.set(namespaceRegistry);
}
} }
return namespaceRegistry;
} }
// get threadlocal // get threadlocal
@@ -466,7 +489,7 @@ public class NamespaceDAOImpl implements NamespaceDAO
if ((namespaceRegistry != null) && (tenantDomain.equals(namespaceRegistry.getTenantDomain()))) if ((namespaceRegistry != null) && (tenantDomain.equals(namespaceRegistry.getTenantDomain())))
{ {
return namespaceRegistry; // return threadlocal, if set return namespaceRegistry; // return threadlocal, if set
} }
return null; return null;
} }

View File

@@ -19,6 +19,7 @@
package org.alfresco.repo.node; package org.alfresco.repo.node;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -52,6 +53,7 @@ import org.alfresco.repo.policy.AssociationPolicyDelegate;
import org.alfresco.repo.policy.ClassPolicyDelegate; import org.alfresco.repo.policy.ClassPolicyDelegate;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.search.Indexer; import org.alfresco.repo.search.Indexer;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.dictionary.ClassDefinition; import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -95,6 +97,8 @@ public abstract class AbstractNodeServiceImpl implements NodeService
private PolicyComponent policyComponent; private PolicyComponent policyComponent;
protected DictionaryService dictionaryService; protected DictionaryService dictionaryService;
protected TransactionService transactionService; protected TransactionService transactionService;
protected TenantService tenantService;
protected List<String> storesToIgnorePolicies = new ArrayList<String>(0);
/* /*
* Policy delegates * Policy delegates
@@ -144,6 +148,16 @@ public abstract class AbstractNodeServiceImpl implements NodeService
{ {
this.transactionService = transactionService; this.transactionService = transactionService;
} }
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
public void setStoresToIgnorePolicies(List<String> storesToIgnorePolicies)
{
this.storesToIgnorePolicies = storesToIgnorePolicies;
}
/** /**
* Checks equality by type and uuid * Checks equality by type and uuid
@@ -203,13 +217,28 @@ public abstract class AbstractNodeServiceImpl implements NodeService
onCreateAssociationDelegate = policyComponent.registerAssociationPolicy(NodeServicePolicies.OnCreateAssociationPolicy.class); onCreateAssociationDelegate = policyComponent.registerAssociationPolicy(NodeServicePolicies.OnCreateAssociationPolicy.class);
onDeleteAssociationDelegate = policyComponent.registerAssociationPolicy(NodeServicePolicies.OnDeleteAssociationPolicy.class); onDeleteAssociationDelegate = policyComponent.registerAssociationPolicy(NodeServicePolicies.OnDeleteAssociationPolicy.class);
} }
private boolean ignorePolicy(StoreRef storeRef)
{
return (storesToIgnorePolicies.contains(tenantService.getBaseName(storeRef).toString()));
}
private boolean ignorePolicy(NodeRef nodeRef)
{
return (storesToIgnorePolicies.contains(tenantService.getBaseName(nodeRef.getStoreRef()).toString()));
}
/** /**
* @see NodeServicePolicies.BeforeCreateStorePolicy#beforeCreateStore(QName, * @see NodeServicePolicies.BeforeCreateStorePolicy#beforeCreateStore(QName,
* StoreRef) * StoreRef)
*/ */
protected void invokeBeforeCreateStore(QName nodeTypeQName, StoreRef storeRef) protected void invokeBeforeCreateStore(QName nodeTypeQName, StoreRef storeRef)
{ {
if (ignorePolicy(storeRef))
{
return;
}
NodeServicePolicies.BeforeCreateStorePolicy policy = this.beforeCreateStoreDelegate.get(nodeTypeQName); NodeServicePolicies.BeforeCreateStorePolicy policy = this.beforeCreateStoreDelegate.get(nodeTypeQName);
policy.beforeCreateStore(nodeTypeQName, storeRef); policy.beforeCreateStore(nodeTypeQName, storeRef);
} }
@@ -219,6 +248,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeOnCreateStore(NodeRef rootNodeRef) protected void invokeOnCreateStore(NodeRef rootNodeRef)
{ {
if (ignorePolicy(rootNodeRef))
{
return;
}
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(rootNodeRef); Set<QName> qnames = getTypeAndAspectQNames(rootNodeRef);
// execute policy for node type and aspects // execute policy for node type and aspects
@@ -232,6 +266,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeBeforeCreateNode(NodeRef parentNodeRef, QName assocTypeQName, QName assocQName, QName childNodeTypeQName) protected void invokeBeforeCreateNode(NodeRef parentNodeRef, QName assocTypeQName, QName assocQName, QName childNodeTypeQName)
{ {
if (ignorePolicy(parentNodeRef))
{
return;
}
// execute policy for node type // execute policy for node type
NodeServicePolicies.BeforeCreateNodePolicy policy = beforeCreateNodeDelegate.get(childNodeTypeQName); NodeServicePolicies.BeforeCreateNodePolicy policy = beforeCreateNodeDelegate.get(childNodeTypeQName);
policy.beforeCreateNode(parentNodeRef, assocTypeQName, assocQName, childNodeTypeQName); policy.beforeCreateNode(parentNodeRef, assocTypeQName, assocQName, childNodeTypeQName);
@@ -243,6 +282,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService
protected void invokeOnCreateNode(ChildAssociationRef childAssocRef) protected void invokeOnCreateNode(ChildAssociationRef childAssocRef)
{ {
NodeRef childNodeRef = childAssocRef.getChildRef(); NodeRef childNodeRef = childAssocRef.getChildRef();
if (ignorePolicy(childNodeRef))
{
return;
}
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(childNodeRef); Set<QName> qnames = getTypeAndAspectQNames(childNodeRef);
// execute policy for node type and aspects // execute policy for node type and aspects
@@ -256,6 +301,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService
protected void invokeOnMoveNode(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef) protected void invokeOnMoveNode(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef)
{ {
NodeRef childNodeRef = newChildAssocRef.getChildRef(); NodeRef childNodeRef = newChildAssocRef.getChildRef();
if (ignorePolicy(childNodeRef))
{
return;
}
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(childNodeRef); Set<QName> qnames = getTypeAndAspectQNames(childNodeRef);
// execute policy for node type and aspects // execute policy for node type and aspects
@@ -268,6 +319,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeBeforeUpdateNode(NodeRef nodeRef) protected void invokeBeforeUpdateNode(NodeRef nodeRef)
{ {
if (ignorePolicy(nodeRef))
{
return;
}
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(nodeRef); Set<QName> qnames = getTypeAndAspectQNames(nodeRef);
// execute policy for node type and aspects // execute policy for node type and aspects
@@ -280,6 +336,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeOnUpdateNode(NodeRef nodeRef) protected void invokeOnUpdateNode(NodeRef nodeRef)
{ {
if (ignorePolicy(nodeRef))
{
return;
}
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(nodeRef); Set<QName> qnames = getTypeAndAspectQNames(nodeRef);
// execute policy for node type and aspects // execute policy for node type and aspects
@@ -295,6 +356,10 @@ public abstract class AbstractNodeServiceImpl implements NodeService
Map<QName, Serializable> before, Map<QName, Serializable> before,
Map<QName, Serializable> after) Map<QName, Serializable> after)
{ {
if (ignorePolicy(nodeRef))
{
return;
}
// Some logging so we can see which properties have been modified // Some logging so we can see which properties have been modified
if (logger.isDebugEnabled() == true) if (logger.isDebugEnabled() == true)
@@ -344,6 +409,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeBeforeDeleteNode(NodeRef nodeRef) protected void invokeBeforeDeleteNode(NodeRef nodeRef)
{ {
if (ignorePolicy(nodeRef))
{
return;
}
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(nodeRef); Set<QName> qnames = getTypeAndAspectQNames(nodeRef);
// execute policy for node type and aspects // execute policy for node type and aspects
@@ -356,14 +426,30 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeOnDeleteNode(ChildAssociationRef childAssocRef, QName childNodeTypeQName, Set<QName> childAspectQnames, boolean isArchivedNode) protected void invokeOnDeleteNode(ChildAssociationRef childAssocRef, QName childNodeTypeQName, Set<QName> childAspectQnames, boolean isArchivedNode)
{ {
// get qnames to invoke against NodeRef childNodeRef = childAssocRef.getChildRef();
Set<QName> qnames = new HashSet<QName>(childAspectQnames.size() + 1);
qnames.addAll(childAspectQnames);
qnames.add(childNodeTypeQName);
// execute policy for node type and aspects Set<QName> qnames = null;
NodeServicePolicies.OnDeleteNodePolicy policy = onDeleteNodeDelegate.get(childAssocRef.getChildRef(), qnames);
policy.onDeleteNode(childAssocRef, isArchivedNode); if (ignorePolicy(childNodeRef))
{
// special case
qnames = new HashSet<QName>(1);
qnames.add(ContentModel.ASPECT_VERSIONABLE);
}
else
{
// get qnames to invoke against
qnames = new HashSet<QName>(childAspectQnames.size() + 1);
qnames.addAll(childAspectQnames);
qnames.add(childNodeTypeQName);
}
if (qnames != null)
{
// execute policy for node type and aspects
NodeServicePolicies.OnDeleteNodePolicy policy = onDeleteNodeDelegate.get(childAssocRef.getChildRef(), qnames);
policy.onDeleteNode(childAssocRef, isArchivedNode);
}
} }
/** /**
@@ -372,6 +458,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeBeforeAddAspect(NodeRef nodeRef, QName aspectTypeQName) protected void invokeBeforeAddAspect(NodeRef nodeRef, QName aspectTypeQName)
{ {
if (ignorePolicy(nodeRef))
{
return;
}
NodeServicePolicies.BeforeAddAspectPolicy policy = beforeAddAspectDelegate.get(nodeRef, aspectTypeQName); NodeServicePolicies.BeforeAddAspectPolicy policy = beforeAddAspectDelegate.get(nodeRef, aspectTypeQName);
policy.beforeAddAspect(nodeRef, aspectTypeQName); policy.beforeAddAspect(nodeRef, aspectTypeQName);
} }
@@ -381,6 +472,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeOnAddAspect(NodeRef nodeRef, QName aspectTypeQName) protected void invokeOnAddAspect(NodeRef nodeRef, QName aspectTypeQName)
{ {
if (ignorePolicy(nodeRef))
{
return;
}
NodeServicePolicies.OnAddAspectPolicy policy = onAddAspectDelegate.get(nodeRef, aspectTypeQName); NodeServicePolicies.OnAddAspectPolicy policy = onAddAspectDelegate.get(nodeRef, aspectTypeQName);
policy.onAddAspect(nodeRef, aspectTypeQName); policy.onAddAspect(nodeRef, aspectTypeQName);
} }
@@ -391,6 +487,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeBeforeRemoveAspect(NodeRef nodeRef, QName aspectTypeQName) protected void invokeBeforeRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
{ {
if (ignorePolicy(nodeRef))
{
return;
}
NodeServicePolicies.BeforeRemoveAspectPolicy policy = beforeRemoveAspectDelegate.get(nodeRef, aspectTypeQName); NodeServicePolicies.BeforeRemoveAspectPolicy policy = beforeRemoveAspectDelegate.get(nodeRef, aspectTypeQName);
policy.beforeRemoveAspect(nodeRef, aspectTypeQName); policy.beforeRemoveAspect(nodeRef, aspectTypeQName);
} }
@@ -401,6 +502,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeOnRemoveAspect(NodeRef nodeRef, QName aspectTypeQName) protected void invokeOnRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
{ {
if (ignorePolicy(nodeRef))
{
return;
}
NodeServicePolicies.OnRemoveAspectPolicy policy = onRemoveAspectDelegate.get(nodeRef, aspectTypeQName); NodeServicePolicies.OnRemoveAspectPolicy policy = onRemoveAspectDelegate.get(nodeRef, aspectTypeQName);
policy.onRemoveAspect(nodeRef, aspectTypeQName); policy.onRemoveAspect(nodeRef, aspectTypeQName);
} }
@@ -411,6 +517,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeBeforeCreateNodeAssociation(NodeRef parentNodeRef, QName assocTypeQName, QName assocQName) protected void invokeBeforeCreateNodeAssociation(NodeRef parentNodeRef, QName assocTypeQName, QName assocQName)
{ {
if (ignorePolicy(parentNodeRef))
{
return;
}
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef); Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef);
// execute policy for node type // execute policy for node type
@@ -425,6 +536,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService
{ {
// Get the parent reference and the assoc type qName // Get the parent reference and the assoc type qName
NodeRef parentNodeRef = childAssocRef.getParentRef(); NodeRef parentNodeRef = childAssocRef.getParentRef();
if (ignorePolicy(parentNodeRef))
{
return;
}
QName assocTypeQName = childAssocRef.getTypeQName(); QName assocTypeQName = childAssocRef.getTypeQName();
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef); Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef);
@@ -439,6 +556,11 @@ public abstract class AbstractNodeServiceImpl implements NodeService
*/ */
protected void invokeBeforeCreateChildAssociation(NodeRef parentNodeRef, NodeRef childNodeRef, QName assocTypeQName, QName assocQName, boolean isNewNode) protected void invokeBeforeCreateChildAssociation(NodeRef parentNodeRef, NodeRef childNodeRef, QName assocTypeQName, QName assocQName, boolean isNewNode)
{ {
if (ignorePolicy(parentNodeRef))
{
return;
}
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef); Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef);
// execute policy for node type // execute policy for node type
@@ -453,6 +575,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService
{ {
// Get the parent reference and the assoc type qName // Get the parent reference and the assoc type qName
NodeRef parentNodeRef = childAssocRef.getParentRef(); NodeRef parentNodeRef = childAssocRef.getParentRef();
if (ignorePolicy(parentNodeRef))
{
return;
}
QName assocTypeQName = childAssocRef.getTypeQName(); QName assocTypeQName = childAssocRef.getTypeQName();
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef); Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef);
@@ -467,6 +595,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService
protected void invokeBeforeDeleteChildAssociation(ChildAssociationRef childAssocRef) protected void invokeBeforeDeleteChildAssociation(ChildAssociationRef childAssocRef)
{ {
NodeRef parentNodeRef = childAssocRef.getParentRef(); NodeRef parentNodeRef = childAssocRef.getParentRef();
if (ignorePolicy(parentNodeRef))
{
return;
}
QName assocTypeQName = childAssocRef.getTypeQName(); QName assocTypeQName = childAssocRef.getTypeQName();
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef); Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef);
@@ -481,6 +615,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService
protected void invokeOnDeleteChildAssociation(ChildAssociationRef childAssocRef) protected void invokeOnDeleteChildAssociation(ChildAssociationRef childAssocRef)
{ {
NodeRef parentNodeRef = childAssocRef.getParentRef(); NodeRef parentNodeRef = childAssocRef.getParentRef();
if (ignorePolicy(parentNodeRef))
{
return;
}
QName assocTypeQName = childAssocRef.getTypeQName(); QName assocTypeQName = childAssocRef.getTypeQName();
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef); Set<QName> qnames = getTypeAndAspectQNames(parentNodeRef);
@@ -495,6 +635,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService
protected void invokeOnCreateAssociation(AssociationRef nodeAssocRef) protected void invokeOnCreateAssociation(AssociationRef nodeAssocRef)
{ {
NodeRef sourceNodeRef = nodeAssocRef.getSourceRef(); NodeRef sourceNodeRef = nodeAssocRef.getSourceRef();
if (ignorePolicy(sourceNodeRef))
{
return;
}
QName assocTypeQName = nodeAssocRef.getTypeQName(); QName assocTypeQName = nodeAssocRef.getTypeQName();
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(sourceNodeRef); Set<QName> qnames = getTypeAndAspectQNames(sourceNodeRef);
@@ -509,6 +655,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService
protected void invokeOnDeleteAssociation(AssociationRef nodeAssocRef) protected void invokeOnDeleteAssociation(AssociationRef nodeAssocRef)
{ {
NodeRef sourceNodeRef = nodeAssocRef.getSourceRef(); NodeRef sourceNodeRef = nodeAssocRef.getSourceRef();
if (ignorePolicy(sourceNodeRef))
{
return;
}
QName assocTypeQName = nodeAssocRef.getTypeQName(); QName assocTypeQName = nodeAssocRef.getTypeQName();
// get qnames to invoke against // get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(sourceNodeRef); Set<QName> qnames = getTypeAndAspectQNames(sourceNodeRef);

View File

@@ -149,6 +149,8 @@ public class MultiTDemoTest extends TestCase
repoAdminService = (RepoAdminService) ctx.getBean("RepoAdminService"); repoAdminService = (RepoAdminService) ctx.getBean("RepoAdminService");
dictionaryService = (DictionaryService) ctx.getBean("DictionaryService"); dictionaryService = (DictionaryService) ctx.getBean("DictionaryService");
usageService = (UsageService) ctx.getBean("usageService"); usageService = (UsageService) ctx.getBean("usageService");
createTenants();
} }
@Override @Override
@@ -157,6 +159,51 @@ public class MultiTDemoTest extends TestCase
super.tearDown(); super.tearDown();
} }
private void createTenants()
{
for (final String tenantDomain : tenants)
{
createTenant(tenantDomain);
}
}
public void testCreateTenants() throws Throwable
{
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); // authenticate as super-admin
logger.info("Create tenants");
Set<NodeRef> personRefs = personService.getAllPeople();
//assertEquals(2, personRefs.size()); // super-tenant: admin, guest (note: checking for 2 assumes that this test is run in a fresh bootstrap env)
for (NodeRef personRef : personRefs)
{
String userName = (String)nodeService.getProperty(personRef, ContentModel.PROP_USERNAME);
for (final String tenantDomain : tenants)
{
assertFalse("Unexpected (tenant) user: "+userName, userName.endsWith(tenantDomain));
}
}
}
private void createTenant(final String tenantDomain)
{
// create tenants (if not already created)
AuthenticationUtil.runAs(new RunAsWork<Object>()
{
public Object doWork() throws Exception
{
if (! tenantAdminService.existsTenant(tenantDomain))
{
//tenantAdminService.createTenant(tenantDomain, DEFAULT_ADMIN_PW.toCharArray(), ROOT_DIR + "/" + tenantDomain);
tenantAdminService.createTenant(tenantDomain, (DEFAULT_ADMIN_PW+" "+tenantDomain).toCharArray(), null); // use default root dir
logger.info("Created tenant " + tenantDomain);
}
return null;
}
}, AuthenticationUtil.getSystemUserName());
}
public void test_ETHREEOH_2015() public void test_ETHREEOH_2015()
{ {
@@ -192,58 +239,6 @@ public class MultiTDemoTest extends TestCase
usageService.deleteDeltas(personNodeRef); usageService.deleteDeltas(personNodeRef);
} }
public void testCreateTenants() throws Throwable
{
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); // authenticate as super-admin
logger.info("Create tenants");
Set<NodeRef> personRefs = personService.getAllPeople();
//assertEquals(2, personRefs.size()); // super-tenant: admin, guest (note: checking for 2 assumes that this test is run in a fresh bootstrap env)
for (NodeRef personRef : personRefs)
{
String userName = (String)nodeService.getProperty(personRef, ContentModel.PROP_USERNAME);
for (final String tenantDomain : tenants)
{
assertFalse("Unexpected (tenant) user: "+userName, userName.endsWith(tenantDomain));
}
}
try
{
for (final String tenantDomain : tenants)
{
createTenant(tenantDomain);
}
}
catch (Throwable t)
{
StringWriter stackTrace = new StringWriter();
t.printStackTrace(new PrintWriter(stackTrace));
System.err.println(stackTrace.toString());
throw t;
}
}
private void createTenant(final String tenantDomain)
{
// create tenants (if not already created)
AuthenticationUtil.runAs(new RunAsWork<Object>()
{
public Object doWork() throws Exception
{
if (! tenantAdminService.existsTenant(tenantDomain))
{
//tenantAdminService.createTenant(tenantDomain, DEFAULT_ADMIN_PW.toCharArray(), ROOT_DIR + "/" + tenantDomain);
tenantAdminService.createTenant(tenantDomain, (DEFAULT_ADMIN_PW+" "+tenantDomain).toCharArray(), null); // use default root dir
logger.info("Created tenant " + tenantDomain);
}
return null;
}
}, AuthenticationUtil.getSystemUserName());
}
public void testCreateUsers() throws Throwable public void testCreateUsers() throws Throwable
{ {