diff --git a/source/java/org/alfresco/repo/virtual/AlfrescoEnviroment.java b/source/java/org/alfresco/repo/virtual/AlfrescoEnviroment.java index 22d71a2d60..38b802f36e 100644 --- a/source/java/org/alfresco/repo/virtual/AlfrescoEnviroment.java +++ b/source/java/org/alfresco/repo/virtual/AlfrescoEnviroment.java @@ -29,7 +29,6 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.jscript.ClasspathScriptLocation; import org.alfresco.repo.model.Repository; import org.alfresco.repo.virtual.config.NodeRefResolver; -import org.alfresco.repo.virtual.ref.Reference; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.InvalidAspectException; import org.alfresco.service.cmr.dictionary.InvalidTypeException; @@ -79,6 +78,11 @@ public class AlfrescoEnviroment implements ActualEnvironment this.serviceRegistry = serviceRegistry; } + public ServiceRegistry getServiceRegistry() + { + return this.serviceRegistry; + } + public void setRepositoryHelper(Repository repository) { this.repositoryHelper = repository; diff --git a/source/java/org/alfresco/repo/virtual/ref/Reference.java b/source/java/org/alfresco/repo/virtual/ref/Reference.java index bc10d31cd0..98ab977426 100644 --- a/source/java/org/alfresco/repo/virtual/ref/Reference.java +++ b/source/java/org/alfresco/repo/virtual/ref/Reference.java @@ -136,23 +136,23 @@ public class Reference } } - // Average reference length DEBUG trace + // Average reference length log trace - private static long _debug_refLength = 0; + private static long _trace_refLength = 0; - private static long _debug_refCount = 0; + private static long _trace_refCount = 0; - private static final long _debug_refBatchSize = 256; + private static final long _trace_refBatchSize = 4096*2; - private static synchronized void debug_avg_ref_length(long refLength) + private static synchronized void _trace_avg_ref_length(long refLength) { - _debug_refLength += refLength; - _debug_refCount++; - if (_debug_refBatchSize > 0 && _debug_refCount % _debug_refBatchSize == 0) + _trace_refLength += refLength; + _trace_refCount++; + if (_trace_refBatchSize > 0 && _trace_refCount % _trace_refBatchSize == 0) { - logger.debug("Average reference encoding size : " + (_debug_refLength / _debug_refCount)); - _debug_refCount = 0; - _debug_refLength = 0; + logger.trace("Average reference encoding size : " + (_trace_refLength / _trace_refCount)); + _trace_refCount = 0; + _trace_refLength = 0; } } @@ -281,9 +281,9 @@ public class Reference NodeRef theNode = new NodeRef(storeRef, idBuilder.toString()); - if (logger.isDebugEnabled()) + if (logger.isTraceEnabled()) { - debug_avg_ref_length(theNode.toString().length()); + _trace_avg_ref_length(theNode.toString().length()); } return theNode; diff --git a/source/java/org/alfresco/repo/virtual/store/VirtualStoreImpl.java b/source/java/org/alfresco/repo/virtual/store/VirtualStoreImpl.java index d11da81ae0..2ba943369e 100644 --- a/source/java/org/alfresco/repo/virtual/store/VirtualStoreImpl.java +++ b/source/java/org/alfresco/repo/virtual/store/VirtualStoreImpl.java @@ -38,8 +38,11 @@ import org.alfresco.query.PagingResults; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.NodePermissionEntry; import org.alfresco.repo.security.permissions.PermissionReference; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.repo.virtual.ActualEnvironment; +import org.alfresco.repo.virtual.AlfrescoEnviroment; import org.alfresco.repo.virtual.VirtualContentModel; import org.alfresco.repo.virtual.VirtualizationException; import org.alfresco.repo.virtual.page.PageCollationException; @@ -68,6 +71,7 @@ import org.alfresco.repo.virtual.template.PropertyValueConstraint; import org.alfresco.repo.virtual.template.VirtualFolderDefinition; import org.alfresco.repo.virtual.template.VirtualQuery; import org.alfresco.repo.virtual.template.VirtualQueryConstraint; +import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; @@ -82,9 +86,13 @@ import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QNamePattern; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.util.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionResolver { + private static Log logger = LogFactory.getLog(VirtualStoreImpl.class); + private static final String VIRTUAL_FOLDER_DEFINITION = "virtualfolder.definition"; private List virtualizationMethods = null; @@ -121,6 +129,20 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe @Override public boolean canVirtualize(NodeRef nodeRef) throws VirtualizationException { + String runAsUser = AuthenticationUtil.getRunAsUser(); + if (runAsUser == null) + { + if (logger.isTraceEnabled()) + { + + RuntimeException stackTracingException = new RuntimeException("Stack trace."); + logger.trace("Virtualization check call in unauthenticated-context - stack trace follows:", + stackTracingException); + } + + return false; + } + if (Reference.isReference(nodeRef)) { return true; @@ -156,8 +178,8 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe } } - private NodeRef nodeProtocolNodeRef(NodeRef nodeRef) - throws ProtocolMethodException, ReferenceParseException, ReferenceEncodingException + private NodeRef nodeProtocolNodeRef(NodeRef nodeRef) throws ProtocolMethodException, ReferenceParseException, + ReferenceEncodingException { NodeRef theNodeRef = nodeRef; if (Reference.isReference(nodeRef)) @@ -373,23 +395,40 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe return childReferences; } - public VirtualFolderDefinition resolveVirtualFolderDefinition(Reference reference) throws ProtocolMethodException + public VirtualFolderDefinition resolveVirtualFolderDefinition(final Reference reference) + throws VirtualizationException { - NodeRef key = reference.toNodeRef(); - Map definitionsCache = TransactionalResourceHelper - .getMap(VIRTUAL_FOLDER_DEFINITION); + ServiceRegistry serviceRegistry = ((AlfrescoEnviroment) environment).getServiceRegistry(); + RetryingTransactionHelper transactionHelper = serviceRegistry.getRetryingTransactionHelper(); - VirtualFolderDefinition virtualFolderDefinition = definitionsCache.get(key); + return transactionHelper.doInTransaction(new RetryingTransactionCallback() + { - if (virtualFolderDefinition == null) - { + @Override + public VirtualFolderDefinition execute() throws Throwable + { + NodeRef key = reference.toNodeRef(); - virtualFolderDefinition = reference.execute(new ApplyTemplateMethod(environment)); - definitionsCache.put(key, - virtualFolderDefinition); - } + Map definitionsCache = TransactionalResourceHelper + .getMap(VIRTUAL_FOLDER_DEFINITION); - return virtualFolderDefinition; + VirtualFolderDefinition virtualFolderDefinition = definitionsCache + .get(key); + + if (virtualFolderDefinition == null) + { + + virtualFolderDefinition = reference + .execute(new ApplyTemplateMethod(environment)); + definitionsCache.put(key, + virtualFolderDefinition); + } + + return virtualFolderDefinition; + } + }, + true, + false); } @Override @@ -397,7 +436,7 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe final boolean folders, final String pattern, final Set searchTypeQNames, final Set ignoreTypeQNames, final Set ignoreAspectQNames, final List> sortProps, final PagingRequest pagingRequest) - throws VirtualizationException + throws VirtualizationException { VirtualFolderDefinition structure = resolveVirtualFolderDefinition(ref); @@ -471,8 +510,8 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe } @Override - public PagingResults list(Reference ref, boolean actual, boolean virtual, boolean files, boolean folders, - String pattern, Set ignoreTypeQNames, Set ignoreAspectQNames, + public PagingResults list(Reference ref, boolean actual, boolean virtual, boolean files, + boolean folders, String pattern, Set ignoreTypeQNames, Set ignoreAspectQNames, List> sortProps, PagingRequest pagingRequest) throws VirtualizationException { return list(ref, diff --git a/source/test-java/org/alfresco/repo/virtual/VirtualizationIntegrationTest.java b/source/test-java/org/alfresco/repo/virtual/VirtualizationIntegrationTest.java index a7f0103359..9cb2c99c7e 100644 --- a/source/test-java/org/alfresco/repo/virtual/VirtualizationIntegrationTest.java +++ b/source/test-java/org/alfresco/repo/virtual/VirtualizationIntegrationTest.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import javax.transaction.Status; import javax.transaction.UserTransaction; import junit.framework.TestCase; @@ -59,10 +60,12 @@ import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; import org.alfresco.traitextender.SpringExtensionBundle; import org.alfresco.util.ApplicationContextHelper; +import org.alfresco.util.transaction.TransactionSupportUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Ignore; import org.springframework.context.ApplicationContext; +import org.springframework.transaction.support.TransactionSynchronizationManager; @Ignore public abstract class VirtualizationIntegrationTest extends TestCase implements VirtualizationTest @@ -149,11 +152,15 @@ public abstract class VirtualizationIntegrationTest extends TestCase implements protected NodeRef rootNodeRef; + protected NodeRef companyHomeNodeRef; + protected ActualEnvironment environment; protected TypeAndAspectsFormProcessor typeAndAspectsFormProcessor; - private UserTransaction txn; + protected String txnTamperHint; + + protected UserTransaction txn; protected AuthenticationComponent authenticationComponent; @@ -179,7 +186,7 @@ public abstract class VirtualizationIntegrationTest extends TestCase implements contentService = serviceRegistry.getContentService(); fileAndFolderService = serviceRegistry.getFileFolderService(); permissionService = serviceRegistry.getPermissionService(); - searchService=serviceRegistry.getSearchService(); + searchService = serviceRegistry.getSearchService(); authenticationComponent = ctx.getBean("authenticationComponent", AuthenticationComponent.class); @@ -215,8 +222,8 @@ public abstract class VirtualizationIntegrationTest extends TestCase implements txn.begin(); AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - NodeRef root = repository.getCompanyHome(); - testRootFolder = fileAndFolderService.create(root, + companyHomeNodeRef = repository.getCompanyHome(); + testRootFolder = fileAndFolderService.create(companyHomeNodeRef, TEST_ROOT_FOLDER_NAME, ContentModel.TYPE_FOLDER); @@ -243,7 +250,17 @@ public abstract class VirtualizationIntegrationTest extends TestCase implements configuredTemplatesClassPath = null; } authenticationComponent.clearCurrentSecurityContext(); - txn.rollback(); + try + { + txn.rollback(); + } + catch (Exception e) + { + logger.error("Test tear down failed. Has the test setup transaction been tempered with ? Hint : " + + txnTamperHint, + e); + } + super.tearDown(); } diff --git a/source/test-java/org/alfresco/repo/virtual/store/VirtualStoreImplTest.java b/source/test-java/org/alfresco/repo/virtual/store/VirtualStoreImplTest.java index d4c379192e..43fda186ed 100644 --- a/source/test-java/org/alfresco/repo/virtual/store/VirtualStoreImplTest.java +++ b/source/test-java/org/alfresco/repo/virtual/store/VirtualStoreImplTest.java @@ -19,8 +19,18 @@ package org.alfresco.repo.virtual.store; -import org.alfresco.repo.virtual.VirtualizationIntegrationTest; +import java.nio.charset.StandardCharsets; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.virtual.VirtualizationException; +import org.alfresco.repo.virtual.VirtualizationIntegrationTest; +import org.alfresco.repo.virtual.ref.Protocols; +import org.alfresco.repo.virtual.ref.Reference; +import org.alfresco.repo.virtual.ref.VanillaProtocol; +import org.alfresco.repo.virtual.ref.VirtualProtocol; +import org.alfresco.repo.virtual.template.ApplyTemplateMethodTest; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; @@ -44,6 +54,69 @@ public class VirtualStoreImplTest extends VirtualizationIntegrationTest } + public void testResolveVirtualFolderDefinition_inactiveSynchronization() throws Exception + { + txnTamperHint = "VirtualStoreImplTest::testResolveVirtualFolderDefinition_inactiveSynchronization"; + txn.rollback(); + NodeRef ntVirtualizedFolder = null; + NodeRef jsonTemplateContent = null; + try + { + final String templateName = "template1.json"; + jsonTemplateContent = nodeService.getChildByName(companyHomeNodeRef, + ContentModel.ASSOC_CONTAINS, + templateName); + if (jsonTemplateContent == null) + { + ChildAssociationRef templateChild = createContent(companyHomeNodeRef, + templateName, + ApplyTemplateMethodTest.class + .getResourceAsStream(TEST_TEMPLATE_1_JSON_NAME), + MimetypeMap.MIMETYPE_JSON, + StandardCharsets.UTF_8.name()); + jsonTemplateContent = templateChild.getChildRef(); + } + + final String folderName = "testCanVirtualize_nonTransactional"; + ntVirtualizedFolder = nodeService.getChildByName(companyHomeNodeRef, + ContentModel.ASSOC_CONTAINS, + folderName); + if (ntVirtualizedFolder == null) + { + ChildAssociationRef folderChild = createFolder(companyHomeNodeRef, + folderName); + ntVirtualizedFolder = folderChild.getChildRef(); + } + + Reference aVanillaRef = ((VanillaProtocol) Protocols.VANILLA.protocol) + .newReference(VANILLA_PROCESSOR_JS_CLASSPATH, + "/1", + ntVirtualizedFolder, + jsonTemplateContent); + + // We use transactional-synchronized resources for caching. In + // non-transactional contexts they might not be available. + virtualStore.resolveVirtualFolderDefinition(aVanillaRef); + + } + finally + { + + txn = transactionService.getUserTransaction(); + txn.begin(); + if (ntVirtualizedFolder != null) + { + nodeService.deleteNode(ntVirtualizedFolder); + } + + if (jsonTemplateContent != null) + { + nodeService.deleteNode(jsonTemplateContent); + } + txn.commit(); + } + } + @Test public void testNonVirtualizable() throws Exception { @@ -71,46 +144,77 @@ public class VirtualStoreImplTest extends VirtualizationIntegrationTest assertEquals(false, canVirtualize); } - + private String asTypedPermission(String perm) { - return virtualStore.getUserPermissions().getPermissionTypeQName()+"."+perm; + return virtualStore.getUserPermissions().getPermissionTypeQName() + "." + perm; } - - private void assertHasQueryNodePermission(AccessStatus accessStatus,String perm) + + private void assertHasQueryNodePermission(AccessStatus accessStatus, String perm) { VirtualUserPermissions virtualUserPermissions = virtualStore.getUserPermissions(); - - assertEquals(AccessStatus.DENIED,virtualUserPermissions.hasQueryNodePermission(perm)); - assertEquals(AccessStatus.DENIED,virtualUserPermissions.hasQueryNodePermission(asTypedPermission(perm))); + + assertEquals(AccessStatus.DENIED, + virtualUserPermissions.hasQueryNodePermission(perm)); + assertEquals(AccessStatus.DENIED, + virtualUserPermissions.hasQueryNodePermission(asTypedPermission(perm))); } - - private void assertHasVirtualNodePermission(AccessStatus accessStatus,String perm,boolean readonly) + + private void assertHasVirtualNodePermission(AccessStatus accessStatus, String perm, boolean readonly) { VirtualUserPermissions virtualUserPermissions = virtualStore.getUserPermissions(); - - assertEquals(AccessStatus.DENIED,virtualUserPermissions.hasVirtualNodePermission(perm,readonly)); - assertEquals(AccessStatus.DENIED,virtualUserPermissions.hasVirtualNodePermission(asTypedPermission(perm),readonly)); + + assertEquals(AccessStatus.DENIED, + virtualUserPermissions.hasVirtualNodePermission(perm, + readonly)); + assertEquals(AccessStatus.DENIED, + virtualUserPermissions.hasVirtualNodePermission(asTypedPermission(perm), + readonly)); } - + @Test public void testConfiguredUserPermissions() throws Exception { - assertHasQueryNodePermission(AccessStatus.DENIED,PermissionService.DELETE); - assertHasQueryNodePermission(AccessStatus.DENIED,PermissionService.DELETE_NODE); - assertHasQueryNodePermission(AccessStatus.DENIED,PermissionService.CHANGE_PERMISSIONS); + assertHasQueryNodePermission(AccessStatus.DENIED, + PermissionService.DELETE); + assertHasQueryNodePermission(AccessStatus.DENIED, + PermissionService.DELETE_NODE); + assertHasQueryNodePermission(AccessStatus.DENIED, + PermissionService.CHANGE_PERMISSIONS); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.CREATE_ASSOCIATIONS,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.UNLOCK,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.CANCEL_CHECK_OUT,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.DELETE,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.DELETE_NODE,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.CHANGE_PERMISSIONS,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE_CONTENT,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE_PROPERTIES,true); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE,false); - assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE_PROPERTIES,false); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.CREATE_ASSOCIATIONS, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.UNLOCK, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.CANCEL_CHECK_OUT, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.DELETE, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.DELETE_NODE, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.CHANGE_PERMISSIONS, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.WRITE_CONTENT, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.WRITE, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.WRITE_PROPERTIES, + true); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.WRITE, + false); + assertHasVirtualNodePermission(AccessStatus.DENIED, + PermissionService.WRITE_PROPERTIES, + false); } }