diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties index 73c9cf4df0..5f4507cad3 100644 --- a/config/alfresco/messages/patch-service.properties +++ b/config/alfresco/messages/patch-service.properties @@ -182,3 +182,6 @@ patch.emailContributorGroup.description=Adds the 'GROUP_EMAIL_CONTRIBUTORS' grou patch.avmStoreAsIdentifier.description=Reindex wca:webfolder to make wca:avmstore an identifier patch.avmStoreAsIdentifier.result=Reindexed wca:webfolder to make wca:avmstore an identifier + +patch.avmFormPropertyIdentifier.description=Reindex wca:webform to make wca:formname an identifier +patch.avmFormPropertyIdentifier.result=Reindexed wca:webform to make wca:formname an identifier diff --git a/config/alfresco/model/wcmAppModel.xml b/config/alfresco/model/wcmAppModel.xml index 79060bd386..1c127c7a70 100644 --- a/config/alfresco/model/wcmAppModel.xml +++ b/config/alfresco/model/wcmAppModel.xml @@ -110,11 +110,11 @@ d:text - true + true d:text - true + true @@ -125,7 +125,12 @@ d:text - true + true + + true + false + false + @@ -164,7 +169,7 @@ d:text - true + true @@ -178,7 +183,7 @@ d:text - true + true d:content @@ -203,7 +208,7 @@ Mimetype for generated assets d:text - true + true @@ -223,22 +228,22 @@ Server Deployed To d:text - true + true Snapshot Version Deployed d:int - true + true Time Deploy Started d:datetime - true + true Time Deploy Finished d:datetime - true + true Deployment Successful @@ -284,12 +289,12 @@ Schema Root Element Name d:text - true + true Schema d:noderef - true + true @@ -325,15 +330,15 @@ A Rendering Engine - + Type d:text - true + true Form Source d:noderef - true + true @@ -359,7 +364,7 @@ Form that generated this asset d:text - true + true The original parent path when this form instance data was created - used for regenerating accurately. @@ -381,17 +386,17 @@ Form data renderer that generated this asset d:noderef - true + true Rendition properties used for this rendition d:noderef - true + true Primary XML Asset used to generate this asset d:text - true + true @@ -402,7 +407,7 @@ Expiration Date d:datetime - true + true diff --git a/config/alfresco/network-protocol-context.xml b/config/alfresco/network-protocol-context.xml index d50f1052bd..7818434ac1 100644 --- a/config/alfresco/network-protocol-context.xml +++ b/config/alfresco/network-protocol-context.xml @@ -94,6 +94,7 @@ + diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index 6275310464..34813884bf 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -1109,5 +1109,19 @@ + + + patch.avmFormPropertyIdentifier + patch.avmFormPropertyIdentifier.description + 0 + 111 + 112 + + + + + + + diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index c21f54b95a..5c6fd6afd0 100644 --- a/config/alfresco/version.properties +++ b/config/alfresco/version.properties @@ -19,4 +19,4 @@ version.build=@build-number@ # Schema number -version.schema=111 +version.schema=112 diff --git a/source/java/org/alfresco/filesys/avm/AVMContext.java b/source/java/org/alfresco/filesys/avm/AVMContext.java index 2224685ace..5f8c7405e0 100644 --- a/source/java/org/alfresco/filesys/avm/AVMContext.java +++ b/source/java/org/alfresco/filesys/avm/AVMContext.java @@ -38,7 +38,7 @@ import org.alfresco.repo.avm.CreateVersionCallback; import org.alfresco.repo.avm.PurgeStoreCallback; import org.alfresco.repo.avm.PurgeVersionCallback; import org.alfresco.repo.domain.PropertyValue; -import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.sandbox.SandboxConstants; import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -63,10 +63,12 @@ public class AVMContext extends AlfrescoContext public static final int VERSION_HEAD = -1; - // Store properties + // Store types to show in the virtualization view - public static QName PROP_WORKFLOWPREVIEW = QName.createQName(NamespaceService.DEFAULT_URI, ".sandbox.workflow.preview"); - public static QName PROP_AUTHORPREVIEW = QName.createQName(NamespaceService.DEFAULT_URI, ".sandbox.author.preview"); + public static final int ShowNormalStores = 0x0001; + public static final int ShowStagingStores = 0x0002; + public static final int ShowAuthorStores = 0x0004; + public static final int ShowPreviewStores = 0x0008; // Store, root path and version @@ -80,13 +82,13 @@ public class AVMContext extends AlfrescoContext private boolean m_virtualView; - // Show sandboxes in the virtualization view - - private boolean m_showSandboxes = false; - - // associated AVM filesystem driver + // Associated AVM filesystem driver private AVMDiskDriver m_avmDriver; + + // Virtualization view filtering options + + private int m_showOptions; /** * Class constructor @@ -118,17 +120,17 @@ public class AVMContext extends AlfrescoContext *

