All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.camunda.bpm.engine.ProcessEngines Maven / Gradle / Ivy

There is a newer version: 7.23.0-alpha1
Show newest version
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; 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.camunda.bpm.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.camunda.bpm.engine.impl.ProcessEngineInfoImpl;
import org.camunda.bpm.engine.impl.ProcessEngineLogger;
import org.camunda.bpm.engine.impl.util.IoUtil;
import org.camunda.bpm.engine.impl.util.ReflectUtil;



/** Helper for initializing and closing process engines in server environments.
 * 
* All created {@link ProcessEngine}s will be registered with this class. *
* The activiti-webapp-init webapp will * call the {@link #init()} method when the webapp is deployed and it will call the * {@link #destroy()} method when the webapp is destroyed, using a context-listener * (org.camunda.bpm.engine.test.impl.servlet.listener.ProcessEnginesServletContextListener). That way, * all applications can just use the {@link #getProcessEngines()} to * obtain pre-initialized and cached process engines.
*
* Please note that there is no lazy initialization of process engines, so make sure the * context-listener is configured or {@link ProcessEngine}s are already created so they were registered * on this class.
*
* The {@link #init()} method will try to build one {@link ProcessEngine} for * each camunda.cfg.xml file found on the classpath. If you have more then one, * make sure you specify different process.engine.name values. * * @author Tom Baeyens * @author Joram Barrez */ public abstract class ProcessEngines { private final static ProcessEngineLogger LOG = ProcessEngineLogger.INSTANCE; public static final String NAME_DEFAULT = "default"; protected static boolean isInitialized = false; protected static Map processEngines = new HashMap(); protected static Map processEngineInfosByName = new HashMap(); protected static Map processEngineInfosByResourceUrl = new HashMap(); protected static List processEngineInfos = new ArrayList(); public synchronized static void init() { init(true); } /** Initializes all process engines that can be found on the classpath for * resources camunda.cfg.xml (plain Activiti style configuration) * and for resources activiti-context.xml (Spring style configuration). */ public synchronized static void init(boolean forceCreate) { if (!isInitialized) { if(processEngines == null) { // Create new map to store process-engines if current map is null processEngines = new HashMap(); } ClassLoader classLoader = ReflectUtil.getClassLoader(); Enumeration resources = null; try { resources = classLoader.getResources("camunda.cfg.xml"); } catch (IOException e) { try { resources = classLoader.getResources("activiti.cfg.xml"); } catch(IOException ex) { if(forceCreate) { throw new ProcessEngineException("problem retrieving camunda.cfg.xml and activiti.cfg.xml resources on the classpath: "+System.getProperty("java.class.path"), ex); } else { return; } } } // Remove duplicated configuration URL's using set. Some classloaders may return identical URL's twice, causing duplicate startups Set configUrls = new HashSet(); while (resources.hasMoreElements()) { configUrls.add( resources.nextElement() ); } for (Iterator iterator = configUrls.iterator(); iterator.hasNext();) { URL resource = iterator.next(); initProcessEngineFromResource(resource); } try { resources = classLoader.getResources("activiti-context.xml"); } catch (IOException e) { if(forceCreate) { throw new ProcessEngineException("problem retrieving activiti-context.xml resources on the classpath: "+System.getProperty("java.class.path"), e); } else { return; } } while (resources.hasMoreElements()) { URL resource = resources.nextElement(); initProcessEngineFromSpringResource(resource); } isInitialized = true; } else { LOG.processEngineAlreadyInitialized(); } } protected static void initProcessEngineFromSpringResource(URL resource) { try { Class< ? > springConfigurationHelperClass = ReflectUtil.loadClass("org.camunda.bpm.engine.spring.SpringConfigurationHelper"); Method method = springConfigurationHelperClass.getMethod("buildProcessEngine", new Class[]{URL.class}); ProcessEngine processEngine = (ProcessEngine) method.invoke(null, new Object[]{resource}); String processEngineName = processEngine.getName(); ProcessEngineInfo processEngineInfo = new ProcessEngineInfoImpl(processEngineName, resource.toString(), null); processEngineInfosByName.put(processEngineName, processEngineInfo); processEngineInfosByResourceUrl.put(resource.toString(), processEngineInfo); } catch (Exception e) { throw new ProcessEngineException("couldn't initialize process engine from spring configuration resource "+resource.toString()+": "+e.getMessage(), e); } } /** * Registers the given process engine. No {@link ProcessEngineInfo} will be * available for this process engine. An engine that is registered will be closed * when the {@link ProcessEngines#destroy()} is called. */ public static void registerProcessEngine(ProcessEngine processEngine) { processEngines.put(processEngine.getName(), processEngine); } /** * Unregisters the given process engine. */ public static void unregister(ProcessEngine processEngine) { processEngines.remove(processEngine.getName()); } private static ProcessEngineInfo initProcessEngineFromResource(URL resourceUrl) { ProcessEngineInfo processEngineInfo = processEngineInfosByResourceUrl.get(resourceUrl); // if there is an existing process engine info if (processEngineInfo!=null) { // remove that process engine from the member fields processEngineInfos.remove(processEngineInfo); if (processEngineInfo.getException()==null) { String processEngineName = processEngineInfo.getName(); processEngines.remove(processEngineName); processEngineInfosByName.remove(processEngineName); } processEngineInfosByResourceUrl.remove(processEngineInfo.getResourceUrl()); } String resourceUrlString = resourceUrl.toString(); try { LOG.initializingProcessEngineForResource(resourceUrl); ProcessEngine processEngine = buildProcessEngine(resourceUrl); String processEngineName = processEngine.getName(); LOG.initializingProcessEngine(processEngine.getName()); processEngineInfo = new ProcessEngineInfoImpl(processEngineName, resourceUrlString, null); processEngines.put(processEngineName, processEngine); processEngineInfosByName.put(processEngineName, processEngineInfo); } catch (Throwable e) { LOG.exceptionWhileInitializingProcessengine(e); processEngineInfo = new ProcessEngineInfoImpl(null, resourceUrlString, getExceptionString(e)); } processEngineInfosByResourceUrl.put(resourceUrlString, processEngineInfo); processEngineInfos.add(processEngineInfo); return processEngineInfo; } private static String getExceptionString(Throwable e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); return sw.toString(); } private static ProcessEngine buildProcessEngine(URL resource) { InputStream inputStream = null; try { inputStream = resource.openStream(); ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream); return processEngineConfiguration.buildProcessEngine(); } catch (IOException e) { throw new ProcessEngineException("couldn't open resource stream: "+e.getMessage(), e); } finally { IoUtil.closeSilently(inputStream); } } /** Get initialization results. */ public static List getProcessEngineInfos() { return processEngineInfos; } /** Get initialization results. Only info will we available for process engines * which were added in the {@link ProcessEngines#init()}. No {@link ProcessEngineInfo} * is available for engines which were registered programatically. */ public static ProcessEngineInfo getProcessEngineInfo(String processEngineName) { return processEngineInfosByName.get(processEngineName); } public static ProcessEngine getDefaultProcessEngine() { return getDefaultProcessEngine(true); } public static ProcessEngine getDefaultProcessEngine(boolean forceCreate) { return getProcessEngine(NAME_DEFAULT, forceCreate); } public static ProcessEngine getProcessEngine(String processEngineName) { return getProcessEngine(processEngineName, true); } /** obtain a process engine by name. * @param processEngineName is the name of the process engine or null for the default process engine. */ public static ProcessEngine getProcessEngine(String processEngineName, boolean forceCreate) { if (!isInitialized) { init(forceCreate); } return processEngines.get(processEngineName); } /** retries to initialize a process engine that previously failed. */ public static ProcessEngineInfo retry(String resourceUrl) { try { return initProcessEngineFromResource(new URL(resourceUrl)); } catch (MalformedURLException e) { throw new ProcessEngineException("invalid url: "+resourceUrl, e); } } /** provides access to process engine to application clients in a * managed server environment. */ public static Map getProcessEngines() { return processEngines; } /** closes all process engines. This method should be called when the server shuts down. */ public synchronized static void destroy() { if (isInitialized) { Map engines = new HashMap(processEngines); processEngines = new HashMap(); for (String processEngineName: engines.keySet()) { ProcessEngine processEngine = engines.get(processEngineName); try { processEngine.close(); } catch (Exception e) { LOG.exceptionWhileClosingProcessEngine(processEngineName==null ? "the default process engine" : "process engine "+processEngineName, e); } } processEngineInfosByName.clear(); processEngineInfosByResourceUrl.clear(); processEngineInfos.clear(); isInitialized = false; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy