mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ACE-2682: MT: Failure occurs when creating tenant with specified contentstore directory
This is not a nice solution, nicer would be if we could allow Spring's ProxyFactoryBean to discover all the interfaces implemented by the underlying bean. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@85696 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -45,7 +45,7 @@
|
|||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Import the selected ContentStore subsystem's fileContentStore bean for use in the main repository context -->
|
<!-- Import the selected ContentStore subsystem's fileContentStore bean for use in the main repository context -->
|
||||||
<bean id="fileContentStore" class="org.alfresco.repo.management.subsystems.SubsystemProxyFactory">
|
<bean id="fileContentStore" class="org.alfresco.repo.management.subsystems.CryptodocSubsystemProxyFactory">
|
||||||
<property name="sourceApplicationContextFactory">
|
<property name="sourceApplicationContextFactory">
|
||||||
<ref bean="ContentStore" />
|
<ref bean="ContentStore" />
|
||||||
</property>
|
</property>
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
<property name="interfaces">
|
<property name="interfaces">
|
||||||
<list>
|
<list>
|
||||||
<value>org.alfresco.repo.content.ContentStore</value>
|
<value>org.alfresco.repo.content.ContentStore</value>
|
||||||
|
<value>org.alfresco.repo.content.ContentStoreCaps</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.management.subsystems;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.alfresco.repo.tenant.TenantDeployer;
|
||||||
|
import org.alfresco.repo.tenant.TenantRoutingContentStore;
|
||||||
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||||
|
|
||||||
|
|
||||||
|
public class CryptodocSubsystemProxyFactory extends SubsystemProxyFactory
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public CryptodocSubsystemProxyFactory()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
addAdvisor(0, new DefaultPointcutAdvisor(new MethodInterceptor()
|
||||||
|
{
|
||||||
|
public Object invoke(MethodInvocation mi) throws Throwable
|
||||||
|
{
|
||||||
|
Method method = mi.getMethod();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (method.getName())
|
||||||
|
{
|
||||||
|
case "getTenantRoutingContentStore":
|
||||||
|
return getTenantRoutingContentStore(mi);
|
||||||
|
case "getTenantDeployer":
|
||||||
|
return getTenantDeployer(mi);
|
||||||
|
default:
|
||||||
|
return mi.proceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvocationTargetException e)
|
||||||
|
{
|
||||||
|
// Unwrap invocation target exceptions
|
||||||
|
throw e.getTargetException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TenantDeployer getTenantDeployer(MethodInvocation mi)
|
||||||
|
{
|
||||||
|
Object bean = locateBean(mi);
|
||||||
|
if (bean instanceof TenantDeployer)
|
||||||
|
{
|
||||||
|
return (TenantDeployer) bean;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TenantRoutingContentStore getTenantRoutingContentStore(MethodInvocation mi)
|
||||||
|
{
|
||||||
|
Object bean = locateBean(mi);
|
||||||
|
if (bean instanceof TenantRoutingContentStore)
|
||||||
|
{
|
||||||
|
return (TenantRoutingContentStore) bean;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
@@ -162,7 +162,7 @@ public class SubsystemProxyFactory extends ProxyFactoryBean implements Applicati
|
|||||||
|
|
||||||
// Bring our cached copies of the source beans in line with the application context factory, using a RW lock to
|
// Bring our cached copies of the source beans in line with the application context factory, using a RW lock to
|
||||||
// ensure consistency
|
// ensure consistency
|
||||||
private Object locateBean(MethodInvocation mi)
|
protected Object locateBean(MethodInvocation mi)
|
||||||
{
|
{
|
||||||
boolean haveWriteLock = false;
|
boolean haveWriteLock = false;
|
||||||
this.lock.readLock().lock();
|
this.lock.readLock().lock();
|
||||||
|
@@ -34,6 +34,7 @@ import net.sf.acegisecurity.providers.encoding.PasswordEncoder;
|
|||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.repo.admin.RepoModelDefinition;
|
import org.alfresco.repo.admin.RepoModelDefinition;
|
||||||
import org.alfresco.repo.content.ContentStore;
|
import org.alfresco.repo.content.ContentStore;
|
||||||
|
import org.alfresco.repo.content.ContentStoreCaps;
|
||||||
import org.alfresco.repo.dictionary.DictionaryComponent;
|
import org.alfresco.repo.dictionary.DictionaryComponent;
|
||||||
import org.alfresco.repo.domain.tenant.TenantAdminDAO;
|
import org.alfresco.repo.domain.tenant.TenantAdminDAO;
|
||||||
import org.alfresco.repo.domain.tenant.TenantEntity;
|
import org.alfresco.repo.domain.tenant.TenantEntity;
|
||||||
@@ -282,11 +283,11 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
|
|||||||
// register dictionary - to allow enable/disable tenant callbacks
|
// register dictionary - to allow enable/disable tenant callbacks
|
||||||
register(dictionaryComponent);
|
register(dictionaryComponent);
|
||||||
|
|
||||||
if (tenantFileContentStore instanceof TenantDeployer)
|
if (isTenantDeployer(tenantFileContentStore))
|
||||||
{
|
{
|
||||||
// register file store - to allow enable/disable tenant callbacks
|
// register file store - to allow enable/disable tenant callbacks
|
||||||
// note: tenantFileContentStore must be registed before dictionaryRepositoryBootstrap
|
// note: tenantFileContentStore must be registed before dictionaryRepositoryBootstrap
|
||||||
register((TenantDeployer)tenantFileContentStore, 0);
|
register(tenantDeployer(tenantFileContentStore), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserTransaction userTransaction = transactionService.getUserTransaction();
|
UserTransaction userTransaction = transactionService.getUserTransaction();
|
||||||
@@ -304,7 +305,7 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
|
|||||||
|
|
||||||
for (Tenant tenant : tenants)
|
for (Tenant tenant : tenants)
|
||||||
{
|
{
|
||||||
if ((! (tenantFileContentStore instanceof TenantRoutingContentStore)) && (! tenantFileContentStore.getRootLocation().equals(tenant.getRootContentStoreDir())))
|
if ((! (isTenantRoutingContentStore(tenantFileContentStore))) && (! tenantFileContentStore.getRootLocation().equals(tenant.getRootContentStoreDir())))
|
||||||
{
|
{
|
||||||
// eg. ALF-14121 - MT will not work with replicating-content-services-context.sample if tenants are not co-mingled
|
// eg. ALF-14121 - MT will not work with replicating-content-services-context.sample if tenants are not co-mingled
|
||||||
throw new AlfrescoRuntimeException("MT: cannot start tenants - TenantRoutingContentStore is not configured AND not all tenants use co-mingled content store");
|
throw new AlfrescoRuntimeException("MT: cannot start tenants - TenantRoutingContentStore is not configured AND not all tenants use co-mingled content store");
|
||||||
@@ -438,9 +439,10 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
|
|||||||
{
|
{
|
||||||
dictionaryComponent.init();
|
dictionaryComponent.init();
|
||||||
|
|
||||||
if (tenantFileContentStore instanceof TenantDeployer)
|
if (isTenantDeployer(tenantFileContentStore))
|
||||||
{
|
{
|
||||||
((TenantDeployer)tenantFileContentStore).init();
|
TenantDeployer deployer = tenantDeployer(tenantFileContentStore);
|
||||||
|
deployer.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
// callback
|
// callback
|
||||||
@@ -553,9 +555,10 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
|
|||||||
|
|
||||||
dictionaryComponent.init();
|
dictionaryComponent.init();
|
||||||
|
|
||||||
if (tenantFileContentStore instanceof TenantDeployer)
|
if (isTenantDeployer(tenantFileContentStore))
|
||||||
{
|
{
|
||||||
((TenantDeployer)tenantFileContentStore).init();
|
TenantDeployer deployer = tenantDeployer(tenantFileContentStore);
|
||||||
|
deployer.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
// import tenant-specific stores
|
// import tenant-specific stores
|
||||||
@@ -1262,6 +1265,47 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected TenantRoutingContentStore tenantRoutingContentStore(ContentStore contentStore)
|
||||||
|
{
|
||||||
|
if (contentStore instanceof TenantRoutingContentStore)
|
||||||
|
{
|
||||||
|
return (TenantRoutingContentStore) contentStore;
|
||||||
|
}
|
||||||
|
else if (contentStore instanceof ContentStoreCaps)
|
||||||
|
{
|
||||||
|
ContentStoreCaps capabilities = (ContentStoreCaps) contentStore;
|
||||||
|
return (TenantRoutingContentStore) capabilities.getTenantRoutingContentStore();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isTenantRoutingContentStore(ContentStore contentStore)
|
||||||
|
{
|
||||||
|
boolean router = tenantRoutingContentStore(contentStore) != null;
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TenantDeployer tenantDeployer(ContentStore contentStore)
|
||||||
|
{
|
||||||
|
if (contentStore instanceof TenantDeployer)
|
||||||
|
{
|
||||||
|
return (TenantDeployer) contentStore;
|
||||||
|
}
|
||||||
|
else if (contentStore instanceof ContentStoreCaps)
|
||||||
|
{
|
||||||
|
ContentStoreCaps capabilities = (ContentStoreCaps) contentStore;
|
||||||
|
return (TenantDeployer) capabilities.getTenantDeployer();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isTenantDeployer(ContentStore contentStore)
|
||||||
|
{
|
||||||
|
boolean deployer = tenantDeployer(contentStore) != null;
|
||||||
|
return deployer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initTenant(String tenantDomain, String contentRoot, String dbUrl)
|
private void initTenant(String tenantDomain, String contentRoot, String dbUrl)
|
||||||
{
|
{
|
||||||
validateTenantName(tenantDomain);
|
validateTenantName(tenantDomain);
|
||||||
@@ -1277,7 +1321,7 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (! (tenantFileContentStore instanceof TenantRoutingContentStore))
|
if (! isTenantRoutingContentStore(tenantFileContentStore))
|
||||||
{
|
{
|
||||||
// eg. ALF-14121 - MT will not work with replicating-content-services-context.sample
|
// eg. ALF-14121 - MT will not work with replicating-content-services-context.sample
|
||||||
throw new AlfrescoRuntimeException("MT: cannot initialse tenant - TenantRoutingContentStore is not configured AND tenant is not using co-mingled content store (ie. default root location)");
|
throw new AlfrescoRuntimeException("MT: cannot initialse tenant - TenantRoutingContentStore is not configured AND tenant is not using co-mingled content store (ie. default root location)");
|
||||||
|
@@ -0,0 +1,180 @@
|
|||||||
|
package org.alfresco.repo.tenant;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.alfresco.repo.content.AbstractContentStore;
|
||||||
|
import org.alfresco.repo.content.ContentStore;
|
||||||
|
import org.alfresco.repo.content.ContentStoreCaps;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class MultiTAdminServiceImplTest
|
||||||
|
{
|
||||||
|
private MultiTAdminServiceImpl tenantAdmin;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception
|
||||||
|
{
|
||||||
|
tenantAdmin = new MultiTAdminServiceImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTenantDeployer()
|
||||||
|
{
|
||||||
|
ContentStore contentStore = new ConcreteTenantDeployer();
|
||||||
|
TenantDeployer tenantDeployer = tenantAdmin.tenantDeployer(contentStore);
|
||||||
|
assertNotNull(tenantDeployer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTenantDeployerRetrievedByContentStoreCaps()
|
||||||
|
{
|
||||||
|
ContentStore contentStore = new FakeSubsystemProxy(false);
|
||||||
|
TenantDeployer tenantDeployer = tenantAdmin.tenantDeployer(contentStore);
|
||||||
|
assertNotNull(tenantDeployer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTenantDeployerMayBeNullWhenInterfaceNotImplemented()
|
||||||
|
{
|
||||||
|
ContentStore contentStore = new BaseStore();
|
||||||
|
TenantDeployer tenantDeployer = tenantAdmin.tenantDeployer(contentStore);
|
||||||
|
assertNull(tenantDeployer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTenantDeployerMayBeNullWhenProxyingAndInterfaceNotImplemented()
|
||||||
|
{
|
||||||
|
// Represents proxy in front of non-TenantDeployer ContentStore
|
||||||
|
ContentStore contentStore = new FakeSubsystemProxy(true);
|
||||||
|
TenantDeployer tenantDeployer = tenantAdmin.tenantDeployer(contentStore);
|
||||||
|
assertNull(tenantDeployer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTenantRoutingContentStore()
|
||||||
|
{
|
||||||
|
ContentStore contentStore = new ConcreteTenantRoutingContentStore();
|
||||||
|
TenantRoutingContentStore router = tenantAdmin.tenantRoutingContentStore(contentStore);
|
||||||
|
assertNotNull(router);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTenantRoutingContentStoreRetrievedByContentStoreCaps()
|
||||||
|
{
|
||||||
|
ContentStore contentStore = new FakeSubsystemProxy(false);
|
||||||
|
TenantRoutingContentStore router = tenantAdmin.tenantRoutingContentStore(contentStore);
|
||||||
|
assertNotNull(router);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTenantRoutingContentStoreMayBeNullWhenInterfaceNotImplemented()
|
||||||
|
{
|
||||||
|
ContentStore contentStore = new BaseStore();
|
||||||
|
TenantRoutingContentStore router = tenantAdmin.tenantRoutingContentStore(contentStore);
|
||||||
|
assertNull(router);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTenantRoutingContentStoreMayBeNullWhenProxyingAndInterfaceNotImplemented()
|
||||||
|
{
|
||||||
|
// Represents proxy in front of non-TenantRoutingContentStore ContentStore
|
||||||
|
ContentStore contentStore = new FakeSubsystemProxy(true);
|
||||||
|
TenantRoutingContentStore router = tenantAdmin.tenantRoutingContentStore(contentStore);
|
||||||
|
assertNull(router);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This is implemented by the CryptodocSubsystemProxyFactory in real life.
|
||||||
|
private static class FakeSubsystemProxy extends BaseStore implements ContentStoreCaps
|
||||||
|
{
|
||||||
|
private boolean returnNull;
|
||||||
|
|
||||||
|
FakeSubsystemProxy(boolean returnNull)
|
||||||
|
{
|
||||||
|
this.returnNull = returnNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TenantDeployer getTenantRoutingContentStore()
|
||||||
|
{
|
||||||
|
// would return the underlying ContentStore bean in real life (or null).
|
||||||
|
return returnNull ? null : new ConcreteTenantRoutingContentStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TenantDeployer getTenantDeployer()
|
||||||
|
{
|
||||||
|
// would return the underlying ContentStore bean in real life (or null).
|
||||||
|
return returnNull ? null : new ConcreteTenantDeployer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteTenantDeployer extends BaseStore implements TenantDeployer
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onEnableTenant()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisableTenant()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteTenantRoutingContentStore extends BaseStore implements TenantRoutingContentStore
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onEnableTenant()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisableTenant()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BaseStore extends AbstractContentStore
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWriteSupported()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentReader getReader(String contentUrl)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user