From 832c1b599ec48871dc4b948fd775da9242d4c684 Mon Sep 17 00:00:00 2001 From: Britt Park Date: Mon, 18 Jun 2007 04:19:35 +0000 Subject: [PATCH] AVMLockingAwareService. A wrapper around AVMService which knows aboout locking. It works by auto-locking on write operations or throwing an AVMLockingException if the requested target is already locked to another user or to a different store in a web project. It is wired up as avmLockingAwareService, AVMLockingAwareService, and indexingAVMLockingAwareService. It isn't hooked into anything else yet. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6000 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/public-services-context.xml | 48 + .../repo/avm/AVMLockingAwareService.java | 837 ++++++++++++++++++ .../org/alfresco/repo/avm/AVMServiceTest.java | 48 + .../alfresco/repo/avm/AVMServiceTestBase.java | 13 +- .../cmr/avm/locking/AVMLockingException.java | 71 ++ 5 files changed, 1012 insertions(+), 5 deletions(-) create mode 100644 source/java/org/alfresco/repo/avm/AVMLockingAwareService.java create mode 100644 source/java/org/alfresco/service/cmr/avm/locking/AVMLockingException.java diff --git a/config/alfresco/public-services-context.xml b/config/alfresco/public-services-context.xml index cd65a37438..178f7bd714 100644 --- a/config/alfresco/public-services-context.xml +++ b/config/alfresco/public-services-context.xml @@ -747,6 +747,54 @@ + + + + + + + + + + + + + + + + + + + org.alfresco.service.cmr.avm.AVMService + + + + avmLockingAwareService + + + + avmServiceWriteTxnAdvisor + avmServiceReadTxnAdvisor + avmSnapShotTriggeredIndexingMethodInterceptor + + + + + + + + org.alfresco.service.cmr.avm.AVMService + + + + avmLockingAwareService + + + + avmSnapShotTriggeredIndexingMethodInterceptor + + + diff --git a/source/java/org/alfresco/repo/avm/AVMLockingAwareService.java b/source/java/org/alfresco/repo/avm/AVMLockingAwareService.java new file mode 100644 index 0000000000..4b6f278562 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/AVMLockingAwareService.java @@ -0,0 +1,837 @@ +/* + * 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.avm; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; + +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.avm.AVMBadArgumentException; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.avm.LayeringDescriptor; +import org.alfresco.service.cmr.avm.VersionDescriptor; +import org.alfresco.service.cmr.avm.locking.AVMLock; +import org.alfresco.service.cmr.avm.locking.AVMLockingException; +import org.alfresco.service.cmr.avm.locking.AVMLockingService; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; + +/** + * An AVMLockingService aware implemantation of AVMService. + * @author britt + */ +public class AVMLockingAwareService implements AVMService +{ + private AVMService fService; + + private AVMLockingService fLockingService; + + private AuthenticationService fAuthenticationService; + + public AVMLockingAwareService() + { + } + + public void setAvmService(AVMService service) + { + fService = service; + } + + public void setAvmLockingService(AVMLockingService service) + { + fLockingService = service; + } + + public void setAuthenticationService(AuthenticationService service) + { + fAuthenticationService = service; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#addAspect(java.lang.String, org.alfresco.service.namespace.QName) + */ + public void addAspect(String path, QName aspectName) + { + grabLock(path); + fService.addAspect(path, aspectName); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#copy(int, java.lang.String, java.lang.String, java.lang.String) + */ + public void copy(int srcVersion, String srcPath, String dstPath, String name) + { + fService.copy(srcVersion, srcPath, dstPath, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#createBranch(int, java.lang.String, java.lang.String, java.lang.String) + */ + public void createBranch(int version, String srcPath, String dstPath, + String name) + { + fService.createBranch(version, srcPath, dstPath, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#createDirectory(java.lang.String, java.lang.String) + */ + public void createDirectory(String path, String name) + { + fService.createDirectory(path, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#createFile(java.lang.String, java.lang.String) + */ + public OutputStream createFile(String path, String name) + { + grabLock(path + '/' + name); + return fService.createFile(path, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#createFile(java.lang.String, java.lang.String, java.io.InputStream) + */ + public void createFile(String path, String name, InputStream in) + { + grabLock(path + '/' + name); + fService.createFile(path, name, in); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#createLayeredDirectory(java.lang.String, java.lang.String, java.lang.String) + */ + public void createLayeredDirectory(String targetPath, String parent, + String name) + { + fService.createLayeredDirectory(targetPath, parent, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#createLayeredFile(java.lang.String, java.lang.String, java.lang.String) + */ + public void createLayeredFile(String targetPath, String parent, String name) + { + grabLock(parent + '/' + name); + fService.createLayeredFile(targetPath, parent, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#createSnapshot(java.lang.String, java.lang.String, java.lang.String) + */ + public int createSnapshot(String store, String tag, String description) + { + return fService.createSnapshot(store, tag, description); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#createStore(java.lang.String) + */ + public void createStore(String name) + { + fService.createStore(name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#deleteNodeProperties(java.lang.String) + */ + public void deleteNodeProperties(String path) + { + grabLock(path); + fService.deleteNodeProperties(path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#deleteNodeProperty(java.lang.String, org.alfresco.service.namespace.QName) + */ + public void deleteNodeProperty(String path, QName name) + { + grabLock(path); + fService.deleteNodeProperty(path, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#deleteStoreProperty(java.lang.String, org.alfresco.service.namespace.QName) + */ + public void deleteStoreProperty(String store, QName name) + { + fService.deleteStoreProperty(store, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#forceCopy(java.lang.String) + */ + public AVMNodeDescriptor forceCopy(String path) + { + grabLock(path); + return fService.forceCopy(path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getAPath(org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public Pair getAPath(AVMNodeDescriptor desc) + { + return fService.getAPath(desc); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getAspects(int, java.lang.String) + */ + public List getAspects(int version, String path) + { + return fService.getAspects(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getCommonAncestor(org.alfresco.service.cmr.avm.AVMNodeDescriptor, org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public AVMNodeDescriptor getCommonAncestor(AVMNodeDescriptor left, + AVMNodeDescriptor right) + { + return fService.getCommonAncestor(left, right); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getContentDataForRead(int, java.lang.String) + */ + public ContentData getContentDataForRead(int version, String path) + { + return fService.getContentDataForRead(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getContentDataForWrite(java.lang.String) + */ + public ContentData getContentDataForWrite(String path) + { + grabLock(path); + return fService.getContentDataForWrite(path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getContentReader(int, java.lang.String) + */ + public ContentReader getContentReader(int version, String path) + { + return fService.getContentReader(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getContentWriter(java.lang.String) + */ + public ContentWriter getContentWriter(String path) + { + grabLock(path); + return fService.getContentWriter(path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDeleted(int, java.lang.String) + */ + public List getDeleted(int version, String path) + { + return fService.getDeleted(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListing(int, java.lang.String) + */ + public SortedMap getDirectoryListing( + int version, String path) + { + return fService.getDirectoryListing(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListing(int, java.lang.String, boolean) + */ + public SortedMap getDirectoryListing( + int version, String path, boolean includeDeleted) + { + return fService.getDirectoryListing(version, path, includeDeleted); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListing(org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public SortedMap getDirectoryListing( + AVMNodeDescriptor dir) + { + return fService.getDirectoryListing(dir); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListing(org.alfresco.service.cmr.avm.AVMNodeDescriptor, boolean) + */ + public SortedMap getDirectoryListing( + AVMNodeDescriptor dir, boolean includeDeleted) + { + return fService.getDirectoryListing(dir, includeDeleted); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListingArray(int, java.lang.String, boolean) + */ + public AVMNodeDescriptor[] getDirectoryListingArray(int version, + String path, boolean includeDeleted) + { + return fService.getDirectoryListingArray(version, path, includeDeleted); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListingArray(org.alfresco.service.cmr.avm.AVMNodeDescriptor, boolean) + */ + public AVMNodeDescriptor[] getDirectoryListingArray(AVMNodeDescriptor dir, + boolean includeDeleted) + { + return fService.getDirectoryListingArray(dir, includeDeleted); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListingDirect(int, java.lang.String) + */ + public SortedMap getDirectoryListingDirect( + int version, String path) + { + return fService.getDirectoryListingDirect(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListingDirect(int, java.lang.String, boolean) + */ + public SortedMap getDirectoryListingDirect( + int version, String path, boolean includeDeleted) + { + return fService.getDirectoryListingDirect(version, path, includeDeleted); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getDirectoryListingDirect(org.alfresco.service.cmr.avm.AVMNodeDescriptor, boolean) + */ + public SortedMap getDirectoryListingDirect( + AVMNodeDescriptor dir, boolean includeDeleted) + { + return fService.getDirectoryListingDirect(dir, includeDeleted); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getFileInputStream(int, java.lang.String) + */ + public InputStream getFileInputStream(int version, String path) + { + return fService.getFileInputStream(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getFileInputStream(org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public InputStream getFileInputStream(AVMNodeDescriptor desc) + { + return fService.getFileInputStream(desc); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getFileOutputStream(java.lang.String) + */ + public OutputStream getFileOutputStream(String path) + { + grabLock(path); + return fService.getFileOutputStream(path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getHeadPaths(org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public List> getHeadPaths(AVMNodeDescriptor desc) + { + return fService.getHeadPaths(desc); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getHistory(org.alfresco.service.cmr.avm.AVMNodeDescriptor, int) + */ + public List getHistory(AVMNodeDescriptor desc, int count) + { + return fService.getHistory(desc, count); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getIndirectionPath(int, java.lang.String) + */ + public String getIndirectionPath(int version, String path) + { + return fService.getIndirectionPath(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getLatestSnapshotID(java.lang.String) + */ + public int getLatestSnapshotID(String storeName) + { + return fService.getLatestSnapshotID(storeName); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getLayeringInfo(int, java.lang.String) + */ + public LayeringDescriptor getLayeringInfo(int version, String path) + { + return fService.getLayeringInfo(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getNextVersionID(java.lang.String) + */ + public int getNextVersionID(String storeName) + { + return fService.getNextVersionID(storeName); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getNodeProperties(int, java.lang.String) + */ + public Map getNodeProperties(int version, String path) + { + return fService.getNodeProperties(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getNodeProperty(int, java.lang.String, org.alfresco.service.namespace.QName) + */ + public PropertyValue getNodeProperty(int version, String path, QName name) + { + return fService.getNodeProperty(version, path, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getPaths(org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public List> getPaths(AVMNodeDescriptor desc) + { + return fService.getPaths(desc); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getPathsInStoreHead(org.alfresco.service.cmr.avm.AVMNodeDescriptor, java.lang.String) + */ + public List> getPathsInStoreHead( + AVMNodeDescriptor desc, String store) + { + return fService.getPathsInStoreHead(desc, store); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getStore(java.lang.String) + */ + public AVMStoreDescriptor getStore(String name) + { + return fService.getStore(name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getStoreProperties(java.lang.String) + */ + public Map getStoreProperties(String store) + { + return fService.getStoreProperties(store); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getStoreProperty(java.lang.String, org.alfresco.service.namespace.QName) + */ + public PropertyValue getStoreProperty(String store, QName name) + { + return fService.getStoreProperty(store, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getStoreRoot(int, java.lang.String) + */ + public AVMNodeDescriptor getStoreRoot(int version, String name) + { + return fService.getStoreRoot(version, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getStoreVersions(java.lang.String) + */ + public List getStoreVersions(String name) + { + return fService.getStoreVersions(name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getStoreVersions(java.lang.String, java.util.Date, java.util.Date) + */ + public List getStoreVersions(String name, Date from, + Date to) + { + return fService.getStoreVersions(name, from, to); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getStores() + */ + public List getStores() + { + return fService.getStores(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#getSystemStore() + */ + public AVMStoreDescriptor getSystemStore() + { + return fService.getSystemStore(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#hasAspect(int, java.lang.String, org.alfresco.service.namespace.QName) + */ + public boolean hasAspect(int version, String path, QName aspectName) + { + return fService.hasAspect(version, path, aspectName); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#link(java.lang.String, java.lang.String, org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public void link(String parentPath, String name, AVMNodeDescriptor toLink) + { + // TODO Does this need a lock? I don't think so, but revisit. + fService.link(parentPath, name, toLink); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#lookup(int, java.lang.String) + */ + public AVMNodeDescriptor lookup(int version, String path) + { + return fService.lookup(version, path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#lookup(int, java.lang.String, boolean) + */ + public AVMNodeDescriptor lookup(int version, String path, + boolean includeDeleted) + { + return fService.lookup(version, path, includeDeleted); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#lookup(org.alfresco.service.cmr.avm.AVMNodeDescriptor, java.lang.String) + */ + public AVMNodeDescriptor lookup(AVMNodeDescriptor dir, String name) + { + return fService.lookup(dir, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#lookup(org.alfresco.service.cmr.avm.AVMNodeDescriptor, java.lang.String, boolean) + */ + public AVMNodeDescriptor lookup(AVMNodeDescriptor dir, String name, + boolean includeDeleted) + { + return fService.lookup(dir, name, includeDeleted); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#makePrimary(java.lang.String) + */ + public void makePrimary(String path) + { + fService.makePrimary(path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#makeTransparent(java.lang.String, java.lang.String) + */ + public void makeTransparent(String dirPath, String name) + { + fService.makeTransparent(dirPath, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#purgeStore(java.lang.String) + */ + public void purgeStore(String name) + { + fService.purgeStore(name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#purgeVersion(int, java.lang.String) + */ + public void purgeVersion(int version, String name) + { + fService.purgeVersion(version, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#queryStorePropertyKey(java.lang.String, org.alfresco.service.namespace.QName) + */ + public Map queryStorePropertyKey(String store, + QName keyPattern) + { + return fService.queryStorePropertyKey(store, keyPattern); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#queryStoresPropertyKeys(org.alfresco.service.namespace.QName) + */ + public Map> queryStoresPropertyKeys( + QName keyPattern) + { + return fService.queryStoresPropertyKeys(keyPattern); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#removeAspect(java.lang.String, org.alfresco.service.namespace.QName) + */ + public void removeAspect(String path, QName aspectName) + { + grabLock(path); + fService.removeAspect(path, aspectName); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#removeNode(java.lang.String, java.lang.String) + */ + public void removeNode(String parent, String name) + { + grabLock(parent + '/' + name); + fService.removeNode(parent, name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#removeNode(java.lang.String) + */ + public void removeNode(String path) + { + grabLock(path); + fService.removeNode(path); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#rename(java.lang.String, java.lang.String, java.lang.String, java.lang.String) + */ + public void rename(String srcParent, String srcName, String dstParent, + String dstName) + { + // TODO Unresolved: how to deal with directory level locking. + // TODO This assumes that the rename occurs within the same web project. + grabLock(srcParent + '/' + srcName); + fService.rename(srcParent, srcName, dstParent, dstName); + String[] srcStorePath = splitPath(srcParent + '/' + srcName); + String[] dstStorePath = splitPath(dstParent + '/' + dstName); + String webProject = getWebProject(dstStorePath[0]); + if (webProject != null) + { + fLockingService.modifyLock(webProject, srcStorePath[1], dstStorePath[1], dstStorePath[0], null, null); + } + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#renameStore(java.lang.String, java.lang.String) + */ + public void renameStore(String sourceName, String destName) + { + fService.renameStore(sourceName, destName); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#retargetLayeredDirectory(java.lang.String, java.lang.String) + */ + public void retargetLayeredDirectory(String path, String target) + { + // TODO This assumes that directories are not locked. + fService.retargetLayeredDirectory(path, target); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#revert(java.lang.String, org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public void revert(String path, AVMNodeDescriptor toRevertTo) + { + grabLock(path); + fService.revert(path, toRevertTo); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setContentData(java.lang.String, org.alfresco.service.cmr.repository.ContentData) + */ + public void setContentData(String path, ContentData data) + { + grabLock(path); + fService.setContentData(path, data); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setEncoding(java.lang.String, java.lang.String) + */ + public void setEncoding(String path, String encoding) + { + grabLock(path); + fService.setEncoding(path, encoding); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setGuid(java.lang.String, java.lang.String) + */ + public void setGuid(String path, String guid) + { + grabLock(path); + fService.setGuid(path, guid); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setMetaDataFrom(java.lang.String, org.alfresco.service.cmr.avm.AVMNodeDescriptor) + */ + public void setMetaDataFrom(String path, AVMNodeDescriptor from) + { + grabLock(path); + fService.setMetaDataFrom(path, from); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setMimeType(java.lang.String, java.lang.String) + */ + public void setMimeType(String path, String mimeType) + { + grabLock(path); + fService.setMimeType(path, mimeType); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setNodeProperties(java.lang.String, java.util.Map) + */ + public void setNodeProperties(String path, + Map properties) + { + grabLock(path); + fService.setNodeProperties(path, properties); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setNodeProperty(java.lang.String, org.alfresco.service.namespace.QName, org.alfresco.repo.domain.PropertyValue) + */ + public void setNodeProperty(String path, QName name, PropertyValue value) + { + grabLock(path); + fService.setNodeProperty(path, name, value); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setOpacity(java.lang.String, boolean) + */ + public void setOpacity(String path, boolean opacity) + { + // TODO Assumes no directory locking. + fService.setOpacity(path, opacity); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setStoreProperties(java.lang.String, java.util.Map) + */ + public void setStoreProperties(String store, Map props) + { + fService.setStoreProperties(store, props); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setStoreProperty(java.lang.String, org.alfresco.service.namespace.QName, org.alfresco.repo.domain.PropertyValue) + */ + public void setStoreProperty(String store, QName name, PropertyValue value) + { + fService.setStoreProperty(store, name, value); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#uncover(java.lang.String, java.lang.String) + */ + public void uncover(String dirPath, String name) + { + // TODO What about when this is a directory? + grabLock(dirPath + '/' + name); + fService.uncover(dirPath, name); + } + + private String[] splitPath(String path) + { + String[] storePath = path.split(":"); + if (storePath.length != 2) + { + throw new AVMBadArgumentException("Invalid Path: " + path); + } + return storePath; + } + + private String getWebProject(String name) + { + Map results = fService.queryStorePropertyKey(name, QName.createQName(null, ".dns%")); + if (results.size() != 1) + { + return null; + } + String dnsString = results.keySet().iterator().next().getLocalName(); + return dnsString.substring(dnsString.lastIndexOf('.') + 1, dnsString.length()); + } + + private void grabLock(String path) + { + String[] storePath = splitPath(path); + String webProject = getWebProject(storePath[0]); + if (webProject != null) + { + String userName = fAuthenticationService.getCurrentUserName(); + if (!fLockingService.hasAccess(webProject, path, userName)) + { + throw new AVMLockingException(userName + " does not have access to " + path); + } + if (fLockingService.getLock(webProject, storePath[1]) == null) + { + List owners = new ArrayList(); + owners.add(userName); + AVMLock lock = new AVMLock(webProject, storePath[0], storePath[1], AVMLockingService.Type.DISCRETIONARY, owners); + fLockingService.lockPath(lock); + } + } + } +} diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 453d314464..bca5f81888 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -68,6 +68,8 @@ import org.alfresco.service.cmr.avm.LayeringDescriptor; import org.alfresco.service.cmr.avm.VersionDescriptor; import org.alfresco.service.cmr.avm.deploy.DeploymentReport; import org.alfresco.service.cmr.avm.deploy.DeploymentService; +import org.alfresco.service.cmr.avm.locking.AVMLockingException; +import org.alfresco.service.cmr.avm.locking.AVMLockingService; import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncException; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; @@ -83,6 +85,7 @@ import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AccessPermission; +import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -98,6 +101,51 @@ import org.alfresco.util.Pair; */ public class AVMServiceTest extends AVMServiceTestBase { + /** + * Minimal testing of Locking Aware service. + */ + public void testLockingAwareService() + { + AVMService oldService = fService; + fService = (AVMService)fContext.getBean("AVMLockingAwareService"); + AVMLockingService lockingService = (AVMLockingService)fContext.getBean("AVMLockingService"); + AuthenticationService authService = (AuthenticationService)fContext.getBean("AuthenticationService"); + try + { + lockingService.addWebProject("main"); + fService.setStoreProperty("main", QName.createQName(null, ".dns.main"), + new PropertyValue(QName.createQName(null, "silly"), "Nothing.")); + fService.createStore("test"); + fService.setStoreProperty("test", QName.createQName(null, ".dns.test.main"), + new PropertyValue(QName.createQName(null, "silly"), "Nothing.")); + setupBasicTree0(); + authService.authenticateAsGuest(); + assertEquals(2, lockingService.getUsersLocks("admin").size()); + List diffs = fSyncService.compare(-1, "main:/", -1, "test:/", null); + fSyncService.update(diffs, null, false, false, false, false, null, null); + try + { + fService.getFileOutputStream("test:/a/b/c/foo").close(); + fail("Shouldn't be able to lock."); + } + catch (AVMLockingException ale) + { + // Do nothing. Success. + } + } + catch (Exception e) + { + e.printStackTrace(); + fail(); + } + finally + { + fService = oldService; + lockingService.removeWebProject("main"); + authService.authenticate("admin", "admin".toCharArray()); + } + } + /** * Test async indexing. * @throws Exception diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java index 84a9e83416..c181500615 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java @@ -80,7 +80,7 @@ public class AVMServiceTestBase extends TestCase */ private long fStartTime; - protected TransactionService fTransactionService; + protected static TransactionService fTransactionService; protected static IndexerAndSearcher fIndexerAndSearcher; @@ -224,7 +224,7 @@ public class AVMServiceTestBase extends TestCase /** * Setup a basic tree. */ - protected void setupBasicTree() + protected void setupBasicTree0() throws IOException { fService.createDirectory("main:/", "a"); @@ -248,10 +248,13 @@ public class AVMServiceTestBase extends TestCase writer.putContent("I am main:/a/b/c/bar"); fService.createSnapshot("main", null, null); - - + } + + protected void setupBasicTree() + throws IOException + { + setupBasicTree0(); runQueriesAgainstBasicTree("main"); - } protected void runQueriesAgainstBasicTree(String store) diff --git a/source/java/org/alfresco/service/cmr/avm/locking/AVMLockingException.java b/source/java/org/alfresco/service/cmr/avm/locking/AVMLockingException.java new file mode 100644 index 0000000000..117428de87 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/avm/locking/AVMLockingException.java @@ -0,0 +1,71 @@ +/* + * 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.service.cmr.avm.locking; + +import org.alfresco.service.cmr.avm.AVMException; + +/** + * Exception thrown when lock permission is denied. + * @author britt + */ +public class AVMLockingException extends AVMException +{ + /** + * @param msgId + */ + public AVMLockingException(String msgId) + { + super(msgId); + } + + /** + * @param msgId + * @param msgParams + */ + public AVMLockingException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + + /** + * @param msgId + * @param cause + */ + public AVMLockingException(String msgId, Throwable cause) + { + super(msgId, cause); + } + + /** + * @param msgId + * @param msgParams + * @param cause + */ + public AVMLockingException(String msgId, Object[] msgParams, Throwable cause) + { + super(msgId, msgParams, cause); + } +}