mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Moving to root below branch label
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.repo.coci;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.version.VersionableAspect;
|
||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||
import org.alfresco.service.cmr.coci.CheckOutCheckInServiceException;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
import org.alfresco.service.cmr.lock.LockType;
|
||||
import org.alfresco.service.cmr.lock.UnableToReleaseLockException;
|
||||
import org.alfresco.service.cmr.repository.AspectMissingException;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
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.cmr.version.VersionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Version opertaions service implementation
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
||||
{
|
||||
/**
|
||||
* I18N labels
|
||||
*/
|
||||
private static final String MSG_ERR_BAD_COPY = "coci_service.err_bad_copy";
|
||||
private static final String MSG_WORKING_COPY_LABEL = "coci_service.working_copy_label";
|
||||
private static final String MSG_ERR_NOT_OWNER = "coci_service.err_not_owner";
|
||||
private static final String MSG_ERR_ALREADY_WORKING_COPY = "coci_service.err_workingcopy_checkout";
|
||||
private static final String MSG_ERR_NOT_AUTHENTICATED = "coci_service.err_not_authenticated";
|
||||
private static final String MSG_ERR_WORKINGCOPY_HAS_NO_MIMETYPE = "coci_service.err_workingcopy_has_no_mimetype";
|
||||
|
||||
/**
|
||||
* Extension character, used to recalculate the working copy names
|
||||
*/
|
||||
private static final String EXTENSION_CHARACTER = ".";
|
||||
|
||||
/**
|
||||
* The node service
|
||||
*/
|
||||
private NodeService nodeService;
|
||||
|
||||
/**
|
||||
* The version service
|
||||
*/
|
||||
private VersionService versionService;
|
||||
|
||||
/**
|
||||
* The lock service
|
||||
*/
|
||||
private LockService lockService;
|
||||
|
||||
/**
|
||||
* The copy service
|
||||
*/
|
||||
private CopyService copyService;
|
||||
|
||||
/**
|
||||
* The search service
|
||||
*/
|
||||
private SearchService searchService;
|
||||
|
||||
/**
|
||||
* The authentication service
|
||||
*/
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* The versionable aspect behaviour implementation
|
||||
*/
|
||||
private VersionableAspect versionableAspect;
|
||||
|
||||
/**
|
||||
* Set the node service
|
||||
*
|
||||
* @param nodeService the node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the version service
|
||||
*
|
||||
* @param versionService the version service
|
||||
*/
|
||||
public void setVersionService(VersionService versionService)
|
||||
{
|
||||
this.versionService = versionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lock service
|
||||
*
|
||||
* @param lockService the lock service
|
||||
*/
|
||||
public void setLockService(LockService lockService)
|
||||
{
|
||||
this.lockService = lockService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the copy service
|
||||
*
|
||||
* @param copyService the copy service
|
||||
*/
|
||||
public void setCopyService(
|
||||
CopyService copyService)
|
||||
{
|
||||
this.copyService = copyService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the authenticatin service
|
||||
*
|
||||
* @param authenticationService the authentication service
|
||||
*/
|
||||
public void setAuthenticationService(
|
||||
AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the search service
|
||||
*
|
||||
* @param searchService the search service
|
||||
*/
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the versionable aspect behaviour implementation
|
||||
*
|
||||
* @param versionableAspect the versionable aspect behaviour implementation
|
||||
*/
|
||||
public void setVersionableAspect(VersionableAspect versionableAspect)
|
||||
{
|
||||
this.versionableAspect = versionableAspect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the working copy label.
|
||||
*
|
||||
* @return the working copy label
|
||||
*/
|
||||
public String getWorkingCopyLabel()
|
||||
{
|
||||
return I18NUtil.getMessage(MSG_WORKING_COPY_LABEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.coci.CheckOutCheckInService#checkout(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName)
|
||||
*/
|
||||
public NodeRef checkout(
|
||||
NodeRef nodeRef,
|
||||
NodeRef destinationParentNodeRef,
|
||||
QName destinationAssocTypeQName,
|
||||
QName destinationAssocQName)
|
||||
{
|
||||
// Make sure we are no checking out a working copy node
|
||||
if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) == true)
|
||||
{
|
||||
throw new CheckOutCheckInServiceException(MSG_ERR_ALREADY_WORKING_COPY);
|
||||
}
|
||||
|
||||
// Apply the lock aspect if required
|
||||
if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE) == false)
|
||||
{
|
||||
this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_LOCKABLE, null);
|
||||
}
|
||||
|
||||
// Rename the working copy
|
||||
String copyName = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
if (this.getWorkingCopyLabel() != null && this.getWorkingCopyLabel().length() != 0)
|
||||
{
|
||||
if (copyName != null && copyName.length() != 0)
|
||||
{
|
||||
int index = copyName.lastIndexOf(EXTENSION_CHARACTER);
|
||||
if (index > 0)
|
||||
{
|
||||
// Insert the working copy label before the file extension
|
||||
copyName = copyName.substring(0, index) + " " + getWorkingCopyLabel() + copyName.substring(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simply append the working copy label onto the end of the existing name
|
||||
copyName = copyName + " " + getWorkingCopyLabel();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
copyName = getWorkingCopyLabel();
|
||||
}
|
||||
}
|
||||
|
||||
// Make the working copy
|
||||
destinationAssocQName = QName.createQName(destinationAssocQName.getNamespaceURI(), QName.createValidLocalName(copyName));
|
||||
NodeRef workingCopy = this.copyService.copy(
|
||||
nodeRef,
|
||||
destinationParentNodeRef,
|
||||
destinationAssocTypeQName,
|
||||
destinationAssocQName);
|
||||
|
||||
// Update the working copy name
|
||||
this.nodeService.setProperty(workingCopy, ContentModel.PROP_NAME, copyName);
|
||||
|
||||
// Get the user
|
||||
String userName = getUserName();
|
||||
|
||||
// Apply the working copy aspect to the working copy
|
||||
Map<QName, Serializable> workingCopyProperties = new HashMap<QName, Serializable>(1);
|
||||
workingCopyProperties.put(ContentModel.PROP_WORKING_COPY_OWNER, userName);
|
||||
this.nodeService.addAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY, workingCopyProperties);
|
||||
|
||||
// Lock the origional node
|
||||
this.lockService.lock(nodeRef, LockType.READ_ONLY_LOCK);
|
||||
|
||||
// Return the working copy
|
||||
return workingCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the authenticated users node reference
|
||||
*
|
||||
* @return the users node reference
|
||||
*/
|
||||
private String getUserName()
|
||||
{
|
||||
String un = this.authenticationService.getCurrentUserName();
|
||||
if (un != null)
|
||||
{
|
||||
return un;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CheckOutCheckInServiceException(MSG_ERR_NOT_AUTHENTICATED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.coci.CheckOutCheckInService#checkout(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public NodeRef checkout(NodeRef nodeRef)
|
||||
{
|
||||
// Find the primary parent in order to determine where to put the copy
|
||||
ChildAssociationRef childAssocRef = this.nodeService.getPrimaryParent(nodeRef);
|
||||
|
||||
// Checkout the working copy to the same destination
|
||||
return checkout(nodeRef, childAssocRef.getParentRef(), childAssocRef.getTypeQName(), childAssocRef.getQName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.version.operations.VersionOperationsService#checkin(org.alfresco.repo.ref.NodeRef, Map<String,Serializable>, java.lang.String, boolean)
|
||||
*/
|
||||
public NodeRef checkin(
|
||||
NodeRef workingCopyNodeRef,
|
||||
Map<String,Serializable> versionProperties,
|
||||
String contentUrl,
|
||||
boolean keepCheckedOut)
|
||||
{
|
||||
NodeRef nodeRef = null;
|
||||
|
||||
// Check that we have been handed a working copy
|
||||
if (this.nodeService.hasAspect(workingCopyNodeRef, ContentModel.ASPECT_WORKING_COPY) == false)
|
||||
{
|
||||
// Error since we have not been passed a working copy
|
||||
throw new AspectMissingException(ContentModel.ASPECT_WORKING_COPY, workingCopyNodeRef);
|
||||
}
|
||||
|
||||
// Check that the working node still has the copy aspect applied
|
||||
if (this.nodeService.hasAspect(workingCopyNodeRef, ContentModel.ASPECT_COPIEDFROM) == true)
|
||||
{
|
||||
// Disable versionable behaviours since we don't want the auto version policy behaviour to execute when we check-in
|
||||
this.versionableAspect.disableAutoVersion();
|
||||
try
|
||||
{
|
||||
Map<QName, Serializable> workingCopyProperties = nodeService.getProperties(workingCopyNodeRef);
|
||||
// Try and get the origional node reference
|
||||
nodeRef = (NodeRef) workingCopyProperties.get(ContentModel.PROP_COPY_REFERENCE);
|
||||
if(nodeRef == null)
|
||||
{
|
||||
// Error since the origional node can not be found
|
||||
throw new CheckOutCheckInServiceException(MSG_ERR_BAD_COPY);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Release the lock
|
||||
this.lockService.unlock(nodeRef);
|
||||
}
|
||||
catch (UnableToReleaseLockException exception)
|
||||
{
|
||||
throw new CheckOutCheckInServiceException(MSG_ERR_NOT_OWNER, exception);
|
||||
}
|
||||
|
||||
if (contentUrl != null)
|
||||
{
|
||||
ContentData contentData = (ContentData) workingCopyProperties.get(ContentModel.PROP_CONTENT);
|
||||
if (contentData == null)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(MSG_ERR_WORKINGCOPY_HAS_NO_MIMETYPE, new Object[]{workingCopyNodeRef});
|
||||
}
|
||||
else
|
||||
{
|
||||
contentData = new ContentData(
|
||||
contentUrl,
|
||||
contentData.getMimetype(),
|
||||
contentData.getSize(),
|
||||
contentData.getEncoding());
|
||||
}
|
||||
// Set the content url value onto the working copy
|
||||
this.nodeService.setProperty(
|
||||
workingCopyNodeRef,
|
||||
ContentModel.PROP_CONTENT,
|
||||
contentData);
|
||||
}
|
||||
|
||||
// Copy the contents of the working copy onto the origional
|
||||
this.copyService.copy(workingCopyNodeRef, nodeRef);
|
||||
|
||||
if (versionProperties != null && this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true)
|
||||
{
|
||||
// Create the new version
|
||||
this.versionService.createVersion(nodeRef, versionProperties);
|
||||
}
|
||||
|
||||
if (keepCheckedOut == false)
|
||||
{
|
||||
// Delete the working copy
|
||||
this.nodeService.removeAspect(workingCopyNodeRef, ContentModel.ASPECT_WORKING_COPY);
|
||||
this.nodeService.deleteNode(workingCopyNodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Re-lock the origional node
|
||||
this.lockService.lock(nodeRef, LockType.READ_ONLY_LOCK);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.versionableAspect.enableAutoVersion();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error since the copy aspect is missing
|
||||
throw new AspectMissingException(ContentModel.ASPECT_COPIEDFROM, workingCopyNodeRef);
|
||||
}
|
||||
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.coci.CheckOutCheckInService#checkin(org.alfresco.service.cmr.repository.NodeRef, Map, java.lang.String)
|
||||
*/
|
||||
public NodeRef checkin(
|
||||
NodeRef workingCopyNodeRef,
|
||||
Map<String, Serializable> versionProperties,
|
||||
String contentUrl)
|
||||
{
|
||||
return checkin(workingCopyNodeRef, versionProperties, contentUrl, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.coci.CheckOutCheckInService#checkin(org.alfresco.service.cmr.repository.NodeRef, Map)
|
||||
*/
|
||||
public NodeRef checkin(
|
||||
NodeRef workingCopyNodeRef,
|
||||
Map<String, Serializable> versionProperties)
|
||||
{
|
||||
return checkin(workingCopyNodeRef, versionProperties, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.coci.CheckOutCheckInService#cancelCheckout(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public NodeRef cancelCheckout(NodeRef workingCopyNodeRef)
|
||||
{
|
||||
NodeRef nodeRef = null;
|
||||
|
||||
// Check that we have been handed a working copy
|
||||
if (this.nodeService.hasAspect(workingCopyNodeRef, ContentModel.ASPECT_WORKING_COPY) == false)
|
||||
{
|
||||
// Error since we have not been passed a working copy
|
||||
throw new AspectMissingException(ContentModel.ASPECT_WORKING_COPY, workingCopyNodeRef);
|
||||
}
|
||||
|
||||
// Ensure that the node has the copy aspect
|
||||
if (this.nodeService.hasAspect(workingCopyNodeRef, ContentModel.ASPECT_COPIEDFROM) == true)
|
||||
{
|
||||
// Get the origional node
|
||||
nodeRef = (NodeRef)this.nodeService.getProperty(workingCopyNodeRef, ContentModel.PROP_COPY_REFERENCE);
|
||||
if (nodeRef == null)
|
||||
{
|
||||
// Error since the origional node can not be found
|
||||
throw new CheckOutCheckInServiceException(MSG_ERR_BAD_COPY);
|
||||
}
|
||||
|
||||
// Release the lock on the origional node
|
||||
this.lockService.unlock(nodeRef);
|
||||
|
||||
// Delete the working copy
|
||||
this.nodeService.removeAspect(workingCopyNodeRef, ContentModel.ASPECT_WORKING_COPY);
|
||||
this.nodeService.deleteNode(workingCopyNodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error since the copy aspect is missing
|
||||
throw new AspectMissingException(ContentModel.ASPECT_COPIEDFROM, workingCopyNodeRef);
|
||||
}
|
||||
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.coci.CheckOutCheckInService#getWorkingCopy(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public NodeRef getWorkingCopy(NodeRef nodeRef)
|
||||
{
|
||||
NodeRef workingCopy = null;
|
||||
|
||||
// Do a search to find the origional document
|
||||
ResultSet resultSet = null;
|
||||
try
|
||||
{
|
||||
resultSet = this.searchService.query(
|
||||
nodeRef.getStoreRef(),
|
||||
SearchService.LANGUAGE_LUCENE,
|
||||
"ASPECT:\"" + ContentModel.ASPECT_WORKING_COPY.toString() + "\" +@\\{http\\://www.alfresco.org/model/content/1.0\\}" + ContentModel.PROP_COPY_REFERENCE.getLocalName() + ":\"" + nodeRef.toString() + "\"");
|
||||
if (resultSet.getNodeRefs().size() != 0)
|
||||
{
|
||||
workingCopy = resultSet.getNodeRef(0);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (resultSet != null)
|
||||
{
|
||||
resultSet.close();
|
||||
}
|
||||
}
|
||||
|
||||
return workingCopy;
|
||||
}
|
||||
}
|
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.repo.coci;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.transaction.TransactionUtil;
|
||||
import org.alfresco.repo.version.VersionModel;
|
||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionService;
|
||||
import org.alfresco.service.cmr.version.VersionType;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.alfresco.util.TestWithUserUtils;
|
||||
|
||||
/**
|
||||
* Version operations service implementation unit tests
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class CheckOutCheckInServiceImplTest extends BaseSpringTest
|
||||
{
|
||||
/**
|
||||
* Services used by the tests
|
||||
*/
|
||||
private NodeService nodeService;
|
||||
private CheckOutCheckInService cociService;
|
||||
private ContentService contentService;
|
||||
private VersionService versionService;
|
||||
private AuthenticationService authenticationService;
|
||||
private LockService lockService;
|
||||
private TransactionService transactionService;
|
||||
private PermissionService permissionService;
|
||||
|
||||
/**
|
||||
* Data used by the tests
|
||||
*/
|
||||
private StoreRef storeRef;
|
||||
private NodeRef rootNodeRef;
|
||||
private NodeRef nodeRef;
|
||||
private String userNodeRef;
|
||||
|
||||
/**
|
||||
* Types and properties used by the tests
|
||||
*/
|
||||
private static final String TEST_VALUE_NAME = "myDocument.doc";
|
||||
private static final String TEST_VALUE_2 = "testValue2";
|
||||
private static final String TEST_VALUE_3 = "testValue3";
|
||||
private static final QName PROP_NAME_QNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "name");
|
||||
private static final QName PROP2_QNAME = ContentModel.PROP_DESCRIPTION;
|
||||
private static final String CONTENT_1 = "This is some content";
|
||||
private static final String CONTENT_2 = "This is the cotent modified.";
|
||||
|
||||
/**
|
||||
* User details
|
||||
*/
|
||||
//private static final String USER_NAME = "cociTest" + GUID.generate();
|
||||
private String userName;
|
||||
private static final String PWD = "password";
|
||||
|
||||
/**
|
||||
* On setup in transaction implementation
|
||||
*/
|
||||
@Override
|
||||
protected void onSetUpInTransaction()
|
||||
throws Exception
|
||||
{
|
||||
// Set the services
|
||||
this.nodeService = (NodeService)this.applicationContext.getBean("nodeService");
|
||||
this.cociService = (CheckOutCheckInService)this.applicationContext.getBean("checkOutCheckInService");
|
||||
this.contentService = (ContentService)this.applicationContext.getBean("contentService");
|
||||
this.versionService = (VersionService)this.applicationContext.getBean("versionService");
|
||||
this.authenticationService = (AuthenticationService)this.applicationContext.getBean("authenticationService");
|
||||
this.lockService = (LockService)this.applicationContext.getBean("lockService");
|
||||
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
|
||||
this.permissionService = (PermissionService)this.applicationContext.getBean("permissionService");
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
|
||||
// Create the store and get the root node reference
|
||||
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(storeRef);
|
||||
|
||||
// Create the node used for tests
|
||||
ChildAssociationRef childAssocRef = this.nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}test"),
|
||||
ContentModel.TYPE_CONTENT);
|
||||
this.nodeRef = childAssocRef.getChildRef();
|
||||
this.nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_TITLED, null);
|
||||
this.nodeService.setProperty(this.nodeRef, ContentModel.PROP_NAME, TEST_VALUE_NAME);
|
||||
this.nodeService.setProperty(this.nodeRef, PROP2_QNAME, TEST_VALUE_2);
|
||||
|
||||
// Add the initial content to the node
|
||||
ContentWriter contentWriter = this.contentService.getWriter(this.nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
contentWriter.setMimetype("text/plain");
|
||||
contentWriter.setEncoding("UTF-8");
|
||||
contentWriter.putContent(CONTENT_1);
|
||||
|
||||
// Add the lock and version aspects to the created node
|
||||
this.nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
|
||||
this.nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_LOCKABLE, null);
|
||||
|
||||
// Create and authenticate the user
|
||||
this.userName = "cociTest" + GUID.generate();
|
||||
TestWithUserUtils.createUser(this.userName, PWD, this.rootNodeRef, this.nodeService, this.authenticationService);
|
||||
TestWithUserUtils.authenticateUser(this.userName, PWD, this.rootNodeRef, this.authenticationService);
|
||||
this.userNodeRef = TestWithUserUtils.getCurrentUser(this.authenticationService);
|
||||
|
||||
permissionService.setPermission(this.rootNodeRef, this.userName.toLowerCase(), PermissionService.ALL_PERMISSIONS, true);
|
||||
permissionService.setPermission(this.nodeRef, this.userName.toLowerCase(), PermissionService.ALL_PERMISSIONS, true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that creates a bag of properties for the test type
|
||||
*
|
||||
* @return bag of properties
|
||||
*/
|
||||
private Map<QName, Serializable> createTypePropertyBag()
|
||||
{
|
||||
Map<QName, Serializable> result = new HashMap<QName, Serializable>();
|
||||
result.put(PROP_NAME_QNAME, TEST_VALUE_NAME);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test checkout
|
||||
*/
|
||||
public void testCheckOut()
|
||||
{
|
||||
checkout();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private NodeRef checkout()
|
||||
{
|
||||
// Check out the node
|
||||
NodeRef workingCopy = this.cociService.checkout(
|
||||
this.nodeRef,
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}workingCopy"));
|
||||
assertNotNull(workingCopy);
|
||||
|
||||
//System.out.println(NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef));
|
||||
|
||||
// Ensure that the working copy and copy aspect has been applied
|
||||
assertTrue(this.nodeService.hasAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY));
|
||||
assertTrue(this.nodeService.hasAspect(workingCopy, ContentModel.ASPECT_COPIEDFROM));
|
||||
|
||||
// Check that the working copy owner has been set correctly
|
||||
assertEquals(this.userNodeRef, this.nodeService.getProperty(workingCopy, ContentModel.PROP_WORKING_COPY_OWNER));
|
||||
|
||||
// Check that the working copy name has been set correctly
|
||||
String workingCopyLabel = ((CheckOutCheckInServiceImpl)this.cociService).getWorkingCopyLabel();
|
||||
String workingCopyName = (String)this.nodeService.getProperty(workingCopy, PROP_NAME_QNAME);
|
||||
if (workingCopyLabel == null || workingCopyLabel.length() == 0)
|
||||
{
|
||||
assertEquals("myDocument.doc", workingCopyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
assertEquals(
|
||||
"myDocument " + workingCopyLabel + ".doc",
|
||||
workingCopyName);
|
||||
}
|
||||
|
||||
// Ensure that the content has been copied correctly
|
||||
ContentReader contentReader = this.contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT);
|
||||
assertNotNull(contentReader);
|
||||
ContentReader contentReader2 = this.contentService.getReader(workingCopy, ContentModel.PROP_CONTENT);
|
||||
assertNotNull(contentReader2);
|
||||
assertEquals(
|
||||
"The content string of the working copy should match the original immediatly after checkout.",
|
||||
contentReader.getContentString(),
|
||||
contentReader2.getContentString());
|
||||
|
||||
return workingCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test checkIn
|
||||
*/
|
||||
public void testCheckIn()
|
||||
{
|
||||
NodeRef workingCopy = checkout();
|
||||
|
||||
// Test standard check-in
|
||||
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>();
|
||||
versionProperties.put(Version.PROP_DESCRIPTION, "This is a test version");
|
||||
this.cociService.checkin(workingCopy, versionProperties);
|
||||
|
||||
// Test check-in with content
|
||||
NodeRef workingCopy3 = checkout();
|
||||
|
||||
this.nodeService.setProperty(workingCopy3, PROP_NAME_QNAME, TEST_VALUE_2);
|
||||
this.nodeService.setProperty(workingCopy3, PROP2_QNAME, TEST_VALUE_3);
|
||||
ContentWriter tempWriter = this.contentService.getWriter(workingCopy3, ContentModel.PROP_CONTENT, false);
|
||||
assertNotNull(tempWriter);
|
||||
tempWriter.putContent(CONTENT_2);
|
||||
String contentUrl = tempWriter.getContentUrl();
|
||||
Map<String, Serializable> versionProperties3 = new HashMap<String, Serializable>();
|
||||
versionProperties3.put(Version.PROP_DESCRIPTION, "description");
|
||||
versionProperties3.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
|
||||
NodeRef origNodeRef = this.cociService.checkin(workingCopy3, versionProperties3, contentUrl, true);
|
||||
assertNotNull(origNodeRef);
|
||||
|
||||
// Check the checked in content
|
||||
ContentReader contentReader = this.contentService.getReader(origNodeRef, ContentModel.PROP_CONTENT);
|
||||
assertNotNull(contentReader);
|
||||
assertEquals(CONTENT_2, contentReader.getContentString());
|
||||
|
||||
// Check that the version history is correct
|
||||
Version version = this.versionService.getCurrentVersion(origNodeRef);
|
||||
assertNotNull(version);
|
||||
assertEquals("description", version.getDescription());
|
||||
assertEquals(VersionType.MAJOR, version.getVersionType());
|
||||
NodeRef versionNodeRef = version.getFrozenStateNodeRef();
|
||||
assertNotNull(versionNodeRef);
|
||||
|
||||
// Check the verioned content
|
||||
ContentReader versionContentReader = this.contentService.getReader(versionNodeRef, ContentModel.PROP_CONTENT);
|
||||
assertNotNull(versionContentReader);
|
||||
assertEquals(CONTENT_2, versionContentReader.getContentString());
|
||||
|
||||
// Check that the name is not updated during the check-in
|
||||
assertEquals(TEST_VALUE_NAME, this.nodeService.getProperty(versionNodeRef, PROP_NAME_QNAME));
|
||||
assertEquals(TEST_VALUE_NAME, this.nodeService.getProperty(origNodeRef, PROP_NAME_QNAME));
|
||||
|
||||
// Check that the other properties are updated during the check-in
|
||||
assertEquals(TEST_VALUE_3, this.nodeService.getProperty(versionNodeRef, PROP2_QNAME));
|
||||
assertEquals(TEST_VALUE_3, this.nodeService.getProperty(origNodeRef, PROP2_QNAME));
|
||||
|
||||
// Cancel the check out after is has been left checked out
|
||||
this.cociService.cancelCheckout(workingCopy3);
|
||||
|
||||
// Test keep checked out flag
|
||||
NodeRef workingCopy2 = checkout();
|
||||
Map<String, Serializable> versionProperties2 = new HashMap<String, Serializable>();
|
||||
versionProperties2.put(Version.PROP_DESCRIPTION, "Another version test");
|
||||
this.cociService.checkin(workingCopy2, versionProperties2, null, true);
|
||||
this.cociService.checkin(workingCopy2, new HashMap<String, Serializable>(), null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test when the aspect is not set when check-in is performed
|
||||
*/
|
||||
public void testVersionAspectNotSetOnCheckIn()
|
||||
{
|
||||
// Create a bag of props
|
||||
Map<QName, Serializable> bagOfProps = createTypePropertyBag();
|
||||
bagOfProps.put(ContentModel.PROP_CONTENT, new ContentData(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, "UTF-8"));
|
||||
|
||||
// Create a new node
|
||||
ChildAssociationRef childAssocRef = this.nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}test"),
|
||||
ContentModel.TYPE_CONTENT,
|
||||
bagOfProps);
|
||||
NodeRef noVersionNodeRef = childAssocRef.getChildRef();
|
||||
|
||||
// Check out and check in
|
||||
NodeRef workingCopy = this.cociService.checkout(noVersionNodeRef);
|
||||
this.cociService.checkin(workingCopy, new HashMap<String, Serializable>());
|
||||
|
||||
// Check that the origional node has no version history dispite sending verion props
|
||||
assertNull(this.versionService.getVersionHistory(noVersionNodeRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cancel checkOut
|
||||
*/
|
||||
public void testCancelCheckOut()
|
||||
{
|
||||
NodeRef workingCopy = checkout();
|
||||
assertNotNull(workingCopy);
|
||||
|
||||
try
|
||||
{
|
||||
this.lockService.checkForLock(this.nodeRef);
|
||||
fail("The origional should be locked now.");
|
||||
}
|
||||
catch (Throwable exception)
|
||||
{
|
||||
// Good the origional is locked
|
||||
}
|
||||
|
||||
NodeRef origNodeRef = this.cociService.cancelCheckout(workingCopy);
|
||||
assertEquals(this.nodeRef, origNodeRef);
|
||||
|
||||
// The origional should no longer be locked
|
||||
this.lockService.checkForLock(origNodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the deleting a wokring copy node removed the lock on the origional node
|
||||
*/
|
||||
public void testAutoCancelCheckOut()
|
||||
{
|
||||
NodeRef workingCopy = checkout();
|
||||
assertNotNull(workingCopy);
|
||||
|
||||
try
|
||||
{
|
||||
this.lockService.checkForLock(this.nodeRef);
|
||||
fail("The origional should be locked now.");
|
||||
}
|
||||
catch (Throwable exception)
|
||||
{
|
||||
// Good the origional is locked
|
||||
}
|
||||
|
||||
// Delete the working copy
|
||||
this.nodeService.deleteNode(workingCopy);
|
||||
|
||||
// The origional should no longer be locked
|
||||
this.lockService.checkForLock(this.nodeRef);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the getWorkingCopy method
|
||||
*/
|
||||
public void testGetWorkingCopy()
|
||||
{
|
||||
NodeRef origNodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}test2"),
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
|
||||
|
||||
NodeRef wk1 = this.cociService.getWorkingCopy(origNodeRef);
|
||||
assertNull(wk1);
|
||||
|
||||
// Check the document out
|
||||
final NodeRef workingCopy = this.cociService.checkout(origNodeRef);
|
||||
|
||||
// Need to commit the transaction in order to get the indexer to run
|
||||
setComplete();
|
||||
endTransaction();
|
||||
|
||||
final NodeRef finalNodeRef = origNodeRef;
|
||||
|
||||
TransactionUtil.executeInUserTransaction(
|
||||
this.transactionService,
|
||||
new TransactionUtil.TransactionWork<Object>()
|
||||
{
|
||||
public Object doWork()
|
||||
{
|
||||
NodeRef wk2 = CheckOutCheckInServiceImplTest.this.cociService.getWorkingCopy(finalNodeRef);
|
||||
assertNotNull(wk2);
|
||||
assertEquals(workingCopy, wk2);
|
||||
|
||||
CheckOutCheckInServiceImplTest.this.cociService.cancelCheckout(workingCopy);
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//NodeRef wk3 = this.cociService.getWorkingCopy(this.nodeRef);
|
||||
//assertNull(wk3);
|
||||
}
|
||||
|
||||
}
|
139
source/java/org/alfresco/repo/coci/WorkingCopyAspect.java
Normal file
139
source/java/org/alfresco/repo/coci/WorkingCopyAspect.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.repo.coci;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
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.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
public class WorkingCopyAspect
|
||||
{
|
||||
/**
|
||||
* Policy component
|
||||
*/
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
/**
|
||||
* The node service
|
||||
*/
|
||||
private NodeService nodeService;
|
||||
|
||||
/**
|
||||
* The lock service
|
||||
*/
|
||||
private LockService lockService;
|
||||
|
||||
/**
|
||||
* Sets the policy component
|
||||
*
|
||||
* @param policyComponent the policy component
|
||||
*/
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the node service
|
||||
*
|
||||
* @param nodeService the node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the lock service
|
||||
*
|
||||
* @param lockService the lock service
|
||||
*/
|
||||
public void setLockService(LockService lockService)
|
||||
{
|
||||
this.lockService = lockService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise method
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
// Register copy behaviour for the working copy aspect
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
|
||||
ContentModel.ASPECT_WORKING_COPY,
|
||||
new JavaBehaviour(this, "onCopy"));
|
||||
|
||||
// register onBeforeDelete class behaviour for the working copy aspect
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||
ContentModel.ASPECT_WORKING_COPY,
|
||||
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||
}
|
||||
|
||||
/**
|
||||
* onCopy policy behaviour
|
||||
*
|
||||
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyNodePolicy#onCopyNode(QName, NodeRef, StoreRef, boolean, PolicyScope)
|
||||
*/
|
||||
public void onCopy(
|
||||
QName sourceClassRef,
|
||||
NodeRef sourceNodeRef,
|
||||
StoreRef destinationStoreRef,
|
||||
boolean copyToNewNode,
|
||||
PolicyScope copyDetails)
|
||||
{
|
||||
if (copyToNewNode == false)
|
||||
{
|
||||
// Make sure that the name of the node is not updated with the working copy name
|
||||
copyDetails.removeProperty(ContentModel.PROP_NAME);
|
||||
}
|
||||
|
||||
// NOTE: the working copy aspect is not added since it should not be copyied
|
||||
}
|
||||
|
||||
/**
|
||||
* beforeDeleteNode policy behaviour
|
||||
*
|
||||
* @param nodeRef the node reference about to be deleted
|
||||
*/
|
||||
public void beforeDeleteNode(NodeRef nodeRef)
|
||||
{
|
||||
// Prior to deleting a working copy the lock on the origional node should be released
|
||||
// Note: we do not call cancelCheckOut since this will also attempt to delete the node is question
|
||||
if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) == true &&
|
||||
this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_COPIEDFROM) == true)
|
||||
{
|
||||
// Get the origional node
|
||||
NodeRef origNodeRef = (NodeRef)this.nodeService.getProperty(nodeRef, ContentModel.PROP_COPY_REFERENCE);
|
||||
if (origNodeRef != null)
|
||||
{
|
||||
// Release the lock on the origional node
|
||||
this.lockService.unlock(origNodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user