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

org.apache.cxf.BusFactory Maven / Gradle / Ivy

There is a newer version: 0.10.0
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.apache.cxf;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.cxf.common.classloader.ClassLoaderUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.SystemPropertyAction;

/**
 * Factory to create CXF Bus objects.
 * 

CXF includes a large number of components that provide services, such * as WSDL parsing, and message processing. To avoid creating these objects over and over, and to * allow them to be shared easily, they are associated with a data structure called a bus. *

*

* You don't ever have to explicitly create or manipulate bus objects. If you simply use the CXF * or JAX-WS APIs to create clients or servers, CXF will create a default bus for you. You can create a bus * explicitly if you need to customize components on the bus or maintain several independent buses * with independent configurations. *

*

* This class maintains the default bus for the entire process and a set of thread-default buses. All CXF * components that reference the bus, which is to say all CXF components, will obtain a default bus from this * class if you do not set a specific bus. *

*

* If you create a bus when there is no default bus in effect, that bus will become the default bus. *

*

* This class holds a reference to the global default bus and a reference to each thread default * bus. The thread references are weak with respect to the threads, but otherwise ordinary. * Thus, so long as the thread remains alive * there will be a strong reference to the bus, and it will not get garbage-collected. * If you want to recover memory used CXF, you can set * the default and per-thread default bus to null, explicitly. *

*/ public abstract class BusFactory { public static final String BUS_FACTORY_PROPERTY_NAME = "org.apache.cxf.bus.factory"; public static final String DEFAULT_BUS_FACTORY = "org.apache.cxf.bus.CXFBusFactory"; protected static Bus defaultBus; static class BusHolder { Bus bus; volatile boolean stale; } protected static final Map THREAD_BUSSES = new WeakHashMap(); protected static final ThreadLocal THREAD_BUS = new ThreadLocal(); private static final Logger LOG = LogUtils.getL7dLogger(BusFactory.class); /** * Creates a new bus. While concrete BusFactory may offer differently parameterized methods * for creating a bus, all factories support this no-arg factory method. * * @return the newly created bus. */ public abstract Bus createBus(); /** * Returns the default bus, creating it if necessary. * * @return the default bus. */ public static synchronized Bus getDefaultBus() { return getDefaultBus(true); } /** * Returns the default bus * * @param createIfNeeded Set to true to create a default bus if one doesn't exist * @return the default bus. */ public static synchronized Bus getDefaultBus(boolean createIfNeeded) { if (defaultBus == null && createIfNeeded) { defaultBus = newInstance().createBus(); } if (defaultBus == null) { // never set up. return null; } else { return defaultBus; } } private static BusHolder getThreadBusHolder(boolean set) { BusHolder h = THREAD_BUS.get(); if (h == null || h.stale) { Thread cur = Thread.currentThread(); synchronized (THREAD_BUSSES) { h = THREAD_BUSSES.get(cur); } if (h == null || h.stale) { h = new BusHolder(); synchronized (THREAD_BUSSES) { THREAD_BUSSES.put(cur, h); } } if (set) { THREAD_BUS.set(h); } } return h; } /** * Sets the default bus. * * @param bus the default bus. */ public static synchronized void setDefaultBus(Bus bus) { defaultBus = bus; BusHolder b = getThreadBusHolder(false); b.bus = bus; if (bus == null) { b.stale = true; THREAD_BUS.remove(); } } /** * Sets the default bus for the thread. * * @param bus the default bus. */ public static void setThreadDefaultBus(Bus bus) { if (bus == null) { BusHolder h = THREAD_BUS.get(); if (h == null) { Thread cur = Thread.currentThread(); synchronized (THREAD_BUSSES) { h = THREAD_BUSSES.get(cur); } } if (h != null) { h.bus = null; h.stale = true; THREAD_BUS.remove(); } } else { BusHolder b = getThreadBusHolder(true); b.bus = bus; } } /** * Sets the default bus for the thread. * * @param bus the new thread default bus. * @return the old thread default bus or null */ public static Bus getAndSetThreadDefaultBus(Bus bus) { if (bus == null) { BusHolder b = THREAD_BUS.get(); if (b == null) { Thread cur = Thread.currentThread(); synchronized (THREAD_BUSSES) { b = THREAD_BUSSES.get(cur); } } if (b != null) { Bus orig = b.bus; b.bus = null; b.stale = true; THREAD_BUS.remove(); return orig; } return null; } BusHolder b = getThreadBusHolder(true); Bus old = b.bus; b.bus = bus; return old; } /** * Gets the default bus for the thread. * * @return the default bus. */ public static Bus getThreadDefaultBus() { return getThreadDefaultBus(true); } /** * Gets the default bus for the thread, creating if needed * * @param createIfNeeded Set to true to create a default bus if one doesn't exist * @return the default bus. */ public static Bus getThreadDefaultBus(boolean createIfNeeded) { if (createIfNeeded) { BusHolder b = getThreadBusHolder(false); if (b.bus == null) { b.bus = createThreadBus(); } return b.bus; } BusHolder h = THREAD_BUS.get(); if (h == null || h.stale) { Thread cur = Thread.currentThread(); synchronized (THREAD_BUSSES) { h = THREAD_BUSSES.get(cur); } } return h == null || h.stale ? null : h.bus; } private static synchronized Bus createThreadBus() { BusHolder b = getThreadBusHolder(false); if (b.bus == null) { b.bus = getDefaultBus(true); } return b.bus; } /** * Removes a bus from being a thread default bus for any thread. *

* This is typically done when a bus has ended its lifecycle (i.e.: a call to * {@link Bus#shutdown(boolean)} was invoked) and it wants to remove any reference to itself for any * thread. * * @param bus the bus to remove */ public static void clearDefaultBusForAnyThread(final Bus bus) { synchronized (THREAD_BUSSES) { for (final Iterator iterator = THREAD_BUSSES.values().iterator(); iterator.hasNext();) { BusHolder itBus = iterator.next(); if (bus == null || itBus == null || itBus.bus == null || itBus.stale || bus.equals(itBus.bus)) { if (itBus != null) { itBus.bus = null; //mark as stale so if a thread asks again, it will create a new one itBus.stale = true; } //This will remove the BusHolder from the only place that should //strongly reference it iterator.remove(); } } } } /** * Sets the default bus if a default bus is not already set. * * @param bus the default bus. * @return true if the bus was not set and is now set */ public static synchronized boolean possiblySetDefaultBus(Bus bus) { BusHolder b = getThreadBusHolder(false); if (b.bus == null) { b.bus = bus; } if (defaultBus == null) { defaultBus = bus; return true; } return false; } /** * Create a new BusFactory The class of the BusFactory is determined by looking for the system propery: * org.apache.cxf.bus.factory or by searching the classpath for: * META-INF/services/org.apache.cxf.bus.factory * * @return a new BusFactory to be used to create Bus objects */ public static BusFactory newInstance() { return newInstance(null); } /** * Create a new BusFactory * * @param className The class of the BusFactory to create. If null, uses the default search algorithm. * @return a new BusFactory to be used to create Bus objects */ public static BusFactory newInstance(String className) { BusFactory instance = null; if (className == null) { ClassLoader loader = Thread.currentThread().getContextClassLoader(); className = getBusFactoryClass(loader); if (className == null && loader != BusFactory.class.getClassLoader()) { className = getBusFactoryClass(BusFactory.class.getClassLoader()); } } if (className == null) { className = BusFactory.DEFAULT_BUS_FACTORY; } Class busFactoryClass; try { busFactoryClass = ClassLoaderUtils.loadClass(className, BusFactory.class) .asSubclass(BusFactory.class); instance = busFactoryClass.newInstance(); } catch (Exception ex) { LogUtils.log(LOG, Level.SEVERE, "BUS_FACTORY_INSTANTIATION_EXC", ex); throw new RuntimeException(ex); } return instance; } protected void initializeBus(Bus bus) { } private static String getBusFactoryClass(ClassLoader classLoader) { String busFactoryClass = null; String busFactoryCondition = null; // next check system properties busFactoryClass = SystemPropertyAction.getPropertyOrNull(BusFactory.BUS_FACTORY_PROPERTY_NAME); if (isValidBusFactoryClass(busFactoryClass)) { return busFactoryClass; } try { // next, check for the services stuff in the jar file String serviceId = "META-INF/services/" + BusFactory.BUS_FACTORY_PROPERTY_NAME; InputStream is = null; if (classLoader == null) { classLoader = Thread.currentThread().getContextClassLoader(); } if (classLoader == null) { is = ClassLoader.getSystemResourceAsStream(serviceId); } else { is = classLoader.getResourceAsStream(serviceId); } if (is == null) { serviceId = "META-INF/cxf/" + BusFactory.BUS_FACTORY_PROPERTY_NAME; if (classLoader == null) { classLoader = Thread.currentThread().getContextClassLoader(); } if (classLoader == null) { is = ClassLoader.getSystemResourceAsStream(serviceId); } else { is = classLoader.getResourceAsStream(serviceId); } } if (is != null) { BufferedReader rd = null; try { rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); busFactoryClass = rd.readLine(); busFactoryCondition = rd.readLine(); } finally { if (rd != null) { rd.close(); } } } if (isValidBusFactoryClass(busFactoryClass) && busFactoryCondition != null) { try { Class cls = ClassLoaderUtils.loadClass(busFactoryClass, BusFactory.class) .asSubclass(BusFactory.class); if (busFactoryCondition.startsWith("#")) { busFactoryCondition = busFactoryCondition.substring(1); } int idx = busFactoryCondition.indexOf(','); while (idx != -1) { cls.getClassLoader().loadClass(busFactoryCondition.substring(0, idx)); busFactoryCondition = busFactoryCondition.substring(idx + 1); idx = busFactoryCondition.indexOf(','); } cls.getClassLoader().loadClass(busFactoryCondition); } catch (ClassNotFoundException e) { busFactoryClass = DEFAULT_BUS_FACTORY; } catch (NoClassDefFoundError e) { busFactoryClass = DEFAULT_BUS_FACTORY; } } return busFactoryClass; } catch (Exception ex) { LogUtils.log(LOG, Level.SEVERE, "FAILED_TO_DETERMINE_BUS_FACTORY_EXC", ex); } return busFactoryClass; } private static boolean isValidBusFactoryClass(String busFactoryClassName) { return busFactoryClassName != null && !"".equals(busFactoryClassName); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy