// 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;
							"classes not defined in MATLAB's Java Virtual Machine");
					e.printStackTrace();
				}

				//Create the remote JMI wrapper and then pass it over RMI to the Java application in its own JVM
				receiver.receiveJMIWrapper(new JMIWrapperRemoteImpl(), _existingSession);
			} catch (RemoteException ex) {
				System.err.println("Connection to Java application could not be established");
				ex.printStackTrace();
			}

			_connectionInProgress.set(false);
		}
	}

	/**
	 * Modifies MATLAB's dynamic class path. Retrieves the current dynamic class path, removes all of the entries
	 * from the previously connected JVM, adds the new ones, and if the classpath is now different, sets a new dynamic
	 * classpath.
	 */
	private static class ModifyCodebaseCallable implements MatlabThreadCallable<Void> {
		private final String[] _toRemove;
		private final String[] _toAdd;

		public ModifyCodebaseCallable(String[] oldRemoteClassPath, String[] newRemoteClassPath) {
			_toRemove = oldRemoteClassPath;
			_toAdd = newRemoteClassPath;
		}

		@Override
// 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;

							"classes not defined in MATLAB's Java Virtual Machine");
					e.printStackTrace();
				}

				//Create the remote JMI wrapper and then pass it over RMI to the Java application in its own JVM
				receiver.receiveJMIWrapper(new JMIWrapperRemoteImpl(), _existingSession);
			} catch (RemoteException ex) {
				System.err.println("Connection to Java application could not be established");
				ex.printStackTrace();
			}

			_connectionInProgress.set(false);
		}
	}

	/**
	 * Modifies MATLAB's dynamic class path. Retrieves the current dynamic class path, removes all of the entries
	 * from the previously connected JVM, adds the new ones, and if the classpath is now different, sets a new dynamic
	 * classpath.
	 */
	private static class ModifyCodebaseCallable implements MatlabThreadCallable<Void> {
		private final String[] _toRemove;
		private final String[] _toAdd;

		public ModifyCodebaseCallable(String[] oldRemoteClassPath, String[] newRemoteClassPath) {
			_toRemove = oldRemoteClassPath;
			_toAdd = newRemoteClassPath;
		}

		@Override
		public Void call(MatlabThreadProxy proxy) throws MatlabInvocationException {