Dave Ward 051508c21d Merged PATCHES/V3.2.r to HEAD
19546: (RECORD ONLY) Merged V3.2 to PATCHES/V3.2.r
      19432: Merged V3.1 to V3.2
         19427: Merged V3.0 to V3.1
            19423: Merged V2.2 to V3.0
               19391: Fix for ALF-2076: AUTO does not work if a document has been added and deleted since the index backup
               19419: V2.2 Build Fix
               19421: Fix for ALF-2076: AUTO does not work if a document has been added and deleted since the index backup
      19463: Merged V3.1 to V3.2
         19459: Merged V3.0 to V3.1
            19457: Merged V2.2 to V3.0
               19449: Addition Fix for ALF-2076: AUTO does not work if a document has been added and deleted since the index backup
      19493 Merged V3.1 to V3.2
         19471: Build fix after changes for ALF-2076 were merged forward. Index checker correctly understands INDETERMINATE state of indexed transactions
   19547: (RECORD ONLY) Incremented version label
   19555: (RECORD ONLY) Merged V3.2 to PATCHES/V3.2.r
      19552: Merged V3.1 to V3.2
         19551: Further fix after changes for ALF-2076 were merged forward. Final fix to check for InIndex.No
   19566: (RECORD ONLY) Merged V3.2 to PATCHES/V3.2.r
      19539: Merged HEAD to V3.2
         19538: ALF-2076: Build fix - fix build speed
   19802: (RECORD ONLY) ALF-2382, ALF-2383: Merged V3.2 to PATCHES/V3.2.r
      19647: ALF-2231: Merged DEV/BELARUS/V2.2-2009_12_01 to V3.2 
         17704: ENH-681: alfresco webdav does not respect webdav locks 
      19624: ALF-2231: Merged DEV/BELARUS/V2.2-2009_12_01 to V3.2
         17704: ENH-681: alfresco webdav does not respect webdav locks
      19623: ALF-1890: Correction to previous checkin to allow defaulting of request body charset
      19617: ALF-1890: Improvements to make ALL WebDAV methods retryable
         - Solution from PutMethod promoted to request wrapper that will handle ALL calls to getInputStream and getReader
      19614: ALF-1890: Merged V2.2 to V3.2
         17709: Merged DEV_TEMPORARY to V2.2
            17700: ETWOTWO-1393: concurrent writes to webdav lead to data loss (0kb resulting file)
         19613: Merged DEV/BELARUS/V2.2-2010_02_03 to V2.2
            19157: ALF-1890: concurrent writes to webdav lead to data loss (0kb resulting file)
   19803: ALF-558: File servers (CIFS / FTP / NFS) can now handle concurrent write operations on Alfresco repository
      - ContentDiskDriver / AVMDiskDriver now use retrying transactions for write operations
      - Disable EagerContentStoreCleaner on ContentDiskDriver / AVMDiskDriver closeFile() operations so that they may be retried after rollback (Sony zero byte problem)
      - Allow manual association of AVM ContentData with nodes so that closeFile() may be retried
      - Propagation of new argument through AVM interfaces
   19804: (RECORD ONLY) Merged PATCHES/V3.2.0 to PATCHES/V3.2.r
      Merged HEAD to V3.2.0
         19786: Refactor of previous test fix. I have pushed down the OOo-specific parts of the change from AbstractContentTransformerTest to OpenOfficeContentTransformerTest leaving an extension point in the base class should other transformations need to be excluded in the future.
         19785: Fix for failing test OpenOfficeContentTransformerTest.testAllConversions.
            Various OOo-related transformations are returned as available but fail on our test server with OOo on it.
            Pending further work on these failings, I am disabling those transformations in test code whilst leaving them available in the product code. This is because in the wild a different OOo version may succeed with these transformations.
            I had previously explicitly disabled 3 transformations in the product and I am moving that restriction from product to test code for the same reason.
         19707: Return value from isTransformationBlocked was inverted. Fixed now.
         19705: Refinement of previous check-in re OOo transformations.
            I have pulled up the code that handles blocked transformations into a superclass so that the JodConverter-based transformer worker can inherit the same list of blocked transformations. To reiterate, blocked transformations are those that the OOo integration code believes should work but which are broken in practice. These are blocked by the transformers and will always be unavailable regardless of the OOo connection state.
         19702: Fix for HEAD builds running on panda build server.
            OOo was recently installed on panda which has activated various OOo-related transformations/extractions in the test code.
            It appears that OOo does not support some transformations from Office 97 to Office 2007. Specifically doc to docx and xls to xlsx. These transformations have now been marked as unavailable.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20004 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2010-04-27 10:57:47 +00:00

