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

org.microemu.microedition.io.ConnectorImpl 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: ConnectorImpl.java 1605 2008-02-25 21:07:14Z barteo $
 */
package org.microemu.microedition.io;

import java.io.IOException;
import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Vector;

import javax.microedition.io.Connection;
import javax.microedition.io.ConnectionNotFoundException;

import org.microemu.cldc.ClosedConnection;
import org.microemu.log.Logger;

import com.sun.cdc.io.ConnectionBaseInterface;

/**
 * @author vlads Original MicroEmulator implementation of
 *         javax.microedition.Connector
 * 
 * TODO integrate with ImplementationInitialization
 */
public class ConnectorImpl extends ConnectorAdapter {

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

	// TODO make this configurable
	public static boolean debugConnectionInvocations = false;

	private final boolean needPrivilegedCalls = isWebstart();

	public ConnectorImpl() {
		acc = AccessController.getContext();
	}

	private static boolean isWebstart() {
		try {
			return (System.getProperty("javawebstart.version") != null);
		} catch (SecurityException e) {
			// This is the case for Applet.
			return false;
		}
	}

	public Connection open(final String name, final int mode, final boolean timeouts) throws IOException {
		try {
			return (Connection) AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Object run() throws IOException {
					if (debugConnectionInvocations || needPrivilegedCalls) {
						return openSecureProxy(name, mode, timeouts, needPrivilegedCalls);
					} else {
						return openSecure(name, mode, timeouts);
					}
				}
			}, acc);
		} catch (PrivilegedActionException e) {
			if (e.getCause() instanceof IOException) {
				throw (IOException) e.getCause();
			}
			throw new IOException(e.toString());
		}
	}

	private static Class[] getAllInterfaces(Class klass) {
		Vector allInterfaces = new Vector();
		Class parent = klass;
		while (parent != null) {
			Class[] interfaces = parent.getInterfaces();
			for (int i = 0; i < interfaces.length; i++) {
				allInterfaces.add(interfaces[i]);
			}
			parent = parent.getSuperclass();
		}

		return (Class[]) allInterfaces.toArray(new Class[allInterfaces.size()]);
	}

	private Connection openSecureProxy(String name, int mode, boolean timeouts, boolean needPrivilegedCalls)
			throws IOException {
		Connection origConnection = openSecure(name, mode, timeouts);
		Class connectionClass = null;
		Class[] interfaces = getAllInterfaces(origConnection.getClass());
		for (int i = 0; i < interfaces.length; i++) {
			if (Connection.class.isAssignableFrom(interfaces[i])) {
				connectionClass = interfaces[i];
				break;
			} else if (interfaces[i].getClass().getName().equals(Connection.class.getName())) {
				Logger.debugClassLoader("ME2 Connection.class", Connection.class);
				Logger.debugClassLoader(name + " Connection.class", interfaces[i]);
				Logger.error("Connection interface loaded by different ClassLoader");
			}
		}
		if (connectionClass == null) {
			throw new ClassCastException(origConnection.getClass().getName() + " Connection expected");
		}
		return (Connection) Proxy.newProxyInstance(ConnectorImpl.class.getClassLoader(), interfaces,
				new ConnectionInvocationHandler(origConnection, needPrivilegedCalls));
	}

	private Connection openSecure(String name, int mode, boolean timeouts) throws IOException {
		String className = null;
		String protocol = null;
		try {
			try {
				protocol = name.substring(0, name.indexOf(':'));
				className = "org.microemu.cldc." + protocol + ".Connection";
				Class cl = Class.forName(className);
				Object inst = cl.newInstance();
				if (inst instanceof ConnectionImplementation) {
					return ((ConnectionImplementation) inst).openConnection(name, mode, timeouts);
				} else {
					return ((ClosedConnection) inst).open(name);
				}
			} catch (ClassNotFoundException e) {
				try {
					className = "com.sun.cdc.io.j2me." + protocol + ".Protocol";
					Class cl = Class.forName(className);
					ConnectionBaseInterface base = (ConnectionBaseInterface) cl.newInstance();
					return base.openPrim(name.substring(name.indexOf(':') + 1), mode, timeouts);
				} catch (ClassNotFoundException ex) {
					Logger.debug("connection [" + protocol + "] class not found", e);
					Logger.debug("connection [" + protocol + "] class not found", ex);
					throw new ConnectionNotFoundException("connection [" + protocol + "] class not found");
				}
			}
		} catch (InstantiationException e) {
			Logger.error("Unable to create", className, e);
			throw new ConnectionNotFoundException();
		} catch (IllegalAccessException e) {
			Logger.error("Unable to create", className, e);
			throw new ConnectionNotFoundException();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy