/*
* Atricore IDBus
*
* Copyright (c) 2009, Atricore Inc.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.atricore.idbus.kernel.planning.jbpm;
import org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xbean.spring.context.ClassPathXmlApplicationContext;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.util.logging.Level;
/**
*
* @author <a href="mailto:gbrigandi@atricore.org">Gianluca Brigandi</a>
* @version $Rev: 252 $ $Date: 2008-12-22 18:24:21 -0200 (Mon, 22 Dec 2008) $
*/
public class ProcessFragmentRegistryApplicationContext extends ClassPathXmlApplicationContext {
private static final String DEFAULT_PROCESS_DESCRIPTOR_FILE = "jpdl-process-descriptor.xml";
private static final String DEFAULT_JBPM_FRAGMENT_CFG_FILE = "META-INF/jbpm/jbpm-process-fragment-default.xml";
private static final String DEFAULT_JBPM_EXT_FRAGMENT_CFG_FILE = "classpath*:META-INF/jbpm/jbpm.fragment";
protected final transient Log logger = LogFactory.getLog(getClass());
private DefaultNamespaceHandlerResolver nsHandlerResolver;
private boolean includeDefaults;
private String[] cfgFiles;
private URL[] cfgFileURLs;
public ProcessFragmentRegistryApplicationContext(String cf, boolean include) {
this(cf, include, null);
}
public ProcessFragmentRegistryApplicationContext(String[] cfs, boolean include) {
this(cfs, include, null);
}
public ProcessFragmentRegistryApplicationContext(URL url, boolean include) {
this(url, include, null);
}
public ProcessFragmentRegistryApplicationContext(URL[] urls, boolean include) {
this(urls, include, null);
}
public ProcessFragmentRegistryApplicationContext(String cf, boolean include, ApplicationContext parent) {
this(new String[] {cf}, include, parent);
}
public ProcessFragmentRegistryApplicationContext(URL url, boolean include, ApplicationContext parent) {
this(new URL[] {url}, include, parent);
}
public ProcessFragmentRegistryApplicationContext(String[] cf, boolean include, ApplicationContext parent) {
super(new String[0], false, parent);
cfgFiles = cf;
includeDefaults = include;
refresh();
}
public ProcessFragmentRegistryApplicationContext(URL[] url, boolean include, ApplicationContext parent) {
super(new String[0], false, parent);
cfgFileURLs = url;
includeDefaults = include;
refresh();
}
@Override
protected Resource[] getConfigResources() {
List<Resource> resources = new ArrayList<Resource>();
try {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(Thread
.currentThread().getContextClassLoader());
Collections.addAll(resources, resolver.getResources(DEFAULT_JBPM_FRAGMENT_CFG_FILE));
Resource[] exts = resolver.getResources(DEFAULT_JBPM_EXT_FRAGMENT_CFG_FILE);
for (Resource r : exts) {
InputStream is = r.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String line = rd.readLine();
while (line != null) {
if (!"".equals(line)) {
resources.add(resolver.getResource(line));
}
line = rd.readLine();
}
is.close();
}
} catch (IOException ex) {
// ignore
}
if (null == cfgFiles) {
cfgFiles = new String[] {DEFAULT_PROCESS_DESCRIPTOR_FILE};
}
for (String cfgFile : cfgFiles) {
boolean found = false;
Resource cpr = new ClassPathResource(cfgFile);
if (!cpr.exists()) {
try {
//see if it's a URL
URL url = new URL(cfgFile);
cpr = new UrlResource(url);
if (cpr.exists()) {
resources.add(cpr);
found = true;
}
} catch (MalformedURLException e) {
//ignore
}
if (!found) {
//try loading it our way
URL url = getResource(cfgFile, this.getClass());
if (url != null) {
cpr = new UrlResource(url);
if (cpr.exists()) {
resources.add(cpr);
found = true;
}
}
}
} else {
resources.add(cpr);
found = true;
}
if (!found) {
logger.warn("No Process Descriptor found: " + cfgFile);
}
}
if (null != cfgFileURLs) {
for (URL cfgFileURL : cfgFileURLs) {
UrlResource ur = new UrlResource(cfgFileURL);
if (ur.exists()) {
resources.add(ur);
} else {
logger.warn("No Process Descriptor found: " + cfgFileURL);
}
}
}
logger.info("Creating application context with resources: " + resources);
if (0 == resources.size()) {
return null;
}
Resource[] res = new Resource[resources.size()];
res = resources.toArray(res);
return res;
}
/**
* Load a given resource. <p/> This method will try to load the resource
* using the following methods (in order):
* <ul>
* <li>From Thread.currentThread().getContextClassLoader()
* <li>From ClassLoaderUtil.class.getClassLoader()
* <li>callingClass.getClassLoader()
* </ul>
*
* @param resourceName The name of the resource to load
* @param callingClass The Class object of the calling object
*/
private URL getResource(String resourceName, Class callingClass) {
URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
if (url == null && resourceName.startsWith("/")) {
//certain classloaders need it without the leading /
url = Thread.currentThread().getContextClassLoader()
.getResource(resourceName.substring(1));
}
if (url == null) {
ClassLoader cl = callingClass.getClassLoader();
if (cl != null) {
url = cl.getResource(resourceName);
}
}
if (url == null) {
url = callingClass.getResource(resourceName);
}
if ((url == null) && (resourceName != null) && (resourceName.charAt(0) != '/')) {
return getResource('/' + resourceName, callingClass);
}
return url;
}
}