782 lines
29 KiB
Java

/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.wcm.asset;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.mbeans.VirtServerRegistry;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.ImporterActionExecuter;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.avm.util.AVMUtil;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionListenerAdapter;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.locking.AVMLock;
import org.alfresco.service.cmr.avm.locking.AVMLockingService;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.alfresco.util.TempFileProvider;
import org.alfresco.wcm.sandbox.SandboxConstants;
import org.alfresco.wcm.util.WCMUtil;
import org.apache.tools.zip.ZipFile;
/**
* Asset Service fundamental API.
* <p>
* This service API is designed to support the public facing Asset APIs.
*
* @author janv
*/
public class AssetServiceImpl implements AssetService
{
/** Logger */
//private static Log logger = LogFactory.getLog(AssetServiceImpl.class);
private static char PATH_SEPARATOR = '/';
private static final int BUFFER_SIZE = 16384;
private AVMService avmService;
private AVMLockingService avmLockingService;
private NodeService avmNodeService; // AVM node service (ML-aware)
private VirtServerRegistry virtServerRegistry;
public void setAvmService(AVMService avmService)
{
this.avmService = avmService;
}
public void setAvmLockingService(AVMLockingService avmLockingService)
{
this.avmLockingService = avmLockingService;
}
public void setNodeService(NodeService avmNodeService)
{
this.avmNodeService = avmNodeService;
}
public void setVirtServerRegistry(VirtServerRegistry virtServerRegistry)
{
this.virtServerRegistry = virtServerRegistry;
}
private void checkMandatoryPath(String path)
{
ParameterCheck.mandatoryString("path", path);
if (path.indexOf(AVMUtil.AVM_STORE_SEPARATOR_CHAR) != -1)
{
throw new IllegalArgumentException("Unexpected path '"+path+"' - should not contain '"+WCMUtil.AVM_STORE_SEPARATOR+"'");
}
}
private boolean isWebProjectStagingSandbox(String sbStoreId)
{
PropertyValue propVal = avmService.getStoreProperty(sbStoreId, SandboxConstants.PROP_WEB_PROJECT_NODE_REF);
return ((propVal != null) && (WCMUtil.isStagingStore(sbStoreId)));
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#createFolderWebApp(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
public void createFolderWebApp(String sbStoreId, String webApp, String parentFolderPathRelativeToWebApp, String name)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("webApp", webApp);
checkMandatoryPath(parentFolderPathRelativeToWebApp);
ParameterCheck.mandatoryString("name", name);
if (! isWebProjectStagingSandbox(sbStoreId))
{
parentFolderPathRelativeToWebApp = AVMUtil.addLeadingSlash(parentFolderPathRelativeToWebApp);
String avmParentPath = WCMUtil.buildStoreWebappPath(sbStoreId, webApp) + parentFolderPathRelativeToWebApp;
createFolderAVM(avmParentPath, name, null);
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + sbStoreId);
}
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#createFolder(java.lang.String, java.lang.String, java.lang.String, java.util.Map)
*/
public void createFolder(String sbStoreId, String parentFolderPath, String name, Map<QName, Serializable> properties)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("parentFolderPath", parentFolderPath);
ParameterCheck.mandatoryString("name", name);
String avmParentPath = AVMUtil.buildAVMPath(sbStoreId, parentFolderPath);
createFolderAVM(avmParentPath, name, properties);
}
private void createFolderAVM(String avmParentPath, String name, Map<QName, Serializable> properties)
{
ParameterCheck.mandatoryString("avmParentPath", avmParentPath);
ParameterCheck.mandatoryString("name", name);
String sbStoreId = WCMUtil.getSandboxStoreId(avmParentPath);
if (! isWebProjectStagingSandbox(sbStoreId))
{
avmService.createDirectory(avmParentPath, name);
String avmPath = avmParentPath + PATH_SEPARATOR + name;
// for WCM Web Client (Alfresco Explorer)
avmService.addAspect(avmPath, ApplicationModel.ASPECT_UIFACETS);
if ((properties != null) && (properties.size() > 0))
{
setProperties(avmPath, properties);
}
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + sbStoreId);
}
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#createFileWebApp(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
public ContentWriter createFileWebApp(String sbStoreId, String webApp, String parentFolderPathRelativeToWebApp, String name)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("webApp", webApp);
ParameterCheck.mandatoryString("parentFolderPathRelativeToWebApp", parentFolderPathRelativeToWebApp);
ParameterCheck.mandatoryString("name", name);
parentFolderPathRelativeToWebApp = AVMUtil.addLeadingSlash(parentFolderPathRelativeToWebApp);
String avmParentPath = WCMUtil.buildStoreWebappPath(sbStoreId, webApp) + parentFolderPathRelativeToWebApp;
createFileAVM(avmParentPath, name);
String avmPath = avmParentPath + PATH_SEPARATOR + name;
return avmService.getContentWriter(avmPath, true);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#createFile(java.lang.String, java.lang.String, java.lang.String, java.util.Map)
*/
public ContentWriter createFile(String sbStoreId, String parentFolderPath, String name, Map<QName, Serializable> properties)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("parentFolderPath", parentFolderPath);
ParameterCheck.mandatoryString("name", name);
String avmParentPath = AVMUtil.buildAVMPath(sbStoreId, parentFolderPath);
createFileAVM(avmParentPath, name);
String avmPath = avmParentPath + PATH_SEPARATOR + name;
if ((properties != null) && (properties.size() > 0))
{
setProperties(avmPath, properties);
}
return avmService.getContentWriter(avmPath, true);
}
private void createFileAVM(String avmParentPath, String name)
{
ParameterCheck.mandatoryString("avmParentPath", avmParentPath);
ParameterCheck.mandatoryString("name", name);
String sbStoreId = WCMUtil.getSandboxStoreId(avmParentPath);
if (! isWebProjectStagingSandbox(sbStoreId))
{
avmService.createFile(avmParentPath, name);
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + sbStoreId);
}
}
private void createFileAVM(String avmParentPath, String name, InputStream in)
{
ParameterCheck.mandatoryString("avmParentPath", avmParentPath);
String sbStoreId = WCMUtil.getSandboxStoreId(avmParentPath);
if (! isWebProjectStagingSandbox(sbStoreId))
{
avmService.createFile(avmParentPath, name, in, null, null);
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + sbStoreId);
}
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getContentWriter(org.alfresco.wcm.asset.AssetInfo)
*/
public ContentWriter getContentWriter(AssetInfo asset)
{
ParameterCheck.mandatory("asset", asset);
if (! isWebProjectStagingSandbox(asset.getSandboxId()))
{
return avmService.getContentWriter(asset.getAvmPath(), true);
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + asset.getSandboxId());
}
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getContentReader(org.alfresco.wcm.asset.AssetInfo)
*/
public ContentReader getContentReader(AssetInfo asset)
{
ParameterCheck.mandatory("asset", asset);
return avmService.getContentReader(asset.getSandboxVersion(), asset.getAvmPath());
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getAssetWebApp(java.lang.String, java.lang.String, java.lang.String)
*/
public AssetInfo getAssetWebApp(String sbStoreId, String webApp, String pathRelativeToWebApp)
{
return getAssetWebApp(sbStoreId, webApp, pathRelativeToWebApp, false);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getAssetWebApp(java.lang.String, java.lang.String, java.lang.String, boolean)
*/
public AssetInfo getAssetWebApp(String sbStoreId, String webApp, String pathRelativeToWebApp, boolean includeDeleted)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("webApp", webApp);
ParameterCheck.mandatoryString("pathRelativeToWebApp", pathRelativeToWebApp);
pathRelativeToWebApp = AVMUtil.addLeadingSlash(pathRelativeToWebApp);
String avmPath = WCMUtil.buildStoreWebappPath(sbStoreId, webApp) + pathRelativeToWebApp;
return getAssetAVM(-1, avmPath, includeDeleted);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getAsset(java.lang.String, java.lang.String)
*/
public AssetInfo getAsset(String sbStoreId, String path)
{
return getAsset(sbStoreId, -1, path, false);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getAsset(java.lang.String, int, java.lang.String, boolean)
*/
public AssetInfo getAsset(String sbStoreId, int version, String path, boolean includeDeleted)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("path", path);
String avmPath = AVMUtil.buildAVMPath(sbStoreId, path);
return getAssetAVM(version, avmPath, includeDeleted);
}
private AssetInfo getAssetAVM(int version, String avmPath, boolean includeDeleted)
{
ParameterCheck.mandatoryString("avmPath", avmPath);
AVMNodeDescriptor node = avmService.lookup(version, avmPath, includeDeleted);
AssetInfo asset = null;
if (node != null)
{
String lockOwner = null;
if (avmLockingService != null)
{
String wpStoreId = WCMUtil.getWebProjectStoreIdFromPath(avmPath);
String[] parts = WCMUtil.splitPath(avmPath);
lockOwner = getLockOwner(wpStoreId, parts[1]);
}
asset = new AssetInfoImpl(version, node, lockOwner);
}
return asset;
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getLockOwner(org.alfresco.wcm.asset.AssetInfo)
*/
public String getLockOwner(AssetInfo asset)
{
ParameterCheck.mandatory("asset", asset);
return getLockOwner(WCMUtil.getWebProjectStoreId(asset.getSandboxId()), asset.getPath());
}
private String getLockOwner(String wpStoreId, String filePath)
{
String lockOwner = null;
if (avmLockingService != null)
{
AVMLock lock = avmLockingService.getLock(wpStoreId, filePath);
if (lock != null)
{
// for now assume single lock owner (if more than one, then return first in list)
List<String> lockUsers = lock.getOwners();
if (lockUsers.size() > 0)
{
lockOwner = lockUsers.get(0);
}
}
}
return lockOwner;
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#hasLockAccess(org.alfresco.wcm.asset.AssetInfo)
*/
public boolean hasLockAccess(AssetInfo asset)
{
ParameterCheck.mandatory("asset", asset);
return avmLockingService.hasAccess(WCMUtil.getWebProjectStoreId(asset.getSandboxId()), asset.getAvmPath(), AuthenticationUtil.getFullyAuthenticatedUser());
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#updateAssetProperties(org.alfresco.wcm.asset.AssetInfo, java.util.Map)
*/
public void updateAssetProperties(AssetInfo asset, Map<QName, Serializable> properties)
{
ParameterCheck.mandatory("asset", asset);
ParameterCheck.mandatory("properties", properties);
NodeRef avmNodeRef = AVMNodeConverter.ToNodeRef(-1, asset.getAvmPath());
for (Map.Entry<QName, Serializable> prop : properties.entrySet())
{
avmNodeService.setProperty(avmNodeRef, prop.getKey(), prop.getValue());
}
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#setAssetProperties(org.alfresco.wcm.asset.AssetInfo, java.util.Map)
*/
public void setAssetProperties(AssetInfo asset, Map<QName, Serializable> properties)
{
ParameterCheck.mandatory("asset", asset);
ParameterCheck.mandatory("properties", properties);
setProperties(asset.getAvmPath(), properties);
}
private void setProperties(String avmPath, Map<QName, Serializable> properties)
{
NodeRef avmNodeRef = AVMNodeConverter.ToNodeRef(-1, avmPath);
avmNodeService.setProperties(avmNodeRef, properties);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#addAspect(org.alfresco.wcm.asset.AssetInfo, org.alfresco.service.namespace.QName, java.util.Map)
*/
public void addAspect(AssetInfo asset, QName aspectName, Map<QName, Serializable> properties)
{
addAspect(asset.getAvmPath(), aspectName, properties);
}
private void addAspect(String avmPath, QName aspect, Map<QName, Serializable> properties)
{
NodeRef avmNodeRef = AVMNodeConverter.ToNodeRef(-1, avmPath);
avmNodeService.addAspect(avmNodeRef, aspect, properties);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#removeAspect(org.alfresco.wcm.asset.AssetInfo, org.alfresco.service.namespace.QName)
*/
public void removeAspect(AssetInfo asset, QName aspectName)
{
ParameterCheck.mandatory("asset", asset);
NodeRef avmNodeRef = AVMNodeConverter.ToNodeRef(-1, asset.getAvmPath());
avmNodeService.removeAspect(avmNodeRef, aspectName);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getAspects(org.alfresco.wcm.asset.AssetInfo)
*/
public Set<QName> getAspects(AssetInfo asset)
{
ParameterCheck.mandatory("asset", asset);
NodeRef avmNodeRef = AVMNodeConverter.ToNodeRef(asset.getSandboxVersion(), asset.getAvmPath());
return avmNodeService.getAspects(avmNodeRef);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#hasAspect(org.alfresco.wcm.asset.AssetInfo, org.alfresco.service.namespace.QName)
*/
public boolean hasAspect(AssetInfo asset, QName aspectName)
{
ParameterCheck.mandatory("asset", asset);
NodeRef avmNodeRef = AVMNodeConverter.ToNodeRef(asset.getSandboxVersion(), asset.getAvmPath());
return avmNodeService.hasAspect(avmNodeRef, aspectName);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#getAssetProperties(org.alfresco.wcm.asset.AssetInfo)
*/
public Map<QName, Serializable> getAssetProperties(AssetInfo asset)
{
ParameterCheck.mandatory("asset", asset);
return getProperties(asset.getSandboxVersion(), asset.getAvmPath());
}
private Map<QName, Serializable> getProperties(int version, String avmPath)
{
NodeRef avmNodeRef = AVMNodeConverter.ToNodeRef(version, avmPath);
return avmNodeService.getProperties(avmNodeRef); // note: includes built-in properties
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#listAssetsWebApp(java.lang.String, java.lang.String, java.lang.String, boolean)
*/
public List<AssetInfo> listAssetsWebApp(String sbStoreId, String webApp, String parentFolderPathRelativeToWebApp, boolean includeDeleted)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("webApp", webApp);
ParameterCheck.mandatoryString("parentFolderPathRelativeToWebApp", parentFolderPathRelativeToWebApp);
parentFolderPathRelativeToWebApp = AVMUtil.addLeadingSlash(parentFolderPathRelativeToWebApp);
String avmPath = WCMUtil.buildStoreWebappPath(sbStoreId, webApp) + parentFolderPathRelativeToWebApp;
return listAssetsAVM(-1, avmPath, includeDeleted);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#listAssets(java.lang.String, java.lang.String, boolean)
*/
public List<AssetInfo> listAssets(String sbStoreId, String parentFolderPath, boolean includeDeleted)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("parentFolderPath", parentFolderPath);
String avmPath = AVMUtil.buildAVMPath(sbStoreId, parentFolderPath);
return listAssetsAVM(-1, avmPath, includeDeleted);
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#listAssets(java.lang.String, int, java.lang.String, boolean)
*/
public List<AssetInfo> listAssets(String sbStoreId, int version, String parentFolderPath, boolean includeDeleted)
{
ParameterCheck.mandatoryString("sbStoreId", sbStoreId);
ParameterCheck.mandatoryString("parentFolderPath", parentFolderPath);
String avmPath = AVMUtil.buildAVMPath(sbStoreId, parentFolderPath);
return listAssetsAVM(version, avmPath, includeDeleted);
}
private List<AssetInfo> listAssetsAVM(int version, String avmPath, boolean includeDeleted)
{
ParameterCheck.mandatoryString("avmPath", avmPath);
Map<String, AVMNodeDescriptor> nodes = avmService.getDirectoryListing(version, avmPath, includeDeleted);
List<AssetInfo> assets = new ArrayList<AssetInfo>(nodes.size());
for (AVMNodeDescriptor node : nodes.values())
{
String lockOwner = null;
if (avmLockingService != null)
{
String wpStoreId = WCMUtil.getWebProjectStoreIdFromPath(avmPath);
String[] parts = WCMUtil.splitPath(avmPath);
lockOwner = getLockOwner(wpStoreId, parts[1]);
}
assets.add(new AssetInfoImpl(version, node, lockOwner));
}
return assets;
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#deleteAsset(org.alfresco.wcm.asset.AssetInfo)
*/
public void deleteAsset(AssetInfo asset)
{
ParameterCheck.mandatory("asset", asset);
if (! isWebProjectStagingSandbox(asset.getSandboxId()))
{
avmService.removeNode(asset.getAvmPath());
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + asset.getSandboxId());
}
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#renameAsset(org.alfresco.wcm.asset.AssetInfo, java.lang.String)
*/
public AssetInfo renameAsset(AssetInfo asset, String newName)
{
ParameterCheck.mandatory("asset", asset);
if (! isWebProjectStagingSandbox(asset.getSandboxId()))
{
String avmParentPath = AVMUtil.splitBase(asset.getAvmPath())[0];
String oldName = asset.getName();
avmService.rename(avmParentPath, oldName, avmParentPath, newName);
return getAsset(asset.getSandboxId(), WCMUtil.getStoreRelativePath(avmParentPath)+"/"+newName);
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + asset.getSandboxId());
}
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#moveAsset(org.alfresco.wcm.asset.AssetInfo, java.lang.String)
*/
public AssetInfo moveAsset(AssetInfo asset, String parentFolderPath)
{
ParameterCheck.mandatory("asset", asset);
if (! isWebProjectStagingSandbox(asset.getSandboxId()))
{
String avmDstPath = AVMUtil.buildAVMPath(asset.getSandboxId(), parentFolderPath);
String avmSrcPath = AVMUtil.splitBase(asset.getAvmPath())[0];
String name = asset.getName();
avmService.rename(avmSrcPath, name, avmDstPath, name);
return getAsset(asset.getSandboxId(), WCMUtil.getStoreRelativePath(avmDstPath)+"/"+name);
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + asset.getSandboxId());
}
}
/* (non-Javadoc)
* @see org.alfresco.wcm.asset.AssetService#copyAsset(org.alfresco.wcm.asset.AssetInfo, java.lang.String)
*/
public AssetInfo copyAsset(AssetInfo asset, String parentFolderPath)
{
ParameterCheck.mandatory("asset", asset);
if (! isWebProjectStagingSandbox(asset.getSandboxId()))
{
String avmDstParentPath = AVMUtil.buildAVMPath(asset.getSandboxId(), parentFolderPath);
String avmSrcPath = asset.getAvmPath();
String name = asset.getName();
avmService.copy(-1, avmSrcPath, avmDstParentPath, name);
return getAsset(asset.getSandboxId(), WCMUtil.getStoreRelativePath(avmDstParentPath+"/"+name));
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + asset.getSandboxId());
}
}
// TODO should this be in sandbox service ?
public void bulkImport(String sbStoreId, String parentFolderPath, File zipFile, boolean isHighByteZip)
{
if (! isWebProjectStagingSandbox(sbStoreId))
{
String avmDstPath = AVMUtil.buildAVMPath(sbStoreId, parentFolderPath);
// convert the AVM path to a NodeRef so we can use the NodeService to perform import
NodeRef importRef = AVMNodeConverter.ToNodeRef(-1, avmDstPath);
processZipImport(zipFile, isHighByteZip, importRef);
// After a bulk import, snapshot the store
avmService.createSnapshot(sbStoreId, "Import of file: " + zipFile.getName(), null);
// Bind the post-commit transaction listener with data required for virtualization server notification
UpdateSandboxTransactionListener tl = new UpdateSandboxTransactionListener(avmDstPath);
AlfrescoTransactionSupport.bindListener(tl);
}
else
{
throw new AccessDeniedException("Not allowed to write in: " + sbStoreId);
}
}
/**
* Process ZIP file for import into an AVM repository store location
*
* @param file ZIP format file
* @param rootRef Root reference of the AVM location to import into
*/
private void processZipImport(File file, boolean isHighByteZip, NodeRef rootRef)
{
try
{
// NOTE: This encoding allows us to workaround bug:
// http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4820807
ZipFile zipFile = new ZipFile(file, isHighByteZip ? "Cp437" : null);
File alfTempDir = TempFileProvider.getTempDir();
// build a temp dir name based on the name of the file we are importing
File tempDir = new File(alfTempDir.getPath() + File.separatorChar + file.getName() + "_unpack");
try
{
ImporterActionExecuter.extractFile(zipFile, tempDir.getPath());
importDirectory(tempDir.getPath(), rootRef);
}
finally
{
if (tempDir.exists())
{
ImporterActionExecuter.deleteDir(tempDir);
}
}
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("Unable to process Zip file. File may not be of the expected format.", e);
}
}
/**
* Recursively import a directory structure into the specified root node
*
* @param dir The directory of files and folders to import
* @param root The root node to import into
*/
private void importDirectory(String dir, NodeRef root)
{
File topdir = new File(dir);
if (!topdir.exists()) return;
for (File file : topdir.listFiles())
{
try
{
if (file.isFile())
{
// Create a file in the AVM store
String avmPath = AVMNodeConverter.ToAVMVersionPath(root).getSecond();
String fileName = file.getName();
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>();
titledProps.put(ContentModel.PROP_TITLE, fileName);
createFileAVM(avmPath, fileName, new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE));
addAspect(avmPath, ContentModel.ASPECT_TITLED, titledProps);
}
else
{
// Create a directory in the AVM store
String avmPath = AVMNodeConverter.ToAVMVersionPath(root).getSecond();
createFolderAVM(avmPath, file.getName(), null);
String folderPath = avmPath + '/' + file.getName();
NodeRef folderRef = AVMNodeConverter.ToNodeRef(-1, folderPath);
importDirectory(file.getPath(), folderRef);
}
}
catch (FileNotFoundException e)
{
// TODO: add failed file info to status message?
throw new AlfrescoRuntimeException("Failed to process ZIP file.", e);
}
catch (FileExistsException e)
{
// TODO: add failed file info to status message?
throw new AlfrescoRuntimeException("Failed to process ZIP file.", e);
}
}
}
/**
* Update Sandbox Transaction listener - invoked after bulk import
*/
private class UpdateSandboxTransactionListener extends TransactionListenerAdapter
{
private String virtUpdatePath;
public UpdateSandboxTransactionListener(String virtUpdatePath)
{
this.virtUpdatePath = virtUpdatePath;
}
/**
* @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit()
*/
@Override
public void afterCommit()
{
// Reload virtualisation server as required
if (this.virtUpdatePath != null)
{
WCMUtil.updateVServerWebapp(virtServerRegistry, this.virtUpdatePath, true);
}
}
}
}