blob: 2375eab3f67c52c72edf508e13fbcf8c04254030 [file] [log] [blame]
/*
* 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.bsf.util.event;
import java.util.Hashtable;
import org.apache.bsf.util.event.generator.EventAdapterGenerator;
import org.apache.bsf.BSFManager;
/**
* The <em>EventAdapterRegistry</em> is the registry of event adapters. If a desired adapter is not found, the adapter will be dynamically generated when lookup
* is attempted. Set the <code>dynamic</code> property to <code>false</code> to disable this feature.
* <p>
* This implementation first looks for an adapter in its lookup table and if it doesn't find one looks for a standard implementation of that adapter in the
* org.apache.bsf.util.event.adapters package with a standard naming convention. The naming convention it assumes is the following: for event listener type
* {@code a.b.c.FooListener}, it loads an adapter of type {@code org.apache.bsf.util.event.adapters.a_b_c_FooAdapter}. If both the loading and the dynamic
* generation fail, then a <code>null</code> is returned.
* <p>
*
* @see EventAdapter
*/
/*
* changed: 2012-01-29: Rony G. Flatscher, cf. [https://issues.apache.org/jira/browse/BSF-21]: - take into account that a context class loader may not be set
*
* - new class loading sequence: - Thread's context class loader - settable class loader stored with EventAdapterRegistry - BSFManager's defining class loader
*/
public class EventAdapterRegistry {
private static final Hashtable reg = new Hashtable();
private static ClassLoader cl;
private static final String adapterPackage = "org.apache.bsf.util.event.adapters";
private static final String adapterSuffix = "Adapter";
private static boolean dynamic = true;
public static Class lookup(final Class listenerType) {
final String key = listenerType.getName().replace('.', '_');
Class adapterClass = (Class) reg.get(key);
if (adapterClass == null) {
final String en = key.substring(0, key.lastIndexOf("Listener"));
final String cn = adapterPackage + "." + en + adapterSuffix;
if (adapterClass == null) { // get Thread's context class loader
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
if (tccl != null) {
try { // try supplied class loader
adapterClass = Thread.currentThread().getContextClassLoader().loadClass(cn);
} catch (final ClassNotFoundException e02) {
}
}
}
try { // try ClassLoader set in this object (cf. this.setClassLoader())
if (cl != null) {
adapterClass = cl.loadClass(cn);
}
} catch (final ClassNotFoundException e01) {
}
if (adapterClass == null) { // Defined CL
try { // try supplied class loader
final ClassLoader defCL = BSFManager.getDefinedClassLoader();
if (cl != defCL) {
adapterClass = defCL.loadClass(cn);
}
} catch (final ClassNotFoundException e03) {
}
}
if (adapterClass == null && dynamic) {
// Unable to resolve one, try to generate one.
adapterClass = // if second argument is set to 'true', then the class file will be stored in the filesystem:
EventAdapterGenerator.makeEventAdapterClass(listenerType, false);
}
if (adapterClass != null) {
reg.put(key, adapterClass);
}
}
return adapterClass;
}
public static void register(final Class listenerType, final Class eventAdapterClass) {
final String key = listenerType.getName().replace('.', '_');
reg.put(key, eventAdapterClass);
}
/**
* Class loader to use to load event adapter classes.
*/
public static void setClassLoader(final ClassLoader cloader) {
cl = cloader;
}
/**
* Indicates whether or not to dynamically generate adapters; default is <code>true</code>.
* <p>
* If the <code>dynamic</code> property is set to true, and the <code>ClassLoader</code> is unable to resolve an adapter, one will be dynamically generated.
*
* @param dynamic whether or not to dynamically generate adapters.
*/
public static void setDynamic(final boolean dynamic) {
EventAdapterRegistry.dynamic = dynamic;
}
}