it.openutils.mgnlutils.test.AbstractRepositoryTestcase Maven / Gradle / Ivy
/**
*
* Test utilities for Magnolia CMS (http://www.openmindlab.com/lab/products/mgnltests.html)
* Copyright(C) 2009-2015, Openmind S.r.l. http://www.openmindonline.it
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package it.openutils.mgnlutils.test;
import info.magnolia.cms.core.Path;
import info.magnolia.cms.core.SystemProperty;
import info.magnolia.cms.security.AccessManager;
import info.magnolia.cms.security.DummyUser;
import info.magnolia.cms.security.MgnlGroupManager;
import info.magnolia.cms.security.MgnlRoleManager;
import info.magnolia.cms.security.PermissionUtil;
import info.magnolia.cms.security.Realm;
import info.magnolia.cms.security.SecuritySupport;
import info.magnolia.cms.security.SecuritySupportImpl;
import info.magnolia.cms.security.SystemUserManager;
import info.magnolia.cms.util.ClasspathResourcesUtil;
import info.magnolia.cms.util.ContentUtil;
import info.magnolia.content2bean.Content2BeanException;
import info.magnolia.content2bean.Content2BeanProcessor;
import info.magnolia.content2bean.Content2BeanUtil;
import info.magnolia.content2bean.TypeMapping;
import info.magnolia.content2bean.impl.Content2BeanProcessorImpl;
import info.magnolia.content2bean.impl.TypeMappingImpl;
import info.magnolia.context.MgnlContext;
import info.magnolia.context.SystemContext;
import info.magnolia.context.SystemRepositoryStrategy;
import info.magnolia.importexport.BootstrapUtil;
import info.magnolia.init.MagnoliaConfigurationProperties;
import info.magnolia.init.properties.ClasspathPropertySource;
import info.magnolia.init.properties.InitPathsPropertySource;
import info.magnolia.init.properties.ModulePropertiesSource;
import info.magnolia.jcr.wrapper.DelegateSessionWrapper;
import info.magnolia.module.ModuleLifecycle;
import info.magnolia.module.ModuleLifecycleContextImpl;
import info.magnolia.module.ModuleManagementException;
import info.magnolia.module.ModuleManager;
import info.magnolia.module.ModuleManagerImpl;
import info.magnolia.module.ModuleRegistry;
import info.magnolia.module.ModuleRegistryImpl;
import info.magnolia.module.model.ModuleDefinition;
import info.magnolia.module.model.reader.BetwixtModuleDefinitionReader;
import info.magnolia.module.model.reader.DependencyCheckerImpl;
import info.magnolia.objectfactory.Components;
import info.magnolia.objectfactory.configuration.ComponentConfiguration;
import info.magnolia.objectfactory.configuration.ComponentProviderConfiguration;
import info.magnolia.objectfactory.configuration.ComponentProviderConfigurationBuilder;
import info.magnolia.objectfactory.configuration.ConfiguredComponentConfiguration;
import info.magnolia.objectfactory.configuration.ImplementationConfiguration;
import info.magnolia.objectfactory.configuration.InstanceConfiguration;
import info.magnolia.objectfactory.configuration.ProviderConfiguration;
import info.magnolia.repository.DefaultRepositoryManager;
import info.magnolia.repository.RepositoryConstants;
import info.magnolia.repository.RepositoryManager;
import info.magnolia.test.ComponentsTestUtil;
import info.magnolia.test.FixedModuleDefinitionReader;
import info.magnolia.test.TestMagnoliaConfigurationProperties;
import info.magnolia.test.TestMagnoliaInitPaths;
import info.magnolia.test.mock.MockContext;
import info.magnolia.test.mock.MockWebContext;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.jcr.ImportUUIDBehavior;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.EventListenerIterator;
import javax.jcr.observation.ObservationManager;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.jndi.BindableRepository;
import org.apache.log4j.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Generic version of Magnolia RepositoryTestcase, as found in magnolia-core test jar.
* @author fgiust
* @version $Id: AbstractRepositoryTestcase.java 201 2015-01-26 18:06:02Z fgiust $
*/
@RepositoryTestConfiguration
public abstract class AbstractRepositoryTestcase
{
/**
* Logger.
*/
protected Logger log = LoggerFactory.getLogger(getClass());
/**
* Setup and start the repository
* @throws Exception any exception thrown during the test setup
*/
public void setUp() throws Exception
{
// ignore mapping warnings
org.apache.log4j.Logger.getLogger(RepositoryManager.class).setLevel(Level.ERROR);
if (!this.getClass().isAnnotationPresent(RepositoryTestConfiguration.class))
{
throw new IllegalArgumentException("You should annotate your test with @RepositoryTestConfiguration");
}
// retrieve configuration from annotation
RepositoryTestConfiguration repositoryTestConfiguration = this.getClass().getAnnotation(
RepositoryTestConfiguration.class);
String repositoryConfigFileName = repositoryTestConfiguration.repositoryConfig();
String jackrabbitRepositoryConfigFileName = repositoryTestConfiguration.jackrabbitRepositoryConfig();
String magnoliaProperties = repositoryTestConfiguration.magnoliaProperties();
boolean autoStart = repositoryTestConfiguration.autostart();
boolean quiet = repositoryTestConfiguration.quiet();
boolean security = repositoryTestConfiguration.security();
initDefaultImplementations();
SystemProperty.getProperties().load(this.getClass().getResourceAsStream(magnoliaProperties));
// MockUtil.initMockContext();
final MockContext ctx = new MockWebContext()
{
@Override
public AccessManager getAccessManager(String workspace)
{
return PermissionUtil.getAccessManager(workspace, getSubject());
}
};
MgnlContext.setInstance(ctx);
ComponentsTestUtil.setImplementation(SystemContext.class, MockContext.class);
if (autoStart)
{
cleanUp();
startRepository(repositoryConfigFileName, jackrabbitRepositoryConfigFileName, quiet);
}
if (repositoryTestConfiguration != null)
{
// bootstrap files list
bootstrapFile(repositoryTestConfiguration.bootstrapFiles());
// bootstrap files from directory
if (repositoryTestConfiguration.bootstrapDirectory() != null
&& repositoryTestConfiguration.bootstrapDirectory().length > 0)
{
bootstrapDirectory(repositoryTestConfiguration.bootstrapDirectory());
}
for (ModuleConfiguration module : repositoryTestConfiguration.startModules())
{
startModule(module.name(), module.moduleclass());
}
}
if (security)
{
final SecuritySupportImpl sec = new SecuritySupportImpl();
sec.setGroupManager(new MgnlGroupManager());
sec.setRoleManager(new MgnlRoleManager());
SystemUserManager systemUserManager = new SystemUserManager();
systemUserManager.setRealmName(Realm.REALM_SYSTEM.getName());
sec.addUserManager(Realm.REALM_SYSTEM.getName(), systemUserManager);
sec.setRoleManager(new MgnlRoleManager());
sec.setGroupManager(new MgnlGroupManager());
ComponentsTestUtil.setInstance(SecuritySupport.class, sec);
}
}
/**
* Shutdown the repository, optionally deleting the containing folder.
* @throws Exception any exception thrown during the shutdown.
*/
public void tearDown() throws Exception
{
RepositoryTestConfiguration repositoryTestConfiguration = this.getClass().getAnnotation(
RepositoryTestConfiguration.class);
// if module is set it is stopped on tearDown
for (ModuleConfiguration module : repositoryTestConfiguration.startModules())
{
((ModuleLifecycle) Components.getComponent(ModuleRegistry.class).getModuleInstance(module.name()))
.stop(null);
}
if (repositoryTestConfiguration.autostart())
{
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger("info.magnolia");
final Level originalLogLevel = logger.getLevel();
if (repositoryTestConfiguration.quiet())
{
logger.setLevel(Level.WARN);
}
MgnlContext.release();
SystemContext systemContext = Components.getComponent(SystemContext.class);
RepositoryManager repositoryManager = Components.getComponent(RepositoryManager.class);
Collection workspaceNames = repositoryManager.getWorkspaceNames();
// manually cleanup active sessions to avoid duplicate closures()
for (String workspaceName : workspaceNames)
{
Session session = systemContext.getJCRSession(workspaceName);
final ObservationManager observationManager = session.getWorkspace().getObservationManager();
final EventListenerIterator listeners = observationManager.getRegisteredEventListeners();
while (listeners.hasNext())
{
observationManager.removeEventListener(listeners.nextEventListener());
}
BindableRepository br = ((BindableRepository) repositoryManager.getRepository(repositoryManager
.getWorkspaceMapping(workspaceName)
.getRepositoryName()));
final Field repoField = BindableRepository.class.getDeclaredField("repository");
repoField.setAccessible(true);
Repository repository = (Repository) repoField.get(br);
while (session instanceof DelegateSessionWrapper)
{
session = ((DelegateSessionWrapper) session).getWrappedSession();
}
final Field asclass = RepositoryImpl.class.getDeclaredField("activeSessions");
asclass.setAccessible(true);
Map activesessions = (Map) asclass.get(repository);
for (Session as : new HashSet(activesessions.keySet()))
{
((RepositoryImpl) repository).loggedOut((SessionImpl) as);
// as.logout();
}
}
systemContext.release();
repositoryManager.shutdown();
if (true)
{
cleanUp();
}
logger.setLevel(originalLogLevel);
}
ComponentsTestUtil.clear();
MgnlContext.setInstance(null);
}
// info.magnolia.test.MgnlTestCase.initDefaultImplementations()
private void initDefaultImplementations() throws IOException, ModuleManagementException
{
final List modules = getModuleDefinitionsForTests();
final ModuleRegistry mr = new ModuleRegistryImpl();
ModuleManagerImpl mm = new ModuleManagerImpl(
null,
new FixedModuleDefinitionReader(modules),
mr,
new DependencyCheckerImpl(), null);
mm.loadDefinitions();
final TestMagnoliaConfigurationProperties configurationProperties = new TestMagnoliaConfigurationProperties(
new ModulePropertiesSource(mr),
new ClasspathPropertySource("/test-magnolia.properties"),
new InitPathsPropertySource(new TestMagnoliaInitPaths()));
SystemProperty.setMagnoliaConfigurationProperties(configurationProperties);
ComponentsTestUtil.setInstance(ModuleManager.class, mm);
ComponentsTestUtil.setInstance(ModuleRegistry.class, mr);
ComponentsTestUtil.setInstance(MagnoliaConfigurationProperties.class, configurationProperties);
ComponentsTestUtil.setImplementation(RepositoryManager.class, DefaultRepositoryManager.class);
ComponentProviderConfigurationBuilder configurationBuilder = new ComponentProviderConfigurationBuilder();
ComponentProviderConfiguration configuration = configurationBuilder.getComponentsFromModules(
"system",
mr.getModuleDefinitions());
configuration.combine(configurationBuilder.getComponentsFromModules("main", mr.getModuleDefinitions()));
// Content2BeanProcessorImpl uses dependency injection and since we don't have that with MockComponentProvider
// we need to manually create this object and replace the component configuration read from core.xml
final TypeMappingImpl typeMapping = new TypeMappingImpl();
configuration.registerInstance(TypeMapping.class, typeMapping);
configuration.registerInstance(Content2BeanProcessor.class, new Content2BeanProcessorImpl(typeMapping));
for (Map.Entry entry : configuration.getComponents().entrySet())
{
ComponentConfiguration value = entry.getValue();
if (value instanceof ImplementationConfiguration)
{
ImplementationConfiguration config = (ImplementationConfiguration) value;
ComponentsTestUtil.setImplementation(config.getType(), config.getImplementation());
}
else if (value instanceof InstanceConfiguration)
{
InstanceConfiguration config = (InstanceConfiguration) value;
ComponentsTestUtil.setInstance(config.getType(), config.getInstance());
}
else if (value instanceof ProviderConfiguration)
{
ProviderConfiguration config = (ProviderConfiguration) value;
ComponentsTestUtil.setImplementation(config.getType(), config.getProviderClass());
}
else if (value instanceof ConfiguredComponentConfiguration)
{
ConfiguredComponentConfiguration config = (ConfiguredComponentConfiguration) value;
ComponentsTestUtil.setConfigured(
config.getType(),
config.getWorkspace(),
config.getPath(),
config.isObserved());
}
}
for (Map.Entry, Class< ? >> entry : configuration.getTypeMapping().entrySet())
{
ComponentsTestUtil.setImplementation((Class) entry.getKey(), (Class) entry.getValue());
}
}
// info.magnolia.test.MgnlTestCase.getModuleDefinitionsForTests()
/**
* Override this method to provide the appropriate list of modules your tests need.
*/
protected List getModuleDefinitionsForTests() throws ModuleManagementException
{
final ModuleDefinition core = new BetwixtModuleDefinitionReader()
.readFromResource("/META-INF/magnolia/core.xml");
return Collections.singletonList(core);
}
protected void modifyContextesToUseRealRepository()
{
// create a mock web context with same repository acquiring strategy as the system context
MockContext systemContext = (MockContext) MgnlContext.getSystemContext();
SystemRepositoryStrategy repositoryStrategy = Components.newInstance(SystemRepositoryStrategy.class);
systemContext.setRepositoryStrategy(repositoryStrategy);
MockContext ctx = (MockContext) MgnlContext.getInstance();
ctx.setRepositoryStrategy(repositoryStrategy);
systemContext.setUser(new DummyUser());
ctx.setUser(new DummyUser());
}
protected void startRepository(String repositoryConfigFileName, String jackrabbitRepositoryConfigFileName,
boolean quiet) throws Exception
{
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger("info.magnolia");
final Level originalLogLevel = logger.getLevel();
if (quiet)
{
logger.setLevel(Level.WARN);
}
URL repositoryConfigURL = ClasspathResourcesUtil.getResource(repositoryConfigFileName);
if (repositoryConfigURL == null)
{
throw new IllegalArgumentException("Unable to find repository config file " + repositoryConfigFileName);
}
InputStream repositoryConfigFileStream = repositoryConfigURL.openStream();
extractConfigFile("magnolia.repositories.config", repositoryConfigFileStream, "target/repositories.xml");
IOUtils.closeQuietly(repositoryConfigFileStream);
InputStream jackrabbitRepositoryConfigFileStream = ClasspathResourcesUtil.getResource(
jackrabbitRepositoryConfigFileName).openStream();
extractConfigFile(
"magnolia.repositories.jackrabbit.config",
jackrabbitRepositoryConfigFileStream,
"target/repo-conf/extracted.xml");
IOUtils.closeQuietly(jackrabbitRepositoryConfigFileStream);
Components.getComponent(RepositoryManager.class).init();
modifyContextesToUseRealRepository();
logger.setLevel(originalLogLevel);
}
private void extractConfigFile(String propertyName, InputStream configFileStream, String extractToPath)
throws Exception
{
String targetFilename = Path.getAbsoluteFileSystemPath(extractToPath);
File targetFile = new File(targetFilename);
// extract resource to the filesystem (jackrabbit can't use a stream)
new File(targetFile.getParent()).mkdirs();
IOUtils.copy(configFileStream, new FileOutputStream(targetFile));
SystemProperty.setProperty(propertyName, extractToPath);
}
private void cleanUp() throws IOException
{
FileUtils.deleteDirectory(new File(Components.getComponent(MagnoliaConfigurationProperties.class).getProperty(
"magnolia.repositories.home")));
}
/**
* Bootstrap one or more xml files.
* @param resources one or more xml files (classpath path)
* @throws RepositoryException thrown during import
* @throws IOException if there are errors while loading the files
*/
protected void bootstrapFile(String... resources) throws IOException, RepositoryException
{
BootstrapUtil.bootstrap(resources, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
}
/**
* Loads all the bootstrap files in a specified path under the classpath
* @param paths classpath path
* @throws RepositoryException thrown during import
* @throws IOException if there are errors while loading the files
*/
protected void bootstrapDirectory(final String... paths) throws IOException, RepositoryException
{
String[] resourcesToBootstrap = ClasspathResourcesUtil.findResources(new ClasspathResourcesUtil.Filter()
{
@Override
public boolean accept(final String name)
{
for (String string : paths)
{
if (StringUtils.contains(name, string) && StringUtils.endsWithIgnoreCase(name, ".xml"))
{
return true;
}
}
return false;
}
});
BootstrapUtil.bootstrap(resourcesToBootstrap, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
}
/**
* Register and starts a module
* @param modulename modulename
* @param moduleClass ModuleClass
* @throws Content2BeanException if the module configuration can't be successfully parsed.
* @return module instance
* @throws RepositoryException
*/
protected ModuleLifecycle startModule(String modulename, Class< ? extends ModuleLifecycle> moduleClass)
throws Content2BeanException, RepositoryException
{
// register and start module
String nodemoconfig = "/modules/" + modulename + "/config";
ModuleLifecycle module = null;
if (MgnlContext.getJCRSession(RepositoryConstants.CONFIG).nodeExists(nodemoconfig))
{
Node node = MgnlContext.getJCRSession(RepositoryConstants.CONFIG).getNode(
"/modules/" + modulename + "/config");
module = (ModuleLifecycle) Content2BeanUtil.toBean(ContentUtil.asContent(node), true, moduleClass);
}
else
{
module = Components.getComponent(moduleClass);
}
Components.getComponent(ModuleRegistry.class).registerModuleInstance(modulename, module);
ModuleLifecycleContextImpl lifecycleCtx = new ModuleLifecycleContextImpl();
module.start(lifecycleCtx);
return module;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy