// Path: src/matlabcontrol/MatlabProxy.java
// public static interface MatlabThreadCallable<T> {
// 	/**
// 	 * Performs the computation in MATLAB. The {@code proxy} provided will invoke its methods directly on MATLAB's
// 	 * main thread without delay. This {@code proxy} should be used to interact with MATLAB, not a
// 	 * {@code MatlabProxy} (or any class delegating to it).
// 	 * 
// 	 * @param proxy
// 	 * @return result of the computation
// 	 * @throws MatlabInvocationException
// 	 */
// 	public T call(MatlabThreadProxy proxy) throws MatlabInvocationException;
// }
// 
// Path: src/matlabcontrol/MatlabProxy.java
// public static interface MatlabThreadProxy extends MatlabOperations {
// 
// }
// 
// Path: src/matlabcontrol/internal/MatlabRMIClassLoaderSpi.java
// public class MatlabRMIClassLoaderSpi extends RMIClassLoaderSpi {
// 	/**
// 	 * Loading of classes is delegated to the default {@link RMIClassLoaderSpi}.
// 	 */
// 	private final RMIClassLoaderSpi _delegateLoaderSpi = RMIClassLoader.getDefaultProviderInstance();
// 
// 	/**
// 	 * The codebase of the external virtual machine which has a proxy that can interact with this session of MATLAB.
// 	 * This is done instead of setting the {@code java.rmi.server.codebase} property so that matlabcontrol does not
// 	 * interfere with any other uses of RMI in the application.
// 	 */
// 	private static volatile String _remoteCodebase = null;
// 
// 	/**
// 	 * Sets the codebase of the currently connected external JVM. This should be called only once per connection to an
// 	 * external JVM and should occur before users of the API can send objects over RMI.
// 	 * 
// 	 * @param remoteCodebase 
// 	 */
// 	public static void setCodebase(String remoteCodebase) {
// 		_remoteCodebase = remoteCodebase;
// 	}
// 
// 	@Override
// 	public Class<?> loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException {
// 		return _delegateLoaderSpi.loadClass(_remoteCodebase, name, defaultLoader);
// 	}
// 
// 	@Override
// 	public Class<?> loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException {
// 		return _delegateLoaderSpi.loadProxyClass(_remoteCodebase, interfaces, defaultLoader);
// 	}
// 
// 	@Override
// 	public ClassLoader getClassLoader(String codebase) throws MalformedURLException {
// 		return _delegateLoaderSpi.getClassLoader(_remoteCodebase);
// 	}
// 
// 	/**
// 	 * {@inheritDoc}
// 	 * <br><br>
// 	 * The returned annotation becomes the {@code codebase} argument in
// 	 * {@link #loadClass(java.lang.String, java.lang.String, java.lang.ClassLoader)} when the {@code RMIClassLoaderSpi}
// 	 * in the receiving JVM attempts to load {@code clazz}. This allows for classes defined in MATLAB but not in the
// 	 * receiving JVM to find and load the class definition.
// 	 * 
// 	 * @param clazz
// 	 * @return 
// 	 */
// 	@Override
// 	public String getClassAnnotation(Class<?> clazz) {
// 		if (clazz == null) {
// 			throw new NullPointerException("class may not be null");
// 		}
// 
// 		String annotation = null;
// 
// 		//If the class has a code source, meaning it is not part of the Java Runtime Environment
// 		if (clazz.getProtectionDomain().getCodeSource() != null) {
// 			//This convoluted way of determining the code source location is necessary due to a bug in early versions of
// 			//Java 6 on Windows (such as what is used by MATLAB R2007b) which puts a space in the code source's URL.
// 			//A space in the URL will cause the receiver of this annotation to treat it as a path separator, which would
// 			//be very problematic and likely cause invalid protocol exceptions.
// 			try {
// 				File file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().getPath());
// 				annotation = file.toURI().toURL().toString();
// 			} catch (MalformedURLException e) {}
// 		}
// 
// 		return annotation;
// 	}
// }


import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import matlabcontrol.MatlabProxy.MatlabThreadCallable;
import matlabcontrol.MatlabProxy.MatlabThreadProxy;
import matlabcontrol.internal.MatlabRMIClassLoaderSpi;
					connected = true;
				} catch (RemoteException e) {}
			}

			available = !connected;
		}

		return available;
	}

	/**
	 * Called from MATLAB at launch. Creates the JMI wrapper and then sends it over RMI to the Java program running in a
	 * separate JVM.
	 * 
	 * @param receiverID the key that binds the receiver in the registry
	 * @param port the port the registry is running on
	 * @param initializationTime
	 */
	public static void connectFromMatlab(String receiverID, int port) {
		connect(receiverID, port, false);
	}

	/**
	 * Retrieves the receiver and sends over the {@link JMIWrapperRemote} on a separate thread so that MATLAB can
	 * continue to initialize.
	 * 
	 * @param receiverID
	 * @param port
	 * @param existingSession 
	 */
