
org.sakaiproject.component.cover.TestComponentManagerContainer Maven / Gradle / Ivy
/**********************************************************************************
* $URL$
* $Id$
***********************************************************************************
*
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.sakaiproject.component.cover;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.impl.SpringCompMgr;
import org.springframework.beans.factory.config.PropertyOverrideConfigurer;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* A container for a Test Component Manager that can be configured with one of more components.
*
*/
public class TestComponentManagerContainer {
/**
* The logger
*/
private static final Log log = LogFactory.getLog(TestComponentManagerContainer.class);
/**
* The current component manager
*/
private SpringCompMgr componentManager;
public TestComponentManagerContainer(String configPaths) throws IOException {
this(configPaths, null);
}
/**
* create a component manager based on a list of component.xml
* @param configPaths a ';' seperated list of xml bean config files
* @throws IOException
*/
public TestComponentManagerContainer(String configPaths, Properties props) throws IOException {
// we assume that all the jars are in the same classloader, so this will
// not check for
// incorrect bindings and will not fully replicate the tomcat
// experience, but is an easier environment
// to work within for kernel testing.
// For a more complex structure we could use the kernel poms in the repo
// to generate the dep list.
if ( ComponentManager.m_componentManager != null ) {
log.info("Closing existing Component Manager ");
/*
try {
ComponentManager.m_componentManager.close();
} catch ( Throwable t ) {
log.warn("Close Failed with message, safe to ignore "+t.getMessage());
}
*/
log.info("Closing Complete ");
ComponentManager.m_componentManager = null;
}
log.info("Starting Component Manager with ["+configPaths+"]");
ComponentManager.setLateRefresh(true);
componentManager = (SpringCompMgr) ComponentManager
.getInstance();
ConfigurableApplicationContext ac = componentManager
.getApplicationContext();
ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
// Supply any additional configuration.
if (props != null) {
PropertyOverrideConfigurer beanFactoryPostProcessor = new PropertyOverrideConfigurer();
beanFactoryPostProcessor.setBeanNameSeparator("@");
beanFactoryPostProcessor.setProperties(props);
ac.addBeanFactoryPostProcessor(beanFactoryPostProcessor);
}
// we could take the kernel bootstrap from from the classpath in future
// rather than from
// the filesystem
List config = new ArrayList();
String[] configPath = configPaths.split(";");
for ( String p : configPath) {
File xml = new File(p);
config.add(new FileSystemResource(xml.getCanonicalPath()));
}
loadComponent(ac, config, classLoader);
ac.refresh();
// SAK-20908 - band-aid for TLM sync issues causing tests to fail
// This sleep shouldn't be needed but it seems these tests are starting before ThreadLocalManager has finished its startup.
try {
Thread.sleep(500); // 1/2 second
log.debug("Finished starting the component manager");
} catch (InterruptedException e) {
log.error("Component manager startup interrupted...");
}
}
/**
* Load the application context using a single classloader
* @param ac The spring application context
* @param config a list of configurations represented as List of resources
* @param loader the classloader to use
*/
public void loadComponent(ConfigurableApplicationContext ac,
List config, ClassLoader loader) {
ClassLoader current = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(loader);
try {
// make a reader
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(
(BeanDefinitionRegistry) ac.getBeanFactory());
// In Spring 2, classes aren't loaded during bean parsing unless
// this
// classloader property is set.
reader.setBeanClassLoader(loader);
reader.loadBeanDefinitions(config.toArray(new Resource[0]));
} catch (Throwable t) {
log.warn("loadComponentPackage: exception loading: " + config
+ " : " + t, t);
} finally {
// restore the context loader
Thread.currentThread().setContextClassLoader(current);
}
}
/**
* get the current component manager
* @return
*/
public org.sakaiproject.component.api.ComponentManager getComponentManager() {
return componentManager;
}
/**
* Convenience method to create a somewhat unique site id for testing. Useful
* in tests that need to create a site to run tests upon.
*
* @return A string suitable for using as a site id.
*/
protected String generateSiteId() {
return "site-" + getClass().getName() + "-" + Math.floor(Math.random()*100000);
}
/**
* Returns a dynamic proxy for a service interface. Useful for testing with
* customized service implementations without needing to write custom stubs.
*
* @param clazz The service interface class
* @param handler The invocation handler that defines how the dynamic proxy should behave
*
* @return The dynamic proxy to use as a collaborator
*/
public static final Object getServiceProxy(Class clazz, InvocationHandler handler) {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] {clazz}, handler);
}
public static void setSakaiHome(String sakaiHome) {
System.setProperty("sakai.home", sakaiHome);
}
/**
* Convenience method to get a service bean from the Sakai component manager.
*
* @param beanId The id of the service
*
* @return The service, or null if the ID is not registered
*/
public Object getService(String beanId) {
try {
return componentManager.get(beanId);
} catch (Exception e) {
log.error(e);
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy