mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-17 14:21:39 +00:00
337 lines
11 KiB
Java
337 lines
11 KiB
Java
/*
|
|
* #%L
|
|
* Alfresco Data model classes
|
|
* %%
|
|
* 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.util;
|
|
|
|
import java.io.IOException;
|
|
import java.net.URL;
|
|
import java.net.URLClassLoader;
|
|
import java.util.Arrays;
|
|
import java.util.Enumeration;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.NoSuchElementException;
|
|
|
|
import org.springframework.beans.BeansException;
|
|
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
|
import org.springframework.context.ApplicationContext;
|
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|
import org.springframework.core.io.DefaultResourceLoader;
|
|
import org.springframework.core.io.Resource;
|
|
import org.springframework.core.io.ResourceLoader;
|
|
import org.springframework.web.context.support.ServletContextResourcePatternResolver;
|
|
|
|
/**
|
|
* Helper class to provide static and common access to the Spring
|
|
* {@link org.springframework.context.ApplicationContext application context}.
|
|
*
|
|
* @author Derek Hulley
|
|
*/
|
|
public abstract class BaseApplicationContextHelper
|
|
{
|
|
private static ClassPathXmlApplicationContext instance;
|
|
private static String[] usedConfiguration;
|
|
private static String[] usedClassLocations;
|
|
private static boolean useLazyLoading = false;
|
|
private static boolean noAutoStart = false;
|
|
|
|
public synchronized static ApplicationContext getApplicationContext(String[] configLocations)
|
|
{
|
|
if (configLocations == null)
|
|
{
|
|
throw new IllegalArgumentException("configLocations argument is mandatory.");
|
|
}
|
|
if (usedConfiguration != null && Arrays.deepEquals(configLocations, usedConfiguration))
|
|
{
|
|
// The configuration was used to create the current context
|
|
return instance;
|
|
}
|
|
// The config has changed so close the current context (if any)
|
|
closeApplicationContext();
|
|
|
|
if(useLazyLoading || noAutoStart) {
|
|
instance = new VariableFeatureClassPathXmlApplicationContext(configLocations);
|
|
} else {
|
|
instance = new ClassPathXmlApplicationContext(configLocations);
|
|
}
|
|
|
|
usedConfiguration = configLocations;
|
|
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Build a classloader for the given classLocations, using the thread's context class loader as its parent.
|
|
*
|
|
* @param classLocations String[]
|
|
* @return ClassLoader
|
|
* @throws IOException
|
|
*/
|
|
public static ClassLoader buildClassLoader(String[] classLocations) throws IOException
|
|
{
|
|
ResourceFinder resolver = new ResourceFinder();
|
|
// Put the test directories at the front of the classpath
|
|
Resource[] resources = resolver.getResources(classLocations);
|
|
URL[] classpath = new URL[resources.length];
|
|
for (int i = 0; i< resources.length; i++)
|
|
{
|
|
classpath[i] = resources[i].getURL();
|
|
}
|
|
// Let's give our classloader 'child-first' resource loading qualities!
|
|
return new URLClassLoader(classpath, Thread.currentThread().getContextClassLoader())
|
|
{
|
|
@Override
|
|
public URL getResource(String name)
|
|
{
|
|
URL ret = findResource(name);
|
|
return ret == null ? super.getResource(name) : ret;
|
|
}
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
@Override
|
|
public Enumeration<URL> getResources(String name) throws IOException
|
|
{
|
|
Enumeration[] tmp = new Enumeration[2];
|
|
tmp[0] = findResources(name);
|
|
tmp[1] = super.getResources(name);
|
|
return new CompoundEnumeration<URL>(tmp);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Provides a static, single instance of the application context. This method can be
|
|
* called repeatedly.
|
|
* <p/>
|
|
* If the configuration requested differs from one used previously, then the previously-created
|
|
* context is shut down.
|
|
*
|
|
* @return Returns an application context for the given configuration
|
|
*/
|
|
public synchronized static ApplicationContext getApplicationContext(String[] configLocations, String[] classLocations) throws IOException
|
|
{
|
|
if (configLocations == null)
|
|
{
|
|
throw new IllegalArgumentException("configLocations argument is mandatory.");
|
|
}
|
|
if (usedConfiguration != null && Arrays.deepEquals(configLocations, usedConfiguration) && classLocations != null && Arrays.deepEquals(classLocations, usedClassLocations))
|
|
{
|
|
// The configuration was used to create the current context
|
|
return instance;
|
|
}
|
|
// The config has changed so close the current context (if any)
|
|
closeApplicationContext();
|
|
|
|
if(useLazyLoading || noAutoStart) {
|
|
instance = new VariableFeatureClassPathXmlApplicationContext(configLocations);
|
|
} else {
|
|
instance = new ClassPathXmlApplicationContext(configLocations, false);
|
|
}
|
|
|
|
if(classLocations != null)
|
|
{
|
|
ClassLoader classLoader = buildClassLoader(classLocations);
|
|
instance.setClassLoader(classLoader);
|
|
}
|
|
|
|
instance.refresh();
|
|
|
|
usedConfiguration = configLocations;
|
|
usedClassLocations = classLocations;
|
|
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Closes and releases the application context. On the next call to
|
|
* {@link #getApplicationContext(String[])} , a new context will be given.
|
|
*/
|
|
public static synchronized void closeApplicationContext()
|
|
{
|
|
if (instance == null)
|
|
{
|
|
// Nothing to do
|
|
return;
|
|
}
|
|
instance.close();
|
|
instance = null;
|
|
usedConfiguration = null;
|
|
}
|
|
|
|
/**
|
|
* Should the Spring beans be initilised in a lazy manner, or all in one go?
|
|
* Normally lazy loading/intialising shouldn't be used when running with the
|
|
* full context, but it may be appropriate to reduce startup times when
|
|
* using a small, cut down context.
|
|
*/
|
|
public static void setUseLazyLoading(boolean lazyLoading)
|
|
{
|
|
useLazyLoading = lazyLoading;
|
|
}
|
|
|
|
/**
|
|
* Will the Spring beans be initilised in a lazy manner, or all in one go?
|
|
* The default it to load everything in one go, as spring normally does.
|
|
*/
|
|
public static boolean isUsingLazyLoading()
|
|
{
|
|
return useLazyLoading;
|
|
}
|
|
|
|
/**
|
|
* Should the autoStart=true property on subsystems be honoured, or should
|
|
* this property be ignored and the auto start prevented? Normally we will
|
|
* use the spring configuration to decide what to start, but when running
|
|
* tests, you can use this to prevent the auto start.
|
|
*/
|
|
public static void setNoAutoStart(boolean noAutoStart)
|
|
{
|
|
BaseApplicationContextHelper.noAutoStart = noAutoStart;
|
|
}
|
|
|
|
/**
|
|
* Will Subsystems with the autoStart=true property set on them be allowed
|
|
* to auto start? The default is to honour the spring configuration and
|
|
* allow them to, but they can be prevented if required.
|
|
*/
|
|
public static boolean isNoAutoStart()
|
|
{
|
|
return noAutoStart;
|
|
}
|
|
|
|
/**
|
|
* Is there currently a context loaded and cached?
|
|
*/
|
|
public static boolean isContextLoaded()
|
|
{
|
|
return (instance != null);
|
|
}
|
|
|
|
/**
|
|
* A wrapper around {@link ClassPathXmlApplicationContext} which allows us
|
|
* to enable lazy loading or prevent Subsystem autostart as requested.
|
|
*/
|
|
protected static class VariableFeatureClassPathXmlApplicationContext extends ClassPathXmlApplicationContext
|
|
{
|
|
protected VariableFeatureClassPathXmlApplicationContext(String[] configLocations) throws BeansException
|
|
{
|
|
super(configLocations);
|
|
}
|
|
|
|
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader)
|
|
{
|
|
super.initBeanDefinitionReader(reader);
|
|
|
|
if (useLazyLoading)
|
|
{
|
|
LazyClassPathXmlApplicationContext.postInitBeanDefinitionReader(reader);
|
|
}
|
|
if (noAutoStart)
|
|
{
|
|
NoAutoStartClassPathXmlApplicationContext.postInitBeanDefinitionReader(reader);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Can be used in Spring configuration to search for all resources matching an array of patterns.
|
|
*
|
|
* @author dward
|
|
*/
|
|
public static class ResourceFinder extends ServletContextResourcePatternResolver
|
|
{
|
|
public ResourceFinder()
|
|
{
|
|
super(new DefaultResourceLoader());
|
|
}
|
|
|
|
/**
|
|
* The Constructor.
|
|
*
|
|
* @param resourceLoader
|
|
* the resource loader
|
|
*/
|
|
public ResourceFinder(ResourceLoader resourceLoader)
|
|
{
|
|
super(resourceLoader);
|
|
}
|
|
|
|
/**
|
|
* Gets an array of resources matching the given location patterns.
|
|
*
|
|
* @param locationPatterns
|
|
* the location patterns
|
|
* @return the matching resources, ordered by locationPattern index and location in the classpath
|
|
* @throws IOException
|
|
* Signals that an I/O exception has occurred.
|
|
*/
|
|
public Resource[] getResources(String... locationPatterns) throws IOException
|
|
{
|
|
List<Resource> resources = new LinkedList<Resource>();
|
|
for (String locationPattern : locationPatterns)
|
|
{
|
|
resources.addAll(Arrays.asList(getResources(locationPattern)));
|
|
}
|
|
Resource[] resourceArray = new Resource[resources.size()];
|
|
resources.toArray(resourceArray);
|
|
return resourceArray;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* A utility class that will enumerate over an array of enumerations.
|
|
* was removed in version JDK 1.9
|
|
*/
|
|
final class CompoundEnumeration<E> implements Enumeration<E> {
|
|
private final Enumeration<E>[] enums;
|
|
private int index;
|
|
|
|
public CompoundEnumeration(Enumeration<E>[] enums) {
|
|
this.enums = enums;
|
|
}
|
|
|
|
private boolean next() {
|
|
while (index < enums.length) {
|
|
if (enums[index] != null && enums[index].hasMoreElements()) {
|
|
return true;
|
|
}
|
|
index++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean hasMoreElements() {
|
|
return next();
|
|
}
|
|
|
|
public E nextElement() {
|
|
if (!next()) {
|
|
throw new NoSuchElementException();
|
|
}
|
|
return enums[index].nextElement();
|
|
}
|
|
}
|