diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/messages/action-service.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/messages/action-service.properties
index 5c6a7d4daf..c0d8b967b9 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/messages/action-service.properties
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/messages/action-service.properties
@@ -36,4 +36,5 @@ rm.action.records_only_undeclared=Only records can be completed.
rm.action.event-not-undone=The event {0} can't be undone, because it's not defined on the disposition lifecycle.
rm.action.node-not-record-category=The disposition schedule could not be created, because the actioned upon node ({0}) was not a record category.
rm.action.parameter-not-supplied=The parameter ''{0}'' has not been supplied.
-rm.action.delete-not-hold-type=The hold couldn't be deleted, because the node isn't of type {0}. (actionedUponNodeRef={1})
\ No newline at end of file
+rm.action.delete-not-hold-type=The hold couldn't be deleted, because the node isn't of type {0}. (actionedUponNodeRef={1})
+rm.action.cast-to-rm-type=Cannot cast to RM type.
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordsManagementContainerType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordsManagementContainerType.java
index 14340ae938..522cd5d96e 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordsManagementContainerType.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordsManagementContainerType.java
@@ -44,6 +44,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
+import org.springframework.extensions.surf.util.I18NUtil;
/**
* rma:recordsManagementContainer behaviour bean.
@@ -70,6 +71,9 @@ public class RecordsManagementContainerType extends BaseBehaviourBean
/** record folder service */
protected RecordFolderService recordFolderService;
+ /** I18N */
+ private static final String MSG_CANNOT_CAST_TO_RM_TYPE = "rm.action.cast-to-rm-type";
+
/**
* @param identifierService identifier service
*/
@@ -155,7 +159,7 @@ public class RecordsManagementContainerType extends BaseBehaviourBean
// Throw exception if the type is not cm:folder
if (!ContentModel.TYPE_FOLDER.equals(childType))
{
- throw new AlfrescoRuntimeException("Record can't be created from this type.");
+ throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_CANNOT_CAST_TO_RM_TYPE));
}
// check the type of the parent to determine what 'kind' of artifact to create
NodeRef parent = childAssocRef.getParentRef();
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3450Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3450Test.java
new file mode 100644
index 0000000000..3146febbbb
--- /dev/null
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3450Test.java
@@ -0,0 +1,63 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.module.org_alfresco_module_rm.test.util.TestModel;
+import org.alfresco.util.GUID;
+import org.springframework.extensions.surf.util.I18NUtil;
+
+/**
+ * Integration test for RM-3450
+ *
+ * @author Roxana Lucanu
+ * @since 2.4.1
+ */
+public class RM3450Test extends BaseRMTestCase
+{
+
+ private static final String MSG_CANNOT_CAST_TO_RM_TYPE = "rm.action.cast-to-rm-type";
+
+ public void testRM3450() throws Exception
+ {
+ doTestInTransaction(new FailureTest
+ (
+ I18NUtil.getMessage(MSG_CANNOT_CAST_TO_RM_TYPE),
+ AlfrescoRuntimeException.class
+ )
+ {
+ @Override
+ public void run() throws Exception
+ {
+ //expect failure
+ fileFolderService.create(unfiledContainer, GUID.generate(), TestModel.NOT_RM_FOLDER_TYPE).getNodeRef();
+ }
+ }, ADMIN_USER);
+ }
+
+}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/TestModel.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/TestModel.java
index 08b6854a56..15e7c45939 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/TestModel.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/TestModel.java
@@ -40,4 +40,5 @@ public interface TestModel
public static final QName ASPECT_RECORD_METADATA = QName.createQName(TEST_URI, "recordMetaData");
public static final QName PROPERTY_RECORD_METADATA = QName.createQName(TEST_URI, "recordMetaDataProperty");
+ public static final QName NOT_RM_FOLDER_TYPE = QName.createQName(TEST_URI, "notRmFolderType");
}
diff --git a/rm-community/rm-community-repo/test/resources/test-model.xml b/rm-community/rm-community-repo/test/resources/test-model.xml
index 41869338d5..9eafa717a3 100644
--- a/rm-community/rm-community-repo/test/resources/test-model.xml
+++ b/rm-community/rm-community-repo/test/resources/test-model.xml
@@ -28,6 +28,9 @@
cm:content
+
+ cm:folder
+
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordsManagementContainerTypeTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordsManagementContainerTypeTest.java
index 6f9fd8a661..7c78c6f080 100644
--- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordsManagementContainerTypeTest.java
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordsManagementContainerTypeTest.java
@@ -26,16 +26,19 @@
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
-import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
-import org.alfresco.service.cmr.repository.ChildAssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
+import org.alfresco.module.org_alfresco_module_rm.test.util.TestModel;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.junit.Test;
import org.mockito.InjectMocks;
/**
@@ -46,7 +49,7 @@ import org.mockito.InjectMocks;
public class RecordsManagementContainerTypeTest extends BaseUnitTest
{
/** test object */
- private @InjectMocks RecordsManagementContainerType recordManagementContainerType;
+ private @InjectMocks RecordsManagementContainerType recordManagementContainerType;
/**
* Having the Unfilled Record container and a folder
@@ -92,6 +95,28 @@ public class RecordsManagementContainerTypeTest extends BaseUnitTest
/* Then the node type should not be changed to TYPE_RECORD_FOLDER */
verify(mockedNodeService, never()).setType(rmFolder, TYPE_RECORD_FOLDER);
verify(mockedRecordFolderService, never()).setupRecordFolder(rmFolder);
+ }
+
+ /**
+ * Trying to create a RM folder and its sub-types via SFDC, IMap, WebDav, etc
+ * Check that exception is thrown on creating child associations
+ */
+ @Test
+ public void testRM3450()
+ {
+ NodeRef rmContainer = generateRMContainer();
+ NodeRef nonRmFolder = generateNonRmFolderNode();
+
+ ChildAssociationRef childAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, rmContainer, TestModel.NOT_RM_FOLDER_TYPE, nonRmFolder);
+ try
+ {
+ recordManagementContainerType.onCreateChildAssociation(childAssoc, true);
+ assertTrue("Expected to throw exception on create child association.", false);
+ }
+ catch (Throwable e)
+ {
+ assertTrue(e instanceof AlfrescoRuntimeException);
+ }
}
/**
@@ -121,5 +146,20 @@ public class RecordsManagementContainerTypeTest extends BaseUnitTest
when(mockedNodeService.hasAspect(rmFolder, ContentModel.ASPECT_HIDDEN)).thenReturn(hasHiddenAspect);
when(mockedNodeService.hasAspect(rmFolder, ASPECT_FILE_PLAN_COMPONENT)).thenReturn(false);
return rmFolder;
+ }
+
+ /**
+ * Generates a folder node
+ * @return reference to the created folder
+ */
+ private NodeRef generateNonRmFolderNode()
+ {
+ NodeRef nonRmFolder = generateNodeRef();
+ when(mockedDictionaryService.isSubClass(TestModel.NOT_RM_FOLDER_TYPE, ContentModel.TYPE_FOLDER)).thenReturn(true);
+ when(mockedNodeService.getType(nonRmFolder)).thenReturn(TestModel.NOT_RM_FOLDER_TYPE);
+ when(mockedNodeService.exists(nonRmFolder)).thenReturn(true);
+ when(mockedNodeService.hasAspect(nonRmFolder, ContentModel.ASPECT_HIDDEN)).thenReturn(false);
+ when(mockedNodeService.hasAspect(nonRmFolder, ASPECT_FILE_PLAN_COMPONENT)).thenReturn(false);
+ return nonRmFolder;
}
}