// Path: src/matlabcontrol/MatlabProxy.java
// public static interface MatlabThreadCallable<T> {
// 	/**
// 	 * Performs the computation in MATLAB. The {@code proxy} provided will invoke its methods directly on MATLAB's
// 	 * main thread without delay. This {@code proxy} should be used to interact with MATLAB, not a
// 	 * {@code MatlabProxy} (or any class delegating to it).
// 	 * 
// 	 * @param proxy
// 	 * @return result of the computation
// 	 * @throws MatlabInvocationException
// 	 */
// 	public T call(MatlabThreadProxy proxy) throws MatlabInvocationException;
// }
// 
// Path: src/matlabcontrol/MatlabProxy.java
// public static interface MatlabThreadProxy extends MatlabOperations {
// 
// }
// 
// Path: src/matlabcontrol/internal/MatlabRMIClassLoaderSpi.java
// public class MatlabRMIClassLoaderSpi extends RMIClassLoaderSpi {
// 	/**
// 	 * Loading of classes is delegated to the default {@link RMIClassLoaderSpi}.
// 	 */
// 	private final RMIClassLoaderSpi _delegateLoaderSpi = RMIClassLoader.getDefaultProviderInstance();
// 
// 	/**
// 	 * The codebase of the external virtual machine which has a proxy that can interact with this session of MATLAB.
// 	 * This is done instead of setting the {@code java.rmi.server.codebase} property so that matlabcontrol does not
// 	 * interfere with any other uses of RMI in the application.
// 	 */
// 	private static volatile String _remoteCodebase = null;
// 
// 	/**
// 	 * Sets the codebase of the currently connected external JVM. This should be called only once per connection to an
// 	 * external JVM and should occur before users of the API can send objects over RMI.
// 	 * 
// 	 * @param remoteCodebase 
// 	 */
// 	public static void setCodebase(String remoteCodebase) {
// 		_remoteCodebase = remoteCodebase;
// 	}
// 
// 	@Override
// 	public Class<?> loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException {
// 		return _delegateLoaderSpi.loadClass(_remoteCodebase, name, defaultLoader);
// 	}
// 
// 	@Override
// 	public Class<?> loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException {
// 		return _delegateLoaderSpi.loadProxyClass(_remoteCodebase, interfaces, defaultLoader);
// 	}
// 
// 	@Override
// 	public ClassLoader getClassLoader(String codebase) throws MalformedURLException {
// 		return _delegateLoaderSpi.getClassLoader(_remoteCodebase);
// 	}
// 
// 	/**
// 	 * {@inheritDoc}
// 	 * <br><br>
// 	 * The returned annotation becomes the {@code codebase} argument in
// 	 * {@link #loadClass(java.lang.String, java.lang.String, java.lang.ClassLoader)} when the {@code RMIClassLoaderSpi}
// 	 * in the receiving JVM attempts to load {@code clazz}. This allows for classes defined in MATLAB but not in the
// 	 * receiving JVM to find and load the class definition.
// 	 * 
// 	 * @param clazz
// 	 * @return 
// 	 */
// 	@Override
// 	public String getClassAnnotation(Class<?> clazz) {
// 		if (clazz == null) {
// 			throw new NullPointerException("class may not be null");
// 		}
// 
// 		String annotation = null;
// 
// 		//If the class has a code source, meaning it is not part of the Java Runtime Environment
// 		if (clazz.getProtectionDomain().getCodeSource() != null) {
// 			//This convoluted way of determining the code source location is necessary due to a bug in early versions of
// 			//Java 6 on Windows (such as what is used by MATLAB R2007b) which puts a space in the code source's URL.
// 			//A space in the URL will cause the receiver of this annotation to treat it as a path separator, which would
// 			//be very problematic and likely cause invalid protocol exceptions.
// 			try {
// 				File file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().getPath());
// 				annotation = file.toURI().toURL().toString();
// 			} catch (MalformedURLException e) {}
// 		}
// 
// 		return annotation;
// 	}
// }


// Path: src/matlabcontrol/MatlabConnector.java
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import matlabcontrol.MatlabProxy.MatlabThreadCallable;
import matlabcontrol.MatlabProxy.MatlabThreadProxy;
import matlabcontrol.internal.MatlabRMIClassLoaderSpi;

					connected = true;
				} catch (RemoteException e) {}
			}

			available = !connected;
		}

		return available;
	}

	/**
	 * Called from MATLAB at launch. Creates the JMI wrapper and then sends it over RMI to the Java program running in a
	 * separate JVM.
	 * 
	 * @param receiverID the key that binds the receiver in the registry
	 * @param port the port the registry is running on
	 * @param initializationTime
	 */
	public static void connectFromMatlab(String receiverID, int port) {
		connect(receiverID, port, false);
	}

	/**
	 * Retrieves the receiver and sends over the {@link JMIWrapperRemote} on a separate thread so that MATLAB can
	 * continue to initialize.
	 * 
	 * @param receiverID
	 * @param port
	 * @param existingSession 
	 */
	static void connect(String receiverID, int port, boolean existingSession) {