mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merge branch 'feature-2.4/RM-3216_ListRMFilesInIMAP' into 'release/V2.4'
Feature 2.4/rm 3216 list rm files in imap RM-3216 - IMAP:Emails messages not available after adding a file and declaring as record The problem is in Alfresco core in the method getPathFromSites from ImapServiceImpl. When declaring a file as a record the node becomes an Inplace Record and the primary parent becomes the Unfiled Records folder. The IMAP service tries to get the record path relative to the site so it goes recursively to the primary parent and checks if it reached the site node with the following condition: ```java if (nodeService.getType(ref).equals(SiteModel.TYPE_SITE)) ``` As the RM site is of type rma:rmsite this clause will fail and the method goes up to the root node which doesn't have any parent and we get a NullPointerException. The if condition should be: ```java if (dictionaryService.isSubClass(nodeService.getType(ref), SiteModel.TYPE_SITE)) ``` This is why no RM folder is listed trough IMAP. To fix the issue I extended ImapServiceImpl and overwrote the method that needed to be fixed. See merge request !107
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
|
||||||
|
<beans>
|
||||||
|
|
||||||
|
<!-- Extend Imap Service -->
|
||||||
|
<bean id="rm.imapService" abstract="true" class="org.alfresco.repo.imap.ExtendedImapServiceImpl">
|
||||||
|
<property name="dictionaryService" ref="DictionaryService"/>
|
||||||
|
<property name="authenticationUtil" ref="AuthenticationUtil"/>
|
||||||
|
</bean>
|
||||||
|
<bean class="org.alfresco.util.BeanExtender">
|
||||||
|
<property name="beanName" value="imapService" />
|
||||||
|
<property name="extendingBeanName" value="rm.imapService" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* #%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 <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.imap;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
|
import org.alfresco.repo.site.SiteModel;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the core service ImapServiceImpl functionality
|
||||||
|
*
|
||||||
|
* @author Ana Bozianu
|
||||||
|
* @since 2.4
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ExtendedImapServiceImpl extends ImapServiceImpl
|
||||||
|
{
|
||||||
|
private NodeService nodeService;
|
||||||
|
private BehaviourFilter policyBehaviourFilter;
|
||||||
|
private DictionaryService dictionaryService;
|
||||||
|
private AuthenticationUtil authenticationUtil;
|
||||||
|
|
||||||
|
public void setDictionaryService(DictionaryService dictionaryService)
|
||||||
|
{
|
||||||
|
this.dictionaryService = dictionaryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPolicyFilter(BehaviourFilter policyBehaviourFilter)
|
||||||
|
{
|
||||||
|
this.policyBehaviourFilter = policyBehaviourFilter;
|
||||||
|
super.setPolicyFilter(policyBehaviourFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
super.setNodeService(nodeService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrites the core functionality so we can list RM files in IMAP
|
||||||
|
* @see https://issues.alfresco.com/jira/browse/RM-3216
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getPathFromSites(final NodeRef ref)
|
||||||
|
{
|
||||||
|
return doAsSystem(new RunAsWork<String>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public String doWork() throws Exception
|
||||||
|
{
|
||||||
|
String name = ((String) nodeService.getProperty(ref, ContentModel.PROP_NAME)).toLowerCase();
|
||||||
|
if (dictionaryService.isSubClass(nodeService.getType(ref), SiteModel.TYPE_SITE))
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NodeRef parent = nodeService.getPrimaryParent(ref).getParentRef();
|
||||||
|
return getPathFromSites(parent) + "/" + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private <R> R doAsSystem(RunAsWork<R> work)
|
||||||
|
{
|
||||||
|
policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||||
|
policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return authenticationUtil.runAsSystem(work);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||||
|
policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* #%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 <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.imap;
|
||||||
|
|
||||||
|
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.MockAuthenticationUtilHelper;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
|
import org.alfresco.repo.site.SiteModel;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
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.QName;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.springframework.extensions.webscripts.GUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for ExtendedImapServiceImpl
|
||||||
|
* @author Ana Bozianu
|
||||||
|
*/
|
||||||
|
public class ExtendedImapServiceImplUnitTest
|
||||||
|
{
|
||||||
|
/* service mocks */
|
||||||
|
private @Mock NodeService mockedNodeService;
|
||||||
|
private @Mock BehaviourFilter mockedPolicyBehaviourFilter;
|
||||||
|
private @Mock DictionaryService mockedDictionaryService;
|
||||||
|
private @Mock AuthenticationUtil mockedAuthenticationUtil;
|
||||||
|
|
||||||
|
/* test instance of extended IMAP service implementation */
|
||||||
|
private @InjectMocks ExtendedImapServiceImpl extendedImapServiceImpl;
|
||||||
|
|
||||||
|
/* test data */
|
||||||
|
private NodeRef rmSite = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
|
||||||
|
private final String RM_SITE_NAME = "RM";
|
||||||
|
private NodeRef rmFilePlan = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
|
||||||
|
private final String RM_FILEPLAN_NAME = "fileplan";
|
||||||
|
private NodeRef rmCategory = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
|
||||||
|
private final String RM_CATEGORY_NAME = "C1";
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup()
|
||||||
|
{
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
// setup mocked authentication util
|
||||||
|
MockAuthenticationUtilHelper.setup(mockedAuthenticationUtil);
|
||||||
|
|
||||||
|
// node names
|
||||||
|
when(mockedNodeService.getProperty(rmSite, ContentModel.PROP_NAME)).thenReturn(RM_SITE_NAME);
|
||||||
|
when(mockedNodeService.getProperty(rmCategory, ContentModel.PROP_NAME)).thenReturn(RM_CATEGORY_NAME);
|
||||||
|
when(mockedNodeService.getProperty(rmFilePlan, ContentModel.PROP_NAME)).thenReturn(RM_FILEPLAN_NAME);
|
||||||
|
|
||||||
|
// node types
|
||||||
|
when(mockedNodeService.getType(rmSite)).thenReturn(RecordsManagementModel.TYPE_RM_SITE);
|
||||||
|
when(mockedNodeService.getType(rmFilePlan)).thenReturn(RecordsManagementModel.TYPE_FILE_PLAN);
|
||||||
|
when(mockedNodeService.getType(rmCategory)).thenReturn(RecordsManagementModel.TYPE_RECORD_CATEGORY);
|
||||||
|
|
||||||
|
// type hierarchy
|
||||||
|
when(mockedDictionaryService.isSubClass(RecordsManagementModel.TYPE_RM_SITE, SiteModel.TYPE_SITE)).thenReturn(true);
|
||||||
|
when(mockedDictionaryService.isSubClass(RecordsManagementModel.TYPE_FILE_PLAN, SiteModel.TYPE_SITE)).thenReturn(false);
|
||||||
|
when(mockedDictionaryService.isSubClass(RecordsManagementModel.TYPE_RECORD_CATEGORY, SiteModel.TYPE_SITE)).thenReturn(false);
|
||||||
|
|
||||||
|
// node associations
|
||||||
|
ChildAssociationRef filePlanParentAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, rmSite, QName.createQName(GUID.generate()), rmFilePlan);
|
||||||
|
when(mockedNodeService.getPrimaryParent(rmFilePlan)).thenReturn(filePlanParentAssoc);
|
||||||
|
|
||||||
|
ChildAssociationRef categoryParentAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, rmFilePlan, QName.createQName(GUID.generate()), rmCategory);
|
||||||
|
when(mockedNodeService.getPrimaryParent(rmCategory)).thenReturn(categoryParentAssoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* given the method is called on the rm site node
|
||||||
|
* check if the result is the site name
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetPathFromRMSite()
|
||||||
|
{
|
||||||
|
String rmSitePath = extendedImapServiceImpl.getPathFromSites(rmSite);
|
||||||
|
Assert.assertEquals("Incorrect return value", RM_SITE_NAME.toLowerCase(), rmSitePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* given the method is called on a rm category
|
||||||
|
* check if the result is the full path relative to the rm site
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetPathFromRMCategory()
|
||||||
|
{
|
||||||
|
String rmCategoryPath = extendedImapServiceImpl.getPathFromSites(rmCategory);
|
||||||
|
Assert.assertEquals("Incorrect return value", (RM_SITE_NAME + "/" + RM_FILEPLAN_NAME + "/" + RM_CATEGORY_NAME).toLowerCase(), rmCategoryPath);
|
||||||
|
|
||||||
|
verify(extendedImapServiceImpl).getPathFromSites(rmSite);
|
||||||
|
verify(extendedImapServiceImpl).getPathFromSites(rmFilePlan);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user