Construct a context for a virtualization view onto all stores/versions within AVM. * * @param filesysName String - * @param showSandboxes boolean + * @param showOptions int * @param avmDriver AVMDiskDriver */ - public AVMContext( String filesysName, boolean showSandboxes, AVMDiskDriver avmDriver) + public AVMContext( String filesysName, int showOptions, AVMDiskDriver avmDriver) { super( filesysName, "VirtualView"); // Enable the virtualization view m_virtualView = true; - m_showSandboxes = showSandboxes; + m_showOptions = showOptions; // Save the associated filesystem driver @@ -176,15 +178,74 @@ public class AVMContext extends AlfrescoContext } /** - * Check if sandboxes should be shown in the virtualization view + * Check if normal stores should be shown in the virtualization view * * @return boolean */ - public final boolean showSandboxes() + public final boolean showNormalStores() { - return m_showSandboxes; + return (m_showOptions & ShowNormalStores) != 0 ? true : false; } + /** + * Check if author stores should be shown in the virtualization view + * + * @return boolean + */ + public final boolean showAuthorStores() + { + return (m_showOptions & ShowAuthorStores) != 0 ? true : false; + } + + /** + * Check if preview stores should be shown in the virtualization view + * + * @return boolean + */ + public final boolean showPreviewStores() + { + return (m_showOptions & ShowPreviewStores) != 0 ? true : false; + } + + /** + * Check if staging stores should be shown in the virtualization view + * + * @return boolean + */ + public final boolean showStagingStores() + { + return (m_showOptions & ShowStagingStores) != 0 ? true : false; + } + + /** + * Check if the specified store type should be visible + * + * @param storeType int + * @return boolean + */ + public final boolean showStoreType(int storeType) + { + boolean showStore = false; + + switch ( storeType) + { + case StoreType.Normal: + showStore = showNormalStores(); + break; + case StoreType.WebAuthorMain: + showStore = showAuthorStores(); + break; + case StoreType.WebStagingMain: + showStore = showStagingStores(); + break; + case StoreType.WebAuthorPreview: + case StoreType.WebStagingPreview: + showStore = showPreviewStores(); + break; + } + + return showStore; + } /** * Close the filesystem context */ @@ -226,43 +287,10 @@ public class AVMContext extends AlfrescoContext if ( rootState != null) { - // Get the properties for the new store - - boolean sandbox = false; - Map props = m_avmDriver.getAVMStoreProperties( storeName); - - if ( props.containsKey( PROP_WORKFLOWPREVIEW) || props.containsKey( PROP_AUTHORPREVIEW)) - sandbox = true; - - // Add a pseudo file for the current store - - if ( sandbox == false || showSandboxes() == true) - { - // Add a pseudo folder for the new store - - rootState.addPseudoFile( new StorePseudoFile( storeName, FileName.DOS_SEPERATOR_STR + storeName)); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug( "Added pseudo folder for new store " + storeName); - - // Send a change notification for the new folder - - if ( hasChangeHandler()) - { - // Build the filesystem relative path to the new store folder - - StringBuilder str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( storeName); - - // Send the change notification - - getChangeHandler().notifyDirectoryChanged(NotifyChange.ActionAdded, str.toString()); - } - } + // Delete the root folder file state and recreate it + + fsTable.removeFileState( FileName.DOS_SEPERATOR_STR); +// m_avmDriver.findPseudoState( new AVMPath( ""), this); } } @@ -306,6 +334,10 @@ public class AVMContext extends AlfrescoContext if ( logger.isDebugEnabled()) logger.debug( "Removed pseudo folder for purged store " + storeName); + // Update the file state modify time + + rootState.setLastUpdated( System.currentTimeMillis()); + // Send a change notification for the deleted folder if ( hasChangeHandler()) diff --git a/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java b/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java index ff70a0dc35..157e5be158 100644 --- a/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java +++ b/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java @@ -25,6 +25,7 @@ package org.alfresco.filesys.avm; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -36,6 +37,7 @@ import javax.transaction.UserTransaction; import org.alfresco.config.ConfigElement; import org.alfresco.filesys.alfresco.AlfrescoDiskDriver; import org.alfresco.filesys.server.SrvSession; +import org.alfresco.filesys.server.auth.ClientInfo; import org.alfresco.filesys.server.core.DeviceContext; import org.alfresco.filesys.server.core.DeviceContextException; import org.alfresco.filesys.server.core.DeviceInterface; @@ -58,12 +60,14 @@ import org.alfresco.filesys.server.pseudo.PseudoFolderNetworkFile; import org.alfresco.filesys.server.state.FileState; import org.alfresco.filesys.util.StringList; import org.alfresco.filesys.util.WildCard; +import org.alfresco.model.WCMAppModel; import org.alfresco.repo.avm.CreateStoreTxnListener; import org.alfresco.repo.avm.CreateVersionTxnListener; import org.alfresco.repo.avm.PurgeStoreTxnListener; import org.alfresco.repo.avm.PurgeVersionTxnListener; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.sandbox.SandboxConstants; import org.alfresco.service.cmr.avm.AVMBadArgumentException; import org.alfresco.service.cmr.avm.AVMExistsException; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; @@ -73,9 +77,17 @@ import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.avm.AVMWrongTypeException; import org.alfresco.service.cmr.avm.VersionDescriptor; import org.alfresco.service.cmr.avm.locking.AVMLockingException; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.MimetypeService; +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.ResultSet; +import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.transaction.TransactionService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -97,39 +109,44 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Configuration key names private static final String KEY_STORE = "storePath"; - private static final String KEY_VERSION = "version"; - private static final String KEY_CREATE = "createStore"; // AVM path seperator public static final char AVM_SEPERATOR = '/'; - public static final String AVM_SEPERATOR_STR = "/"; + // Define client role names + + public static final String RoleContentManager = "ContentManager"; + public static final String RoleWebProject = "WebProject"; + public static final String RoleNotWebAuthor = "NotWebAuthor"; + + // Content manager web project role + + private static final String ROLE_CONTENT_MANAGER = "ContentManager"; + // Services and helpers private AVMService m_avmService; - private TransactionService m_transactionService; - private MimetypeService m_mimetypeService; - private AuthenticationComponent m_authComponent; - private AuthenticationService m_authService; + private NodeService m_nodeService; // AVM listeners private CreateStoreTxnListener m_createStoreListener; - private PurgeStoreTxnListener m_purgeStoreListener; - private CreateVersionTxnListener m_createVerListener; - private PurgeVersionTxnListener m_purgeVerListener; + // Web project store + + private String m_webProjectStore; + /** * Default constructor */ @@ -222,6 +239,16 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface m_mimetypeService = mimetypeService; } + /** + * Set the node service + * + * @param nodeService NodeService + */ + public void setNodeService(NodeService nodeService) + { + m_nodeService = nodeService; + } + /** * Set the create store listener * @@ -266,6 +293,16 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface m_purgeVerListener = purgeVersionListener; } + /** + * Set the web project store + * + * @param webStore String + */ + public void setWebProjectStore(String webStore) + { + m_webProjectStore = webStore; + } + /** * Parse and validate the parameter string and create a device context object for this instance of the shared * device. @@ -307,13 +344,48 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface ConfigElement virtElem = cfg.getChild("virtualView"); if (virtElem != null) { - // Check if sandboxes should be shown in the virtualization view - - boolean showSandboxes = cfg.getChild("showAllSandboxes") != null ? true : false; + // Check if virtualization view show options have been specified + + int showOptions = AVMContext.ShowStagingStores + AVMContext.ShowAuthorStores; + + String showAttr = virtElem.getAttribute( "stores"); + if ( showAttr != null) + { + // Split the show options string + + StringTokenizer tokens = new StringTokenizer( showAttr, ","); + StringList optList = new StringList(); + + while ( tokens.hasMoreTokens()) + optList.addString( tokens.nextToken().trim().toLowerCase()); + + // Build the show options mask + + showOptions = 0; + + if ( optList.containsString("normal")) + showOptions += AVMContext.ShowNormalStores; + + if ( optList.containsString("author")) + showOptions += AVMContext.ShowAuthorStores; + + if ( optList.containsString("preview")) + showOptions += AVMContext.ShowPreviewStores; + + if ( optList.containsString("staging")) + showOptions += AVMContext.ShowStagingStores; + } + else if ( cfg.getChild("showAllSandboxes") != null) + { + // Old style show options + + showOptions = AVMContext.ShowNormalStores + AVMContext.ShowAuthorStores + + AVMContext.ShowPreviewStores + AVMContext.ShowStagingStores; + } // Create the context - context = new AVMContext(name, showSandboxes, this); + context = new AVMContext(name, showOptions, this); // Enable file state caching @@ -327,6 +399,10 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface m_createVerListener.addCallback(context); m_purgeVerListener.addCallback(context); + + // Create the file state for the root path, this will build the store pseudo folder list + + findPseudoState( new AVMPath( ""), context); } else { @@ -518,7 +594,9 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface } } } + // Return the context for this shared filesystem + return context; } finally @@ -673,13 +751,14 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface /** * Build the full store path for a file/folder using the share relative path * - * @param ctx - * AVMContext - * @param path - * String + * @param ctx AVMContext + * @param path String + * @param sess SrvSession * @return AVMPath + * @exception AccessDeniedException */ - protected final AVMPath buildStorePath(AVMContext ctx, String path) + protected final AVMPath buildStorePath(AVMContext ctx, String path, SrvSession sess) + throws AccessDeniedException { // Check if the AVM filesystem is a normal or virtualization view @@ -690,6 +769,10 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Create a path for the virtualization view avmPath = new AVMPath(path); + + // Check that the user has access to the path + + checkPathAccess( avmPath, ctx, sess); } else { @@ -771,7 +854,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Convert the relative path to a store path - AVMPath storePath = buildStorePath(ctx, paths[0]); + AVMPath storePath = buildStorePath(ctx, paths[0], sess); // DEBUG @@ -839,7 +922,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Convert the relative path to a store path - AVMPath storePath = buildStorePath(ctx, paths[0]); + AVMPath storePath = buildStorePath(ctx, paths[0], sess); // DEBUG @@ -871,7 +954,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Get the new file details - AVMPath fileStorePath = buildStorePath(ctx, params.getPath()); + AVMPath fileStorePath = buildStorePath(ctx, params.getPath(), sess); AVMNodeDescriptor nodeDesc = m_avmService.lookup(fileStorePath.getVersion(), fileStorePath.getAVMPath()); if (nodeDesc != null) @@ -933,7 +1016,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath(ctx, dir); + AVMPath storePath = buildStorePath(ctx, dir, sess); // DEBUG @@ -1001,7 +1084,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath(ctx, name); + AVMPath storePath = buildStorePath(ctx, name, sess); // DEBUG @@ -1067,8 +1150,22 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath(ctx, name); - + AVMPath storePath = null; + + try + { + storePath = buildStorePath(ctx, name, sess); + } + catch ( AccessDeniedException ex) + { + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug("File exists check, path=" + name + " Access denied"); + + return FileStatus.NotExist; + } + // DEBUG if (logger.isDebugEnabled()) @@ -1173,8 +1270,8 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath( ctx, name); - + AVMPath storePath = buildStorePath( ctx, name, sess); + // DEBUG if ( logger.isDebugEnabled()) @@ -1260,9 +1357,12 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Mark the file/folder as read-only if not the head version - if ( ctx.isVersion() != AVMContext.VERSION_HEAD) + if ( ctx.isVersion() != AVMContext.VERSION_HEAD || storePath.isReadOnlyAccess()) attr += FileAttribute.ReadOnly; + if ( attr == 0) + attr = FileAttribute.NTNormal; + info.setFileAttributes( attr); // Set the file id @@ -1326,7 +1426,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Convert the relative path to a store path AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath(ctx, params.getPath()); + AVMPath storePath = buildStorePath(ctx, params.getPath(), sess); // DEBUG @@ -1492,8 +1592,8 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Convert the parent paths to store paths - AVMPath oldAVMPath = buildStorePath(ctx, oldPaths[0]); - AVMPath newAVMPath = buildStorePath(ctx, newPaths[0]); + AVMPath oldAVMPath = buildStorePath(ctx, oldPaths[0], sess); + AVMPath newAVMPath = buildStorePath(ctx, newPaths[0], sess); // DEBUG @@ -1631,7 +1731,21 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // Build the store path to the folder being searched - AVMPath storePath = buildStorePath(avmCtx, paths[0]); + AVMPath storePath = null; + + try + { + storePath = buildStorePath(avmCtx, paths[0], sess); + } + catch ( AccessDeniedException ex) + { + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug("Start search access denied"); + + throw new FileNotFoundException("Access denied"); + } // Check if the filesystem is the virtualization view @@ -1649,7 +1763,12 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { // Get the pseudo file list for the parent directory - PseudoFileList searchList = fstate.getPseudoFileList(); + PseudoFileList searchList = null; + + if ( storePath.isLevel() == AVMPath.LevelId.Root) + searchList = filterPseudoFolders(avmCtx, sess, storePath, fstate); + else + searchList = fstate.getPseudoFileList(); // Check if the pseudo file list is valid @@ -1664,7 +1783,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // folder listing WildCard wildCardFilter = new WildCard(paths[1], false); - return new PseudoFileListSearchContext(searchList, attrib, wildCardFilter); + return new PseudoFileListSearchContext(searchList, attrib, wildCardFilter, storePath.isReadOnlyAccess()); } else { @@ -1678,7 +1797,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface PseudoFileList singleList = new PseudoFileList(); singleList.addFile(pseudoFile); - return new PseudoFileListSearchContext(singleList, attrib, null); + return new PseudoFileListSearchContext(singleList, attrib, null, storePath.isReadOnlyAccess()); } } } @@ -1694,7 +1813,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface PseudoFileList metaFiles = new PseudoFileList(); - return new PseudoFileListSearchContext(metaFiles, attrib, null); + return new PseudoFileListSearchContext(metaFiles, attrib, null, storePath.isReadOnlyAccess()); } } @@ -1707,8 +1826,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { // Get the file listing for the folder - AVMNodeDescriptor[] fileList = m_avmService.getDirectoryListingArray(storePath.getVersion(), storePath - .getAVMPath(), false); + AVMNodeDescriptor[] fileList = m_avmService.getDirectoryListingArray(storePath.getVersion(), storePath.getAVMPath(), false); // Create the search context @@ -1724,14 +1842,26 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface // folder listing WildCard wildCardFilter = new WildCard(paths[1], false); - context = new AVMSearchContext(fileList, attrib, wildCardFilter, storePath.getRelativePath()); + context = new AVMSearchContext(fileList, attrib, wildCardFilter, storePath.getRelativePath(), storePath.isReadOnlyAccess()); } } else { // Single file/folder search, convert the path to a store path - storePath = buildStorePath(avmCtx, searchPath); + try + { + storePath = buildStorePath(avmCtx, searchPath, sess); + } + catch ( AccessDeniedException ex) + { + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug("Start search access denied"); + + throw new FileNotFoundException("Access denied"); + } // Get the single file/folder details @@ -1741,7 +1871,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { // Create the search context for the single file/folder - context = new AVMSingleFileSearchContext(nodeDesc, storePath.getRelativePath()); + context = new AVMSingleFileSearchContext(nodeDesc, storePath.getRelativePath(), storePath.isReadOnlyAccess()); } } @@ -2074,7 +2204,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface * AVMContext * @return FileState */ - private final FileState findPseudoState(AVMPath avmPath, AVMContext avmCtx) + protected final FileState findPseudoState(AVMPath avmPath, AVMContext avmCtx) { // Make sure the is to a pseudo file/folder @@ -2114,30 +2244,185 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { // Add pseudo files for the stores - boolean sandbox = false; - for ( AVMStoreDescriptor storeDesc : storeList) { // Get the properties for the current store + + String storeName = storeDesc.getName(); + Map props = m_avmService.getStoreProperties( storeName); - Map props = m_avmService.getStoreProperties( storeDesc.getName()); + // Check if the store is a main web project - if ( props.containsKey( AVMContext.PROP_WORKFLOWPREVIEW) || props.containsKey( AVMContext.PROP_AUTHORPREVIEW)) - sandbox = true; + if ( props.containsKey( SandboxConstants.PROP_SANDBOX_STAGING_MAIN)) + { + // Get the noderef for the web project + + PropertyValue prop = props.get( SandboxConstants.PROP_WEB_PROJECT_NODE_REF); + if ( prop != null) { + + // Get the web project noderef + + NodeRef webNodeRef = new NodeRef( prop.getStringValue()); + + // Create the web project pseudo folder + + WebProjectStorePseudoFile webProjFolder = new WebProjectStorePseudoFile( storeDesc, FileName.DOS_SEPERATOR_STR + storeName, webNodeRef); + fstate.addPseudoFile( webProjFolder); + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug( "Found web project " + webProjFolder.getFileName()); + + // Get the list of content managers for this web project + + List mgrAssocs = m_nodeService.getChildAssocs( webNodeRef, WCMAppModel.ASSOC_WEBUSER, RegexQNamePattern.MATCH_ALL); + + for ( ChildAssociationRef mgrRef : mgrAssocs) + { + // Get the child node and see if it is a content manager association + + NodeRef childRef = mgrRef.getChildRef(); + + if ( m_nodeService.getProperty( childRef, WCMAppModel.PROP_WEBUSERROLE).equals(ROLE_CONTENT_MANAGER)) + { + // Get the user name add it to the web project pseudo folder + + String userName = (String) m_nodeService.getProperty( childRef, WCMAppModel.PROP_WEBUSERNAME); + + webProjFolder.addUserRole( userName, WebProjectStorePseudoFile.RoleContentManager); + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug(" Added content manager " + userName); + } + } + } + } else - sandbox = false; + { + // Check if this store is a web project sandbox + + int storeType = StoreType.Normal; + String webProjName = null; + String userName = null; + + if ( props.containsKey( SandboxConstants.PROP_SANDBOX_AUTHOR_MAIN)) + { + // Sandbox store, linked to a web project + + storeType = StoreType.WebAuthorMain; + + // Get the associated web project name - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug( "Store " + storeDesc.getName() + ", sandbox=" + sandbox); - - // Add a pseudo file for the current store + webProjName = props.get( SandboxConstants.PROP_WEBSITE_NAME).getStringValue(); - if ( sandbox == false || avmCtx.showSandboxes() == true) - fstate.addPseudoFile( new StorePseudoFile( storeDesc, FileName.DOS_SEPERATOR_STR + storeDesc.getName())); + // Get the user name from teh store name + + userName = storeName.substring( webProjName.length() + 2); + } + else if ( props.containsKey( SandboxConstants.PROP_SANDBOX_AUTHOR_PREVIEW)) + { + // Author preview sandbox store, linked to a web project + + storeType = StoreType.WebAuthorPreview; + + // Get the associated web project name + + String projPlusUser = storeName.substring( 0, storeName.length() - "--preview".length()); + int pos = projPlusUser.lastIndexOf("--"); + if ( pos != -1) + { + webProjName = projPlusUser.substring( 0, pos); + userName = projPlusUser.substring(pos + 2); + } + } + else if ( props.containsKey( SandboxConstants.PROP_SANDBOX_WORKFLOW_PREVIEW)) + { + // Staging preview sandbox store, linked to a web project + + storeType = StoreType.WebStagingPreview; + } + else if ( props.containsKey( SandboxConstants.PROP_SANDBOX_STAGING_PREVIEW)) + { + // Staging preview sandbox store, linked to a web project + + storeType = StoreType.WebStagingPreview; + + // Get the associated web project name + + webProjName = storeName.substring( 0, storeName.length() - "--preview".length()); + } + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug( "Store " + storeDesc.getName() + ", type=" + StoreType.asString( storeType) + ", webproj=" + webProjName + ", username=" + userName); + + // Add a pseudo file for the current store + + if ( avmCtx.showStoreType( storeType)) + { + // Create the pseudo folder for the store + + StorePseudoFile storeFolder = new StorePseudoFile( storeDesc, FileName.DOS_SEPERATOR_STR + storeName, storeType); + if ( storeType != StoreType.Normal) + { + storeFolder.setWebProject( webProjName); + storeFolder.setUserName( userName); + } + + // Add the store pseudo folder to the root folder file list + + fstate.addPseudoFile( storeFolder); + } + } } } + + // Scan the pseudo folder list and add all publisher/reviewer user names to the web project roles list + + PseudoFileList folderList = fstate.getPseudoFileList(); + if ( folderList != null && folderList.numberOfFiles() > 0) + { + // Scan the pseudo folder list + + for ( int i = 0; i < folderList.numberOfFiles(); i++) + { + // Check if the current pseduo file is a store folder + + if ( folderList.getFileAt( i) instanceof StorePseudoFile) + { + // Check if the store has an associated web project + + StorePseudoFile curFile = (StorePseudoFile) folderList.getFileAt( i); + if ( curFile.hasWebProject()) + { + // Find the associated web project pseudo folder + + WebProjectStorePseudoFile webProj = (WebProjectStorePseudoFile) folderList.findFile( curFile.getWebProject(), true); + + // Strip the web project name from the sandbox store name and extract the user name. + // Add the user as a publisher/reviewer to the web project roles list + + String userName = curFile.getFileName().substring( webProj.getFileName().length() + 2); + + // If the user does not have a content manager role then add as a publisher + + if ( webProj.getUserRole( userName) == WebProjectStorePseudoFile.RoleNone) + { + webProj.addUserRole( userName, WebProjectStorePseudoFile.RolePublisher); + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug( "Added publisher " + userName + " to " + webProj.getFileName()); + } + } + } + } + } } break; @@ -2406,4 +2691,219 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface } } } + + /** + * Check that the user has access to the path + * + * @param avmPath AVMPath + * @param avmCtx AVMContext + * @param sess SrvSession + * @exception AccessDeniedException + */ + private final void checkPathAccess( AVMPath avmPath, AVMContext avmCtx, SrvSession sess) + throws AccessDeniedException { + + // Only enforce access checks on virtualization views + + if ( avmCtx.isVirtualizationView() == false) + return; + + // Get the client details for the session + + ClientInfo cInfo = sess.getClientInformation(); + if ( cInfo == null || cInfo.getUserName() == null || cInfo.getUserName().length() == 0) + throw new AccessDeniedException(); + + // Allow access to the root folder + + if ( avmPath.isLevel() == AVMPath.LevelId.Root) + return; + + // Admin user has full access + + if ( cInfo.getUserName().equalsIgnoreCase( m_authComponent.getSystemUserName())) + return; + + // Get root file state, get the store pseudo folder details + + FileState rootState = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR); + if ( rootState == null){ + + // Recreate the root file state, new stores may have been added + + rootState = findPseudoState( new AVMPath( FileName.DOS_SEPERATOR_STR), avmCtx); + } + + // Check if there are any store pseudo folders + + if ( rootState != null && rootState.hasPseudoFiles()) + { + PseudoFile pseudoFolder = rootState.getPseudoFileList().findFile( avmPath.getStoreName(), false); + if ( pseudoFolder != null) + { + // Check if the pseudo folder is a web project folder or sandbox within a web project + + if ( pseudoFolder instanceof WebProjectStorePseudoFile) + { + // Check the users role within the web project + + WebProjectStorePseudoFile webFolder = (WebProjectStorePseudoFile) pseudoFolder; + + int role = webFolder.getUserRole( cInfo.getUserName()); + + if ( role == WebProjectStorePseudoFile.RoleNone) + { + // User does not have access to this web project + + throw new AccessDeniedException("User " + cInfo.getUserName() + " has no access to web project, " + webFolder.getFileName()); + } + else if ( role == WebProjectStorePseudoFile.RolePublisher) + { + // Only allow read-only access to the staging area + + avmPath.setReadOnlyAccess( true); + } + } + else if ( pseudoFolder instanceof StorePseudoFile) + { + // Check the store type + + StorePseudoFile storeFolder = (StorePseudoFile) pseudoFolder; + if ( storeFolder.isStoreType() == StoreType.Normal) + return; + else if ( storeFolder.hasWebProject()) + { + // Get the web project that the sandbox is linked to + + WebProjectStorePseudoFile webFolder = (WebProjectStorePseudoFile) rootState.getPseudoFileList().findFile( storeFolder.getWebProject(), false); + + int role = webFolder.getUserRole( cInfo.getUserName()); + + if ( role == WebProjectStorePseudoFile.RoleNone) + { + // User does not have access to this web project + + throw new AccessDeniedException("User " + cInfo.getUserName() + " has no access to web project, " + webFolder.getFileName() + "/" + storeFolder.getFileName()); + } + else if ( role == WebProjectStorePseudoFile.RolePublisher && + storeFolder.getUserName().equalsIgnoreCase( cInfo.getUserName()) == false) + { + // User does not have access to this web project + + throw new AccessDeniedException("User " + cInfo.getUserName() + " has no access to web project, " + webFolder.getFileName() + "/" + storeFolder.getFileName()); + } + } + } + } + } + else + { + // Store does not exist + + throw new AccessDeniedException("Store does not exist, " + avmPath.getStoreName()); + } + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug( "Check access " + avmPath); + } + + /** + * Filter the list of pseudo folders returned in a search + * + * @param avmCtx AVMContext + * @param sess SrvSession + * @param avmPath AVMPath + * @param fstate FileState + * @return PseudoFileList + */ + private final PseudoFileList filterPseudoFolders( AVMContext avmCtx, SrvSession sess, AVMPath avmPath, FileState fstate) + { + // Check if the root folder file state has any store pseudo folders + + if ( fstate.hasPseudoFiles() == false) + return null; + + // Get the client details for the session + + ClientInfo cInfo = sess.getClientInformation(); + if ( cInfo == null || cInfo.getUserName() == null || cInfo.getUserName().length() == 0) + return null; + + // Check for the admin user, no need to filter the list + + PseudoFileList fullList = fstate.getPseudoFileList(); + if ( cInfo.getUserName().equalsIgnoreCase( m_authComponent.getSystemUserName())) + return fullList; + + // Create a filtered list of store pseudo folders that the user has access to + + PseudoFileList filterList = new PseudoFileList(); + + for ( int i = 0; i < fullList.numberOfFiles(); i++) + { + // Get the current store pseudo folder + + PseudoFile pseudoFolder = fullList.getFileAt( i); + + // Check if the pseudo folder is a web project folder or sandbox within a web project + + if ( pseudoFolder instanceof WebProjectStorePseudoFile) + { + // Check the users role within the web project + + WebProjectStorePseudoFile webFolder = (WebProjectStorePseudoFile) pseudoFolder; + + if ( avmCtx.showStagingStores() && webFolder.getUserRole( cInfo.getUserName()) != WebProjectStorePseudoFile.RoleNone) + { + // User has access to this store + + filterList.addFile( pseudoFolder); + } + } + else if ( pseudoFolder instanceof StorePseudoFile) + { + // Check if the store type should be included in the visible list + + StorePseudoFile storeFolder = (StorePseudoFile) pseudoFolder; + if ( avmCtx.showStoreType( storeFolder.isStoreType())) + { + // Check if the user has access to this store + + if ( storeFolder.hasWebProject()) + { + // Get the web project that the sandbox is linked to + + WebProjectStorePseudoFile webFolder = (WebProjectStorePseudoFile) fullList.findFile( storeFolder.getWebProject(), false); + int role = webFolder.getUserRole( cInfo.getUserName()); + + if ( role == WebProjectStorePseudoFile.RoleContentManager && avmCtx.showStoreType( storeFolder.isStoreType())) + { + // User is a content manager, allow access to the store + + filterList.addFile( storeFolder); + } + else if ( role == WebProjectStorePseudoFile.RolePublisher && avmCtx.showStoreType( storeFolder.isStoreType())) + { + // Allow access if the user owns the current folder + + if ( storeFolder.getUserName().equalsIgnoreCase( cInfo.getUserName())) + filterList.addFile( storeFolder); + } + } + else if ( avmCtx.showNormalStores()) + { + // Store is not linked to a web project, allow access to the store + + filterList.addFile( storeFolder); + } + } + } + } + + // Return the filtered list + + return filterList; + } } diff --git a/source/java/org/alfresco/filesys/avm/AVMPath.java b/source/java/org/alfresco/filesys/avm/AVMPath.java index f4cce29173..01cfc625e0 100644 --- a/source/java/org/alfresco/filesys/avm/AVMPath.java +++ b/source/java/org/alfresco/filesys/avm/AVMPath.java @@ -86,6 +86,10 @@ public class AVMPath { private String m_avmPath; + // Path is read-only access + + private boolean m_readOnly; + /** * Default constructor */ @@ -132,6 +136,15 @@ public class AVMPath { { return m_levelId; } + + /** + * Check if the path is read-only + * + * @return boolean + */ + public final boolean isReadOnlyAccess() { + return m_readOnly; + } /** * Return the store name @@ -596,6 +609,16 @@ public class AVMPath { return fid; } + + /** + * Set the path access, true for read-only access + * + * @param access boolean + */ + public final void setReadOnlyAccess( boolean readOnly) + { + m_readOnly = readOnly; + } /** * Return the AVM path details as a string @@ -676,6 +699,10 @@ public class AVMPath { str.append(getAVMPath()); break; } + + if ( isReadOnlyAccess()) + str.append("-ReadOnly"); + str.append("]"); return str.toString(); diff --git a/source/java/org/alfresco/filesys/avm/AVMSearchContext.java b/source/java/org/alfresco/filesys/avm/AVMSearchContext.java index 16586032b0..a7f5f5111a 100644 --- a/source/java/org/alfresco/filesys/avm/AVMSearchContext.java +++ b/source/java/org/alfresco/filesys/avm/AVMSearchContext.java @@ -56,6 +56,10 @@ public class AVMSearchContext extends SearchContext { private String m_parentPath; + // Mark all files/folders as read-only + + private boolean m_readOnly; + /** * Class constructor * @@ -63,8 +67,9 @@ public class AVMSearchContext extends SearchContext { * @param attrib int * @param filter WildCard * @param parentPath String + * @param readOnly boolean */ - public AVMSearchContext( AVMNodeDescriptor[] fileList, int attrib, WildCard filter, String parentPath) + public AVMSearchContext( AVMNodeDescriptor[] fileList, int attrib, WildCard filter, String parentPath, boolean readOnly) { m_attrib = attrib; m_filter = filter; @@ -73,6 +78,8 @@ public class AVMSearchContext extends SearchContext { m_parentPath = parentPath; if ( m_parentPath != null && m_parentPath.endsWith( FileName.DOS_SEPERATOR_STR) == false) m_parentPath = m_parentPath + FileName.DOS_SEPERATOR_STR; + + m_readOnly = readOnly; } /** @@ -177,6 +184,12 @@ public class AVMSearchContext extends SearchContext { curFile.getName().equalsIgnoreCase( "Desktop.ini") || curFile.getName().equalsIgnoreCase( "Thumbs.db")) attr += FileAttribute.Hidden; + + if ( isReadOnly()) + attr += FileAttribute.ReadOnly; + + if ( attr == 0) + attr = FileAttribute.NTNormal; info.setFileAttributes( attr); @@ -293,4 +306,24 @@ public class AVMSearchContext extends SearchContext { m_fileIdx = curFileIdx; return false; } + + /** + * Check if all files/folders returned by the search should be marked as read-only + * + * @return boolean + */ + public final boolean isReadOnly() + { + return m_readOnly; + } + + /** + * Set all files/folders returned by the search as read-only + * + * @param readOnly boolean + */ + public final void setReadOnly( boolean readOnly) + { + m_readOnly = readOnly; + } } diff --git a/source/java/org/alfresco/filesys/avm/AVMSingleFileSearchContext.java b/source/java/org/alfresco/filesys/avm/AVMSingleFileSearchContext.java index 0e8542fb2a..af92df0e82 100644 --- a/source/java/org/alfresco/filesys/avm/AVMSingleFileSearchContext.java +++ b/source/java/org/alfresco/filesys/avm/AVMSingleFileSearchContext.java @@ -49,16 +49,23 @@ public class AVMSingleFileSearchContext extends SearchContext { private String m_relativePath; + // Mark thel file/folder as read-only + + private boolean m_readOnly; + /** * Class constructor * * @param fileDetails AVMNodeDescriptor * @param relPath String + * @param readOnly boolean */ - public AVMSingleFileSearchContext( AVMNodeDescriptor fileDetails, String relPath) + public AVMSingleFileSearchContext( AVMNodeDescriptor fileDetails, String relPath, boolean readOnly) { m_fileDetails = fileDetails; m_relativePath = relPath; + + m_readOnly = readOnly; } /** @@ -112,6 +119,9 @@ public class AVMSingleFileSearchContext extends SearchContext { m_fileDetails.getName().equalsIgnoreCase( "Desktop.ini") || m_fileDetails.getName().equalsIgnoreCase( "Thumbs.db")) attr += FileAttribute.Hidden; + + if ( m_readOnly == true) + attr += FileAttribute.ReadOnly; info.setFileAttributes( attr); info.setFileId( m_relativePath.hashCode()); diff --git a/source/java/org/alfresco/filesys/avm/PseudoFileListSearchContext.java b/source/java/org/alfresco/filesys/avm/PseudoFileListSearchContext.java index b0975d23ac..c81facbcb1 100644 --- a/source/java/org/alfresco/filesys/avm/PseudoFileListSearchContext.java +++ b/source/java/org/alfresco/filesys/avm/PseudoFileListSearchContext.java @@ -52,18 +52,24 @@ public class PseudoFileListSearchContext extends SearchContext { private WildCard m_filter; + // Mark all files/folders as read-only + + private boolean m_readOnly; + /** * Class constructor * * @param fileList PseudoFileList * @param attrib int * @param filter WildCard + * @param readOnly boolean */ - public PseudoFileListSearchContext( PseudoFileList fileList, int attrib, WildCard filter) + public PseudoFileListSearchContext( PseudoFileList fileList, int attrib, WildCard filter, boolean readOnly) { m_attrib = attrib; m_filter = filter; m_fileList = fileList; + m_readOnly = readOnly; } /** @@ -176,6 +182,11 @@ public class PseudoFileListSearchContext extends SearchContext { curFile.getFileName().equalsIgnoreCase( "Desktop.ini") || curFile.getFileName().equalsIgnoreCase( "Thumbs.db")) attr += FileAttribute.Hidden; + + // Check if the file/folder should be marked as read-only + + if ( m_readOnly && pfInfo.isReadOnly() == false) + attr += FileAttribute.ReadOnly; info.setFileAttributes( attr); info.setFileId( pfInfo.getFileId()); diff --git a/source/java/org/alfresco/filesys/avm/StorePseudoFile.java b/source/java/org/alfresco/filesys/avm/StorePseudoFile.java index 8ed2056e16..c57b119893 100644 --- a/source/java/org/alfresco/filesys/avm/StorePseudoFile.java +++ b/source/java/org/alfresco/filesys/avm/StorePseudoFile.java @@ -40,13 +40,26 @@ import org.alfresco.service.cmr.avm.AVMStoreDescriptor; */ public class StorePseudoFile extends PseudoFile { + // Store type + + private int m_storeType = StoreType.Normal; + + // Web project this sandbox links to, or null if this store is not linked + + private String m_webProject; + + // User name if this is an author sandbox for a web project + + private String m_userName; + /** * Class constructor * * @param storeDesc AVMStoreDescriptor * @param relPath String + * @param storeType int */ - public StorePseudoFile( AVMStoreDescriptor storeDesc, String relPath) + public StorePseudoFile( AVMStoreDescriptor storeDesc, String relPath, int storeType) { super( storeDesc.getName(), FileAttribute.Directory + FileAttribute.ReadOnly); @@ -63,6 +76,8 @@ public class StorePseudoFile extends PseudoFile { fInfo.setFileId( relPath.hashCode()); setFileInfo( fInfo); + + setStoreType( storeType); } /** @@ -118,4 +133,84 @@ public class StorePseudoFile extends PseudoFile { public FileInfo getFileInfo() { return getInfo(); } + + /** + * Return the store type + * + * @return int + */ + public final int isStoreType() + { + return m_storeType; + } + + /** + * Check if this store is linked to a web project + * + * @return boolean + */ + public final boolean hasWebProject() + { + return m_webProject != null ? true : false; + } + + /** + * Get the web project that this store links to, or null if not linked + * + * @return String + */ + public final String getWebProject() + { + return m_webProject; + } + + /** + * Set the web project that this store is linked to + * + * @param webProject String + */ + public final void setWebProject(String webProject) + { + m_webProject = webProject; + } + + /** + * Check if this store is an author sandbox + * + * @return boolean + */ + public final boolean hasUserName() + { + return m_userName != null ? true : false; + } + + /** + * Get the owner of this sandbox + * + * @return String + */ + public final String getUserName() + { + return m_userName; + } + + /** + * Set the owner of this sandbox + * + * @param userName String + */ + public final void setUserName(String userName) + { + m_userName = userName; + } + + /** + * Set the store type + * + * @param storeType int + */ + public final void setStoreType(int storeType) + { + m_storeType = storeType; + } } diff --git a/source/java/org/alfresco/filesys/avm/StoreType.java b/source/java/org/alfresco/filesys/avm/StoreType.java new file mode 100644 index 0000000000..c8bfe28342 --- /dev/null +++ b/source/java/org/alfresco/filesys/avm/StoreType.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.filesys.avm; + +/** + * Store Types Class + * + * @author gkspencer + */ +public class StoreType { + + // Store types + + public static final int Normal = 0; + + // Web project store types + + public static final int WebAuthorMain = 1; + public static final int WebAuthorPreview = 2; + public static final int WebStagingPreview = 3; + public static final int WebStagingMain = 4; + + // Store type strings + + private static final String[] _types = { "Normal", "AuthorMain", "AuthorPreview", "StagingPreview", "StagingMain" }; + + /** + * Return a store type as a string + * + * @param typ int + * @return String + */ + public final static String asString( int typ) + { + if ( typ < 0 || typ > _types.length) + return "Invalid"; + return _types[ typ]; + } +} diff --git a/source/java/org/alfresco/filesys/avm/WebProjectStorePseudoFile.java b/source/java/org/alfresco/filesys/avm/WebProjectStorePseudoFile.java new file mode 100644 index 0000000000..5a8e557485 --- /dev/null +++ b/source/java/org/alfresco/filesys/avm/WebProjectStorePseudoFile.java @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" */ + +package org.alfresco.filesys.avm; + +import java.util.Hashtable; + +import org.alfresco.filesys.server.filesys.FileAttribute; +import org.alfresco.filesys.server.filesys.FileInfo; +import org.alfresco.filesys.server.filesys.FileName; +import org.alfresco.filesys.server.filesys.NetworkFile; +import org.alfresco.filesys.server.pseudo.PseudoFile; +import org.alfresco.filesys.server.pseudo.PseudoFolderNetworkFile; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Web Project Store Pseudo File Class + * + *

Represents an AVM store as a folder. + * + * @author gkspencer + */ +public class WebProjectStorePseudoFile extends StorePseudoFile { + + // Store/web project user access roles + + public static final int RoleNone = 0; + public static final int RolePublisher = 1; + public static final int RoleContentManager = 2; + + // Node ref for this store + + private NodeRef m_noderef; + + // List of users that are content managers/publishers for this web project store + + private Hashtable m_users; + + /** + * Class constructor + * + * @param storeDesc AVMStoreDescriptor + * @param relPath String + * @param nodeRef NodeRef + */ + public WebProjectStorePseudoFile( AVMStoreDescriptor storeDesc, String relPath, NodeRef nodeRef) + { + super( storeDesc, relPath, StoreType.WebStagingMain); + + // Create static file information from the store details + + FileInfo fInfo = new FileInfo( storeDesc.getName(), 0L, FileAttribute.Directory + FileAttribute.ReadOnly); + + fInfo.setCreationDateTime( storeDesc.getCreateDate()); + fInfo.setModifyDateTime( storeDesc.getCreateDate()); + fInfo.setAccessDateTime( storeDesc.getCreateDate()); + fInfo.setChangeDateTime( storeDesc.getCreateDate()); + + fInfo.setPath( relPath); + fInfo.setFileId( relPath.hashCode()); + + setFileInfo( fInfo); + + // Set the associated node ref for the web project + + m_noderef = nodeRef; + } + + /** + * Class constructor + * + * @param storeName String + * @param relPath String + * @param nodeRef NodeRef + */ + public WebProjectStorePseudoFile( String storeName, String relPath, NodeRef nodeRef) + { + super( storeName, relPath); + + // Create static file information from the store details + + FileInfo fInfo = new FileInfo( storeName, 0L, FileAttribute.Directory + FileAttribute.ReadOnly); + + long timeNow = System.currentTimeMillis(); + fInfo.setCreationDateTime( timeNow); + fInfo.setModifyDateTime( timeNow); + fInfo.setAccessDateTime( timeNow); + fInfo.setChangeDateTime( timeNow); + + fInfo.setPath( relPath); + fInfo.setFileId( relPath.hashCode()); + + setFileInfo( fInfo); + + // Set the associated node ref for the web project + + m_noderef = nodeRef; + } + + /** + * Check if the associated node ref is valid + * + * @return boolean + */ + public final boolean hasNodeRef() + { + return m_noderef != null ? true : false; + } + + /** + * Get the associated node ref for the store + * + * @return NodeRef + */ + public final NodeRef getNodeRef() + { + return m_noderef; + } + + /** + * Set the associated node ref for the store + * + * @param node NodeRef + */ + public final void setNodeRef(NodeRef node) + { + m_noderef = node; + } + + /** + * Return the role for the specified user within this web project + * + * @param userName String + * @return int + */ + public final int getUserRole(String userName) + { + if ( m_users == null) + return RoleNone; + + Integer role = m_users.get( userName); + return role != null ? role.intValue() : RoleNone; + } + + /** + * Add a user role for this web project + * + * @param userName String + * @param role int + */ + public final void addUserRole(String userName, int role) + { + if ( m_users == null) + m_users = new Hashtable(); + + m_users.put(userName, new Integer(role)); + } + + /** + * Remove a user role for this project + * + * @param userName String + */ + public final void removeUserRole(String userName) + { + if ( m_users != null) + m_users.remove(userName); + } +} diff --git a/source/java/org/alfresco/filesys/server/state/FileState.java b/source/java/org/alfresco/filesys/server/state/FileState.java index 01df3c5c8b..af130e3339 100644 --- a/source/java/org/alfresco/filesys/server/state/FileState.java +++ b/source/java/org/alfresco/filesys/server/state/FileState.java @@ -95,6 +95,10 @@ public class FileState private PseudoFileList m_pseudoFiles; + // Last updated time + + private long m_lastUpdate; + /** * Class constructor * @@ -357,6 +361,26 @@ public class FileState m_pseudoFiles = new PseudoFileList(); m_pseudoFiles.addFile( pfile); } + + /** + * Return the last updated time + * + * @return long + */ + public final long getLastUpdated() + { + return m_lastUpdate; + } + + /** + * Set the last updated time + * + * @param updateTime long + */ + public final void setLastUpdated(long updateTime) + { + m_lastUpdate = updateTime; + } /** * Set the file status diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AVMFormsPropertyTokenisationPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AVMFormsPropertyTokenisationPatch.java new file mode 100644 index 0000000000..8722b70332 --- /dev/null +++ b/source/java/org/alfresco/repo/admin/patch/impl/AVMFormsPropertyTokenisationPatch.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.admin.patch.impl; + +import org.alfresco.i18n.I18NUtil; +import org.alfresco.repo.admin.patch.AbstractPatch; +import org.alfresco.repo.importer.ImporterBootstrap; + +/** + * @author Kevin Roast + */ +public class AVMFormsPropertyTokenisationPatch extends BaseReindexingPatch +{ + private static final String MSG_SUCCESS = "patch.avmFormPropertyIdentifier.result"; + + private ImporterBootstrap spacesImporterBootstrap; + + public void setSpacesImporterBootstrap(ImporterBootstrap spacesImporterBootstrap) + { + this.spacesImporterBootstrap = spacesImporterBootstrap; + } + + @Override + protected String applyInternal() throws Exception + { + reindex("TYPE:\"wca:webform\"", spacesImporterBootstrap.getStoreRef()); + return I18NUtil.getMessage(MSG_SUCCESS); + } +} diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AVMStorePropertyTokenisationPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AVMStorePropertyTokenisationPatch.java index 53c5cc473a..b0a2ded9f4 100644 --- a/source/java/org/alfresco/repo/admin/patch/impl/AVMStorePropertyTokenisationPatch.java +++ b/source/java/org/alfresco/repo/admin/patch/impl/AVMStorePropertyTokenisationPatch.java @@ -26,74 +26,29 @@ package org.alfresco.repo.admin.patch.impl; import org.alfresco.i18n.I18NUtil; -import org.alfresco.repo.admin.patch.AbstractPatch; import org.alfresco.repo.importer.ImporterBootstrap; -import org.alfresco.repo.search.Indexer; -import org.alfresco.repo.search.IndexerAndSearcher; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.search.ResultSetRow; -import org.alfresco.service.cmr.search.SearchParameters; -import org.alfresco.service.cmr.search.SearchService; /** * Patch wca:webfolder objects so that the avmstore property is in the * index in untokenized form. * * @author gavinc - * */ -public class AVMStorePropertyTokenisationPatch extends AbstractPatch +public class AVMStorePropertyTokenisationPatch extends BaseReindexingPatch { private static final String MSG_SUCCESS = "patch.avmStoreAsIdentifier.result"; private ImporterBootstrap spacesImporterBootstrap; - private IndexerAndSearcher indexerAndSearcher; - - public AVMStorePropertyTokenisationPatch() - { - - } public void setSpacesImporterBootstrap(ImporterBootstrap spacesImporterBootstrap) { this.spacesImporterBootstrap = spacesImporterBootstrap; } - public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher) - { - this.indexerAndSearcher = indexerAndSearcher; - } - @Override protected String applyInternal() throws Exception { reindex("TYPE:\"wca:webfolder\"", spacesImporterBootstrap.getStoreRef()); return I18NUtil.getMessage(MSG_SUCCESS); } - - private void reindex(String query, StoreRef store) - { - SearchParameters sp = new SearchParameters(); - sp.setLanguage(SearchService.LANGUAGE_LUCENE); - sp.setQuery(query); - sp.addStore(store); - ResultSet rs = null; - try - { - rs = searchService.query(sp); - for(ResultSetRow row : rs) - { - Indexer indexer = indexerAndSearcher.getIndexer(row.getNodeRef().getStoreRef()); - indexer.updateNode(row.getNodeRef()); - } - } - finally - { - if(rs != null) - { - rs.close(); - } - } - } } diff --git a/source/java/org/alfresco/repo/admin/patch/impl/BaseReindexingPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/BaseReindexingPatch.java new file mode 100644 index 0000000000..9d9dbe9216 --- /dev/null +++ b/source/java/org/alfresco/repo/admin/patch/impl/BaseReindexingPatch.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +package org.alfresco.repo.admin.patch.impl; + +import org.alfresco.repo.admin.patch.AbstractPatch; +import org.alfresco.repo.search.Indexer; +import org.alfresco.repo.search.IndexerAndSearcher; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.ResultSetRow; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; + +/** + * Base patch for reindexing nodes in a store based on a lucene query + * + * @author Kevin Roast + * @author gavinc + */ +public abstract class BaseReindexingPatch extends AbstractPatch +{ + protected IndexerAndSearcher indexerAndSearcher; + + public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher) + { + this.indexerAndSearcher = indexerAndSearcher; + } + + /** + * Reindex a collection of nodes in a store based on a Lucene query + * + * @param query The Lucene query to execute to return nodes + * @param store The Store containing the nodes to reindex + */ + protected void reindex(String query, StoreRef store) + { + SearchParameters sp = new SearchParameters(); + sp.setLanguage(SearchService.LANGUAGE_LUCENE); + sp.setQuery(query); + sp.addStore(store); + ResultSet rs = null; + try + { + rs = searchService.query(sp); + for(ResultSetRow row : rs) + { + Indexer indexer = indexerAndSearcher.getIndexer(row.getNodeRef().getStoreRef()); + indexer.updateNode(row.getNodeRef()); + } + } + finally + { + if (rs != null) + { + rs.close(); + } + } + } +} diff --git a/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java b/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java index e78d33819e..9488485ad5 100644 --- a/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java +++ b/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java @@ -15,11 +15,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ @@ -44,6 +44,7 @@ import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.avm.util.SimplePath; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.remote.AVMRemoteImpl; +import org.alfresco.repo.remote.AVMSyncServiceRemote; import org.alfresco.repo.remote.ClientTicketHolder; import org.alfresco.repo.remote.ClientTicketHolderThread; import org.alfresco.service.cmr.action.ActionService; @@ -62,6 +63,7 @@ import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.remote.AVMRemote; import org.alfresco.service.cmr.remote.AVMRemoteTransport; +import org.alfresco.service.cmr.remote.AVMSyncServiceTransport; import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.namespace.QName; @@ -79,7 +81,7 @@ public class DeploymentServiceImpl implements DeploymentService * The local AVMService Instance. */ private AVMService fAVMService; - + /** * The Ticket holder. */ @@ -92,7 +94,7 @@ public class DeploymentServiceImpl implements DeploymentService { fTicketHolder = new ClientTicketHolderThread(); } - + /** * Setter. * @param service The instance to set. @@ -101,7 +103,7 @@ public class DeploymentServiceImpl implements DeploymentService { fAVMService = service; } - + /* (non-Javadoc) * @see org.alfresco.service.cmr.avm.deploy.DeploymentService#deployDifference(int, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean) */ @@ -113,7 +115,7 @@ public class DeploymentServiceImpl implements DeploymentService AVMRemote remote = getRemote(hostName, port, userName, password); if (callback != null) { - DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.START, + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.START, new Pair(version, srcPath), dstPath); callback.eventOccurred(event); @@ -153,14 +155,14 @@ public class DeploymentServiceImpl implements DeploymentService throw new AVMNotFoundException("Node Not Found: " + parentBase[0]); } } - snapshot = remote.createSnapshot(storePath[0], "PreDeploy", "Pre Deployment Snapshot").get(storePath[0]); + snapshot = remote.createSnapshot(storePath[0], "PreDeploy", "Pre Deployment Snapshot").get(storePath[0]); } // Get the root of the deployment on the destination server. AVMNodeDescriptor dstRoot = remote.lookup(-1, dstPath); if (dstRoot == null) { // If it doesn't exist, do a copyDirectory to create it. - DeploymentEvent event = + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.COPIED, new Pair(version, srcPath), dstPath); @@ -177,7 +179,7 @@ public class DeploymentServiceImpl implements DeploymentService remote.createSnapshot(storePath[0], "Deployment", "Post Deployment Snapshot."); if (callback != null) { - event = new DeploymentEvent(DeploymentEvent.Type.END, + event = new DeploymentEvent(DeploymentEvent.Type.END, new Pair(version, srcPath), dstPath); callback.eventOccurred(event); @@ -187,7 +189,7 @@ public class DeploymentServiceImpl implements DeploymentService if (!dstRoot.isDirectory()) { throw new AVMWrongTypeException("Not a Directory: " + dstPath); - } + } // The corresponding directory exists so recursively deploy. try { @@ -195,7 +197,7 @@ public class DeploymentServiceImpl implements DeploymentService remote.createSnapshot(storePath[0], "Deployment", "Post Deployment Snapshot."); if (callback != null) { - DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.END, + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.END, new Pair(version, srcPath), dstPath); callback.eventOccurred(event); @@ -223,9 +225,9 @@ public class DeploymentServiceImpl implements DeploymentService finally { fTicketHolder.setTicket(null); - } + } } - + /** * Deploy all the children of corresponding directories. * @param src The source directory. @@ -234,9 +236,9 @@ public class DeploymentServiceImpl implements DeploymentService * @param dontDelete Flag for not deleting. * @param dontDo Flag for dry run. */ - private void deployDirectoryPush(int version, + private void deployDirectoryPush(int version, AVMNodeDescriptor src, AVMNodeDescriptor dst, - AVMRemote remote, + AVMRemote remote, NameMatcher matcher, boolean dontDelete, boolean dontDo, DeploymentReport report, @@ -278,7 +280,7 @@ public class DeploymentServiceImpl implements DeploymentService String destination = AVMNodeConverter.ExtendAVMPath(dst.getPath(), name); if (!excluded(matcher, null, destination)) { - DeploymentEvent event = + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.DELETED, source, destination); @@ -296,7 +298,7 @@ public class DeploymentServiceImpl implements DeploymentService } } } - + /** * Push out a single node. * @param src The source node. @@ -308,7 +310,7 @@ public class DeploymentServiceImpl implements DeploymentService */ private void deploySinglePush(int version, AVMNodeDescriptor src, AVMNodeDescriptor dstParent, - AVMNodeDescriptor dst, AVMRemote remote, + AVMNodeDescriptor dst, AVMRemote remote, NameMatcher matcher, boolean dontDelete, boolean dontDo, DeploymentReport report, @@ -338,7 +340,7 @@ public class DeploymentServiceImpl implements DeploymentService copyDirectory(version, src, dstParent, remote, matcher); return; } - Pair source = + Pair source = new Pair(version, src.getPath()); String destination = AVMNodeConverter.ExtendAVMPath(dstParent.getPath(), src.getName()); DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.COPIED, @@ -369,7 +371,7 @@ public class DeploymentServiceImpl implements DeploymentService deployDirectoryPush(version, src, dst, remote, matcher, dontDelete, dontDo, report, callback); return; } - Pair source = + Pair source = new Pair(version, src.getPath()); String destination = dst.getPath(); DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.COPIED, @@ -395,7 +397,7 @@ public class DeploymentServiceImpl implements DeploymentService { return; } - Pair source = + Pair source = new Pair(version, src.getPath()); String destination = dst.getPath(); DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.UPDATED, @@ -439,7 +441,7 @@ public class DeploymentServiceImpl implements DeploymentService copyStream(in, out); copyMetadata(version, src, remote.lookup(-1, dstParent.getPath() + '/' + dst.getName()), remote); } - + /** * Recursively copy a directory. * @param src @@ -453,7 +455,7 @@ public class DeploymentServiceImpl implements DeploymentService remote.createDirectory(parent.getPath(), src.getName()); AVMNodeDescriptor newParent = remote.lookup(-1, parent.getPath() + '/' + src.getName()); copyMetadata(version, src, newParent, remote); - SortedMap list = + SortedMap list = fAVMService.getDirectoryListing(src); // For each child in the source directory. for (AVMNodeDescriptor child : list.values()) @@ -474,7 +476,7 @@ public class DeploymentServiceImpl implements DeploymentService } } } - + /** * Utility for copying from one stream to another. * @param in The input stream. @@ -488,7 +490,7 @@ public class DeploymentServiceImpl implements DeploymentService { while ((read = in.read(buff)) != -1) { - out.write(buff, 0, read); + out.write(buff, 0, read); } in.close(); out.close(); @@ -520,7 +522,7 @@ public class DeploymentServiceImpl implements DeploymentService remote.setMimeType(dst.getPath(), contData.getMimetype()); } } - + /** * Utility to get an AVMRemote from a remote Alfresco Server. * @param hostName @@ -558,7 +560,7 @@ public class DeploymentServiceImpl implements DeploymentService throw new AVMException("Could not Initialize Remote Connection to " + hostName, e); } } - + /* (non-Javadoc) * @see org.alfresco.service.cmr.avm.deploy.DeploymentService#getRemoteActionService(java.lang.String, int, java.lang.String, java.lang.String) */ @@ -624,18 +626,21 @@ public class DeploymentServiceImpl implements DeploymentService { RmiProxyFactoryBean syncFactory = new RmiProxyFactoryBean(); syncFactory.setRefreshStubOnConnectFailure(true); - syncFactory.setServiceInterface(AVMSyncService.class); + syncFactory.setServiceInterface(AVMSyncServiceTransport.class); syncFactory.setServiceUrl("rmi://" + hostName + ":" + port + "/avmsync"); syncFactory.afterPropertiesSet(); - AVMSyncService syncService = (AVMSyncService)syncFactory.getObject(); - return syncService; + AVMSyncServiceTransport syncServiceTransport = (AVMSyncServiceTransport)syncFactory.getObject(); + AVMSyncServiceRemote remote = new AVMSyncServiceRemote(); + remote.setAvmSyncServiceTransport(syncServiceTransport); + remote.setClientTicketHolder(fTicketHolder); + return remote; } catch (Exception e) { throw new AVMException("Could not roll back failed deployment to " + hostName, e); } } - + /** * Helper function to create a non existent destination. * @param remote The AVMRemote instance. @@ -668,7 +673,7 @@ public class DeploymentServiceImpl implements DeploymentService prevPath = currPath; } } - + /* (non-Javadoc) * @see org.alfresco.service.cmr.avm.deploy.DeploymentService#deployDifferenceFS(int, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean) */ @@ -703,7 +708,7 @@ public class DeploymentServiceImpl implements DeploymentService report.add(event); return report; } - + private void deployDirectoryPush(DeploymentReceiverService service, String ticket, DeploymentReport report, DeploymentCallback callback, int version, @@ -738,7 +743,7 @@ public class DeploymentServiceImpl implements DeploymentService if (!excluded(matcher, null, newDstPath)) { service.delete(ticket, newDstPath); - DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.DELETED, + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.DELETED, new Pair(version, extendPath(srcPath, dst.getName())), newDstPath); if (callback != null) @@ -821,7 +826,7 @@ public class DeploymentServiceImpl implements DeploymentService DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.DELETED, new Pair(version, extendPath(srcPath, dst.getName())), newDstPath); - if (callback != null) + if (callback != null) { callback.eventOccurred(event); } @@ -829,7 +834,7 @@ public class DeploymentServiceImpl implements DeploymentService dst = null; } } - + /** * Copy or overwrite a single file. * @param service @@ -840,7 +845,7 @@ public class DeploymentServiceImpl implements DeploymentService * @param src * @param dstPath */ - private void copyFile(DeploymentReceiverService service, String ticket, + private void copyFile(DeploymentReceiverService service, String ticket, DeploymentReport report, DeploymentCallback callback, int version, AVMNodeDescriptor src, String dstPath) { @@ -865,7 +870,7 @@ public class DeploymentServiceImpl implements DeploymentService throw new AVMException("Failed to copy " + src + ". Deployment aborted.", e); } } - + /** * Copy a file or directory to an empty destination. * @param service @@ -877,7 +882,7 @@ public class DeploymentServiceImpl implements DeploymentService * @param parentPath */ private void copy(DeploymentReceiverService service, String ticket, - DeploymentReport report, DeploymentCallback callback, + DeploymentReport report, DeploymentCallback callback, int version, AVMNodeDescriptor src, String parentPath, NameMatcher matcher) { String dstPath = extendPath(parentPath, src.getName()); @@ -905,7 +910,7 @@ public class DeploymentServiceImpl implements DeploymentService } } } - + /** * Extend a path. * @param path @@ -920,7 +925,7 @@ public class DeploymentServiceImpl implements DeploymentService } return path + '/' + name; } - + /** * Returns true if either srcPath or dstPath are matched by matcher. * @param matcher diff --git a/source/java/org/alfresco/service/namespace/QName.java b/source/java/org/alfresco/service/namespace/QName.java index 8aa37c0b94..630aa5f269 100644 --- a/source/java/org/alfresco/service/namespace/QName.java +++ b/source/java/org/alfresco/service/namespace/QName.java @@ -401,7 +401,7 @@ public final class QName implements QNamePattern, Serializable, Cloneable { QName qname = null; - if (str == null && str.length() == 0) + if (str == null || str.length() == 0) { throw new IllegalArgumentException("str parameter is mandatory"); } @@ -449,7 +449,7 @@ public final class QName implements QNamePattern, Serializable, Cloneable { String result = str; - if (str == null && str.length() == 0) + if (str == null || str.length() == 0) { throw new IllegalArgumentException("str parameter is mandatory"); }