Java tutorial
/* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.activiti.dmn.engine; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.activiti.dmn.engine.impl.util.ReflectUtil; import org.activiti.engine.ActivitiException; import org.activiti.engine.EngineInfo; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class DmnEngines { private static Logger log = LoggerFactory.getLogger(DmnEngines.class); public static final String NAME_DEFAULT = "default"; protected static boolean isInitialized; protected static Map<String, DmnEngine> dmnEngines = new HashMap<String, DmnEngine>(); protected static Map<String, EngineInfo> dmnEngineInfosByName = new HashMap<String, EngineInfo>(); protected static Map<String, EngineInfo> dmnEngineInfosByResourceUrl = new HashMap<String, EngineInfo>(); protected static List<EngineInfo> dmnEngineInfos = new ArrayList<EngineInfo>(); /** * Initializes all dmn engines that can be found on the classpath for * resources <code>activiti.dmn.cfg.xml</code> and for resources * <code>activiti-dmn-context.xml</code> (Spring style configuration). */ public synchronized static void init() { if (!isInitialized()) { if (dmnEngines == null) { // Create new map to store dmn engines if current map is null dmnEngines = new HashMap<String, DmnEngine>(); } ClassLoader classLoader = DmnEngines.class.getClassLoader(); Enumeration<URL> resources = null; try { resources = classLoader.getResources("activiti.dmn.cfg.xml"); } catch (IOException e) { throw new ActivitiException("problem retrieving activiti.dmn.cfg.xml resources on the classpath: " + System.getProperty("java.class.path"), e); } // Remove duplicated configuration URL's using set. Some // classloaders may return identical URL's twice, causing duplicate startups Set<URL> configUrls = new HashSet<URL>(); while (resources.hasMoreElements()) { configUrls.add(resources.nextElement()); } for (Iterator<URL> iterator = configUrls.iterator(); iterator.hasNext();) { URL resource = iterator.next(); log.info("Initializing dmn engine using configuration '{}'", resource.toString()); initDmnEngineFromResource(resource); } try { resources = classLoader.getResources("activiti-dmn-context.xml"); } catch (IOException e) { throw new ActivitiException( "problem retrieving activiti-dmn-context.xml resources on the classpath: " + System.getProperty("java.class.path"), e); } while (resources.hasMoreElements()) { URL resource = resources.nextElement(); log.info("Initializing dmn engine using Spring configuration '{}'", resource.toString()); initDmnEngineFromSpringResource(resource); } setInitialized(true); } else { log.info("DMN engines already initialized"); } } protected static void initDmnEngineFromSpringResource(URL resource) { try { Class<?> springConfigurationHelperClass = ReflectUtil .loadClass("org.activiti.dmn.spring.SpringDmnConfigurationHelper"); Method method = springConfigurationHelperClass.getDeclaredMethod("buildDmnEngine", new Class<?>[] { URL.class }); DmnEngine dmnEngine = (DmnEngine) method.invoke(null, new Object[] { resource }); String dmnEngineName = dmnEngine.getName(); EngineInfo dmnEngineInfo = new EngineInfo(dmnEngineName, resource.toString(), null); dmnEngineInfosByName.put(dmnEngineName, dmnEngineInfo); dmnEngineInfosByResourceUrl.put(resource.toString(), dmnEngineInfo); } catch (Exception e) { throw new ActivitiException("couldn't initialize dmn engine from spring configuration resource " + resource.toString() + ": " + e.getMessage(), e); } } /** * Registers the given dmn engine. No {@link DmnEngineInfo} will be available * for this dmn engine. An engine that is registered will be closed when the * {@link DmnEngines#destroy()} is called. */ public static void registerDmnEngine(DmnEngine dmnEngine) { dmnEngines.put(dmnEngine.getName(), dmnEngine); } /** * Unregisters the given dmn engine. */ public static void unregister(DmnEngine dmnEngine) { dmnEngines.remove(dmnEngine.getName()); } private static EngineInfo initDmnEngineFromResource(URL resourceUrl) { EngineInfo dmnEngineInfo = dmnEngineInfosByResourceUrl.get(resourceUrl.toString()); // if there is an existing dmn engine info if (dmnEngineInfo != null) { // remove that dmn engine from the member fields dmnEngineInfos.remove(dmnEngineInfo); if (dmnEngineInfo.getException() == null) { String dmnEngineName = dmnEngineInfo.getName(); dmnEngines.remove(dmnEngineName); dmnEngineInfosByName.remove(dmnEngineName); } dmnEngineInfosByResourceUrl.remove(dmnEngineInfo.getResourceUrl()); } String resourceUrlString = resourceUrl.toString(); try { log.info("initializing dmn engine for resource {}", resourceUrl); DmnEngine dmnEngine = buildDmnEngine(resourceUrl); String dmnEngineName = dmnEngine.getName(); log.info("initialised dmn engine {}", dmnEngineName); dmnEngineInfo = new EngineInfo(dmnEngineName, resourceUrlString, null); dmnEngines.put(dmnEngineName, dmnEngine); dmnEngineInfosByName.put(dmnEngineName, dmnEngineInfo); } catch (Throwable e) { log.error("Exception while initializing dmn engine: {}", e.getMessage(), e); dmnEngineInfo = new EngineInfo(null, resourceUrlString, getExceptionString(e)); } dmnEngineInfosByResourceUrl.put(resourceUrlString, dmnEngineInfo); dmnEngineInfos.add(dmnEngineInfo); return dmnEngineInfo; } private static String getExceptionString(Throwable e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); return sw.toString(); } protected static DmnEngine buildDmnEngine(URL resource) { InputStream inputStream = null; try { inputStream = resource.openStream(); DmnEngineConfiguration dmnEngineConfiguration = DmnEngineConfiguration .createDmnEngineConfigurationFromInputStream(inputStream); return dmnEngineConfiguration.buildDmnEngine(); } catch (IOException e) { throw new ActivitiException("couldn't open resource stream: " + e.getMessage(), e); } finally { IOUtils.closeQuietly(inputStream); } } /** Get initialization results. */ public static List<EngineInfo> getDmnEngineInfos() { return dmnEngineInfos; } /** * Get initialization results. Only info will we available for dmn engines * which were added in the {@link DmnEngines#init()}. No {@link DmnEngineInfo} * is available for engines which were registered programmatically. */ public static EngineInfo getDmnEngineInfo(String dmnEngineName) { return dmnEngineInfosByName.get(dmnEngineName); } public static DmnEngine getDefaultDmnEngine() { return getDmnEngine(NAME_DEFAULT); } /** * obtain a dmn engine by name. * * @param dmnEngineName * is the name of the dmn engine or null for the default dmn engine. */ public static DmnEngine getDmnEngine(String dmnEngineName) { if (!isInitialized()) { init(); } return dmnEngines.get(dmnEngineName); } /** * retries to initialize a dmn engine that previously failed. */ public static EngineInfo retry(String resourceUrl) { log.debug("retying initializing of resource {}", resourceUrl); try { return initDmnEngineFromResource(new URL(resourceUrl)); } catch (MalformedURLException e) { throw new ActivitiException("invalid url: " + resourceUrl, e); } } /** * provides access to dmn engine to application clients in a managed server * environment. */ public static Map<String, DmnEngine> getDmnEngines() { return dmnEngines; } /** * closes all dmn engines. This method should be called when the server shuts * down. */ public synchronized static void destroy() { if (isInitialized()) { Map<String, DmnEngine> engines = new HashMap<String, DmnEngine>(dmnEngines); dmnEngines = new HashMap<String, DmnEngine>(); for (String dmnEngineName : engines.keySet()) { DmnEngine dmnEngine = engines.get(dmnEngineName); try { dmnEngine.close(); } catch (Exception e) { log.error("exception while closing {}", (dmnEngineName == null ? "the default dmn engine" : "dmn engine " + dmnEngineName), e); } } dmnEngineInfosByName.clear(); dmnEngineInfosByResourceUrl.clear(); dmnEngineInfos.clear(); setInitialized(false); } } public static boolean isInitialized() { return isInitialized; } public static void setInitialized(boolean isInitialized) { DmnEngines.isInitialized = isInitialized; } }