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

org.microemu.microedition.ImplFactory Maven / Gradle / Ivy

The newest version!
/**
 *  MicroEmulator
 *  Copyright (C) 2006-2007 Bartek Teodorczyk 
 *  Copyright (C) 2006-2007 Vlad Skarzhevskyy
 *
 *  It is licensed under the following two licenses as alternatives:
 *    1. GNU Lesser General Public License (the "LGPL") version 2.1 or any newer version
 *    2. Apache License (the "AL") Version 2.0
 *
 *  You may not use this file except in compliance with at least one of
 *  the above two licenses.
 *
 *  You may obtain a copy of the LGPL at
 *      http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
 *
 *  You may obtain a copy of the AL 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 LGPL or the AL for the specific language governing permissions and
 *  limitations.
 *
 *  @version $Id: ImplFactory.java 1683 2008-04-09 20:59:35Z vlads $
 */
package org.microemu.microedition;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Map;

import org.microemu.microedition.io.ConnectorDelegate;

/**
 * This class allows to unbind implemenation with CLDC or MIDP declarations.
 * 
 * @author vlads
 * 
 */
public class ImplFactory {

	public static final String DEFAULT = "org.microemu.default";

	private static final String INTERFACE_NAME_SUFIX = "Delegate";

	private static final String IMPLEMENTATION_NAME_SUFIX = "Impl";

	private Map implementations = new HashMap();

	private Map implementationsGCF = new HashMap();

	/* The context to be used when loading classes and resources */
	private AccessControlContext acc;

	/**
	 * Allow default initialization. In Secure environment instance() should be
	 * called initialy from secure contex.
	 */
	private static class SingletonHolder {
		private static ImplFactory instance = new ImplFactory();
	}

	private ImplFactory() {
		acc = AccessController.getContext();
	}

	public static ImplFactory instance() {
		return SingletonHolder.instance;
	}

	public static void register(Class delegate, Class implementationClass) {
		instance().implementations.put(delegate, implementationClass);
	}

	public static void register(Class delegate, Object implementationInstance) {
		instance().implementations.put(delegate, implementationInstance);
	}

	public static void unregister(Class delegate, Class implementation) {
		// TODO implement
	}

	/**
	 * 
	 * Register Generic Connection Framework scheme implementation.
	 * 
	 * @param implementation
	 *            instance of ConnectorDelegate
	 * @param scheme
	 */
	public static void registerGCF(String scheme, Object implementation) {
		if (!ConnectorDelegate.class.isAssignableFrom(implementation.getClass())) {
			throw new IllegalArgumentException();
		}
		if (scheme == null) {
			scheme = DEFAULT;
		}
		Object impl = instance().implementationsGCF.get(scheme);
		if (impl instanceof ImplementationUnloadable) {
			((ImplementationUnloadable) impl).unregisterImplementation();
		}
		instance().implementationsGCF.put(scheme, implementation);
	}

	public static void unregistedGCF(String scheme, Object implementation) {
		if (!ConnectorDelegate.class.isAssignableFrom(implementation.getClass())) {
			throw new IllegalArgumentException();
		}
		if (scheme == null) {
			scheme = DEFAULT;
		}
		Object impl = instance().implementationsGCF.get(scheme);
		if (impl == implementation) {
			instance().implementationsGCF.remove(scheme);
		}
	}

	private Object getDefaultImplementation(Class delegateInterface) {
		try {
			String name = delegateInterface.getName();
			if (name.endsWith(INTERFACE_NAME_SUFIX)) {
				name = name.substring(0, name.length() - INTERFACE_NAME_SUFIX.length());
			}
			final String implClassName = name + IMPLEMENTATION_NAME_SUFIX;
			return AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Object run() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
					Class implClass = ImplFactory.class.getClassLoader().loadClass(implClassName);
					try {
						implClass.getConstructor(null);
					} catch (NoSuchMethodException e) {
						throw new InstantiationException("No default constructor in class " + implClassName);
					}
					return implClass.newInstance();
				}
			}, acc);
		} catch (Throwable e) {
			throw new RuntimeException("Unable create " + delegateInterface.getName() + " implementation", e);
		}
	}

	private Object implementationNewInstance(final Class implClass) {
		try {
			return AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Object run() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
					return implClass.newInstance();
				}
			}, acc);
		} catch (Throwable e) {
			throw new RuntimeException("Unable create " + implClass.getName() + " implementation", e);
		}
	}

	/**
	 * 
	 * @param name
	 *            The URL for the connection.
	 * @return UTL scheme
	 */
	public static String getCGFScheme(String name) {
		return name.substring(0, name.indexOf(':'));
	}

	/**
	 * 
	 * @param name
	 *            The URL for the connection.
	 * @return
	 */
	public static ConnectorDelegate getCGFImplementation(String name) {
		String scheme = getCGFScheme(name);
		ConnectorDelegate impl = (ConnectorDelegate) instance().implementationsGCF.get(scheme);
		if (impl != null) {
			return impl;
		}
		impl = (ConnectorDelegate) instance().implementationsGCF.get(DEFAULT);
		if (impl != null) {
			return impl;
		}
		return (ConnectorDelegate) instance().getDefaultImplementation(ConnectorDelegate.class);
	}

	// public static Implementation getImplementation(Class origClass, Object[]
	// constructorArgs) {
	// //TO-DO constructorArgs
	// return getImplementation(origClass);
	// }

	public static Implementation getImplementation(Class origClass, Class delegateInterface) {
		// if called from implementation constructor return null to avoid
		// recurive calls!
		// TODO can be done using thread stack analyse or ThreadLocal
		Object impl = instance().implementations.get(delegateInterface);
		// debugClassLoader(Implementation.class);
		// debugClassLoader(origClass);
		// debugClassLoader(delegateInterface);
		// debugClassLoader(o);

		if (impl != null) {
			if (impl instanceof Class) {
				return (Implementation) instance().implementationNewInstance((Class) impl);
			} else {
				return (Implementation) impl;
			}
		}
		return (Implementation) instance().getDefaultImplementation(delegateInterface);
	}

	// private static void debugClassLoader(Object obj) {
	// if (obj == null) {
	// System.out.print("no class");
	// return;
	// }
	// Class klass;
	// if (obj instanceof Class) {
	// klass = (Class)obj;
	// System.out.print("class ");
	// } else {
	// klass = obj.getClass();
	// System.out.print("instance ");
	// }
	// System.out.print(klass.getName() + " loaded by ");
	// if (klass.getClassLoader() != null) {
	// System.out.print(klass.getClassLoader().hashCode());
	// } else {
	// System.out.print("system");
	// }
	// System.out.println();
	// }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy