diff --git a/config/alfresco/model/contentModel.xml b/config/alfresco/model/contentModel.xml index d743bf31d7..99f90e650e 100644 --- a/config/alfresco/model/contentModel.xml +++ b/config/alfresco/model/contentModel.xml @@ -1015,6 +1015,10 @@ + + CMIS Created Checked Out + + Versionable diff --git a/source/java/org/alfresco/opencmis/CMISConnector.java b/source/java/org/alfresco/opencmis/CMISConnector.java index 82deac23d8..9931b564f4 100644 --- a/source/java/org/alfresco/opencmis/CMISConnector.java +++ b/source/java/org/alfresco/opencmis/CMISConnector.java @@ -1447,9 +1447,8 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen nodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, null); } - Map versionProperties = new HashMap(5); - versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); - versionProperties.put(VersionModel.PROP_DESCRIPTION, "Initial Version"); + // MNT-14687 : Creating a document as checkedout and then cancelling the checkout should delete the document + nodeService.addAspect(nodeRef, ContentModel.ASPECT_CMIS_CREATED_CHECKEDOUT, null); getCheckOutCheckInService().checkout(nodeRef); } diff --git a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java index 56ac596e94..aead6894a7 100644 --- a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java +++ b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java @@ -488,6 +488,7 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService,Extens nodeService.addAspect(workingCopy, ContentModel.ASPECT_LOCKABLE, null); nodeService.addAspect(nodeRef, ContentModel.ASPECT_CHECKED_OUT, null); nodeService.createAssociation(nodeRef, workingCopy, ContentModel.ASSOC_WORKING_COPY_LINK); + nodeService.removeAspect(workingCopy, ContentModel.ASPECT_CMIS_CREATED_CHECKEDOUT); } finally { @@ -648,13 +649,17 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService,Extens } } } - - if (versionProperties != null && nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE)) + + if (versionProperties != null && + nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) && + !nodeService.hasAspect(nodeRef, ContentModel.ASPECT_CMIS_CREATED_CHECKEDOUT)) { // Create the new version this.versionService.createVersion(nodeRef, versionProperties); } + nodeService.removeAspect(nodeRef, ContentModel.ASPECT_CMIS_CREATED_CHECKEDOUT); + if (keepCheckedOut == false) { // Delete the working copy @@ -728,6 +733,11 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService,Extens // Invoke policy invokeOnCancelCheckOut(nodeRef); + + if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_CMIS_CREATED_CHECKEDOUT)) + { + nodeService.deleteNode(nodeRef); + } } catch (UnableToReleaseLockException exception) { @@ -740,7 +750,7 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService,Extens return nodeRef; } - + @Override @Extend(traitAPI=CheckOutCheckInServiceTrait.class,extensionAPI=CheckOutCheckInServiceExtension.class) public NodeRef getWorkingCopy(NodeRef nodeRef) diff --git a/source/java/org/alfresco/repo/coci/WorkingCopyAspect.java b/source/java/org/alfresco/repo/coci/WorkingCopyAspect.java index bc020f4079..002ea01dbb 100644 --- a/source/java/org/alfresco/repo/coci/WorkingCopyAspect.java +++ b/source/java/org/alfresco/repo/coci/WorkingCopyAspect.java @@ -140,6 +140,11 @@ public class WorkingCopyAspect implements CopyServicePolicies.OnCopyNodePolicy, { lockService.unlock(checkedOutNodeRef, false, true); nodeService.removeAspect(checkedOutNodeRef, ContentModel.ASPECT_CHECKED_OUT); + + if (nodeService.hasAspect(checkedOutNodeRef, ContentModel.ASPECT_CMIS_CREATED_CHECKEDOUT)) + { + nodeService.deleteNode(checkedOutNodeRef); + } } finally { diff --git a/source/test-java/org/alfresco/opencmis/OpenCmisLocalTest.java b/source/test-java/org/alfresco/opencmis/OpenCmisLocalTest.java index 29f1d528a9..670301eac3 100644 --- a/source/test-java/org/alfresco/opencmis/OpenCmisLocalTest.java +++ b/source/test-java/org/alfresco/opencmis/OpenCmisLocalTest.java @@ -37,9 +37,13 @@ import org.alfresco.events.types.ContentReadRangeEvent; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.filestore.FileContentWriter; import org.alfresco.repo.events.EventPublisherForTestingOnly; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; 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.test_category.OwnJVMTestsCategory; import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.FileFilterMode.Client; @@ -56,6 +60,7 @@ import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; import org.apache.chemistry.opencmis.commons.PropertyIds; import org.apache.chemistry.opencmis.commons.SessionParameter; import org.apache.chemistry.opencmis.commons.data.ContentStream; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; import org.apache.chemistry.opencmis.commons.enums.BindingType; import org.apache.chemistry.opencmis.commons.enums.VersioningState; import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException; @@ -83,6 +88,8 @@ public class OpenCmisLocalTest extends TestCase "classpath:opencmis/opencmistest-context.xml" }; private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(CONFIG_LOCATIONS); + private static final String BEAN_NAME_AUTHENTICATION_COMPONENT = "authenticationComponent"; + private static final String MIME_PLAIN_TEXT = "text/plain"; private ThresholdOutputStreamFactory streamFactory; private EventPublisherForTestingOnly eventPublisher; @@ -436,4 +443,52 @@ public class OpenCmisLocalTest extends TestCase { void methodA(ContentStream csa, String str, ContentStream csb, ContentStream csc, int i) throws Exception; } + + /** + * MNT-14687 - Creating a document as checkedout and then cancelling the + * checkout should delete the document. + * + * This test would have fit better within CheckOutCheckInServiceImplTest but + * was added here to make use of existing methods + */ + public void testCancelCheckoutWhileInCheckedOutState() + { + ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); + CheckOutCheckInService cociService = serviceRegistry.getCheckOutCheckInService(); + + // Authenticate as system + AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean(BEAN_NAME_AUTHENTICATION_COMPONENT); + authenticationComponent.setSystemUserAsCurrentUser(); + + /* Create the document using openCmis services */ + Repository repository = getRepository("admin", "admin"); + Session session = repository.createSession(); + Folder rootFolder = session.getRootFolder(); + + // Set file properties + String docname = "myDoc-" + GUID.generate() + ".txt"; + Map props = new HashMap(); + { + props.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value()); + props.put(PropertyIds.NAME, docname); + } + + // Create some content + byte[] byteContent = "Some content".getBytes(); + InputStream stream = new ByteArrayInputStream(byteContent); + ContentStream contentStream = new ContentStreamImpl(docname, BigInteger.valueOf(byteContent.length), MIME_PLAIN_TEXT, stream); + + // Create the document + Document doc1 = rootFolder.createDocument(props, contentStream, VersioningState.CHECKEDOUT); + NodeRef doc1NodeRef = cmisIdToNodeRef(doc1.getId()); + NodeRef doc1WorkingCopy = cociService.getWorkingCopy(doc1NodeRef); + + /* Cancel Checkout */ + cociService.cancelCheckout(doc1WorkingCopy); + + /* Check if both the working copy and the document were deleted */ + NodeService nodeService = serviceRegistry.getNodeService(); + assertFalse(nodeService.exists(doc1NodeRef)); + assertFalse(nodeService.exists(doc1WorkingCopy)); + } }