// 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/com/mathworks/jmi/Matlab.java
// public class Matlab {
// 	public static Object mtFevalConsoleOutput(String function, Object[] args, int nargout) throws Exception {
// 		throw new UnsupportedOperationException("stub");
// 	}
// 
// 	public static void whenMatlabIdle(Runnable runnable) {
// 		throw new UnsupportedOperationException("stub");
// 	}
// }
// 
// Path: src/com/mathworks/jmi/NativeMatlab.java
// public class NativeMatlab {
// 	public static boolean nativeIsMatlabThread() {
// 		throw new UnsupportedOperationException("stub");
// 	}
// }


import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import matlabcontrol.MatlabProxy.MatlabThreadCallable;
import matlabcontrol.MatlabProxy.MatlabThreadProxy;
import com.mathworks.jmi.Matlab;
import com.mathworks.jmi.NativeMatlab;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/*
 * Code licensed under new-style BSD (see LICENSE).
 * All code up to tags/original: Copyright (c) 2013, Joshua Kaplan
 * All code after tags/original: Copyright (c) 2016, DiffPlug
 */
package matlabcontrol;





/**
 * Interacts with MATLAB via the undocumented Java MATLAB Interface (JMI).
 * <br><br>
 * This code is inspired by <a href="mailto:whitehouse@virginia.edu">Kamin Whitehouse</a>'s
 * <a href="http://www.cs.virginia.edu/~whitehouse/matlab/JavaMatlab.html">MatlabControl</a>. Fixes to concurrency
 * bugs in this class have been aided by the feedback of several matlabcontrol users, thank you for your feedback!
 * <br><br>
 * This class runs inside of MATLAB's Java Virtual Machine and relies upon the Java MATLAB Interface which is
 * distributed by MathWorks as {@code jmi.jar}. It allows for Java to send {@code eval} and {@code feval} statements to
 * MATLAB and receive results. {@code jmi.jar} is <b>not</b> distributed with matlabcontrol as it is the property of
 * MathWorks. If you wish to compile the source code you will need to reference the version of {@code jmi.jar} that is
 * distributed with your copy of MATLAB. It is located at {@code matlabroot/java/jar/jmi.jar} where {@code matlabroot}
 * is the location of your MATLAB installation. The location of {@code matlabroot} can be determined by executing the
 * {@code matlabroot} command in the MATLAB Command Window.
 * <br><br>
 * This is the only class in matlabcontrol which directly links against code in {@code jmi.jar}. (And therefore also the
 * only class that needs {@code jmi.jar} to be on the classpath in order to compile.) {@link Configuration} also uses
 * code in {@code jmi.jar} but uses reflection to interact with it.
 *
 * @since 3.0.0
 * 
 * @author <a href="mailto:nonother@gmail.com">Joshua Kaplan</a>
 */
class JMIWrapper {
	private static final MatlabThreadOperations THREAD_OPERATIONS = new MatlabThreadOperations();

	private static final EventQueue EVENT_QUEUE = Toolkit.getDefaultToolkit().getSystemEventQueue();
	private static final Method EVENT_QUEUE_DISPATCH_METHOD;

	static {
		try {
			EVENT_QUEUE_DISPATCH_METHOD = EventQueue.class.getDeclaredMethod("dispatchEvent", AWTEvent.class);
		} catch (NoSuchMethodException e) {
			throw new IllegalStateException("java.awt.EventQueue's protected void dispatchEvent(java.awt.AWTEvent) " +
					"method could not be found", e);
		}

		EVENT_QUEUE_DISPATCH_METHOD.setAccessible(true);
	}

	private JMIWrapper() {}

	/**
	 * Exits MATLAB without waiting for MATLAB to return, because MATLAB will not return when exiting.
	 * 
	 * @throws MatlabInvocationException 
	 */
	@SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "False positive.")
	static void exit() {
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				try {
// 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/com/mathworks/jmi/Matlab.java
// public class Matlab {
// 	public static Object mtFevalConsoleOutput(String function, Object[] args, int nargout) throws Exception {
// 		throw new UnsupportedOperationException("stub");
// 	}
// 
// 	public static void whenMatlabIdle(Runnable runnable) {
// 		throw new UnsupportedOperationException("stub");
// 	}
// }
// 
// Path: src/com/mathworks/jmi/NativeMatlab.java
// public class NativeMatlab {
// 	public static boolean nativeIsMatlabThread() {
// 		throw new UnsupportedOperationException("stub");
// 	}
// }


// Path: src/matlabcontrol/JMIWrapper.java
import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import matlabcontrol.MatlabProxy.MatlabThreadCallable;
import matlabcontrol.MatlabProxy.MatlabThreadProxy;
import com.mathworks.jmi.Matlab;
import com.mathworks.jmi.NativeMatlab;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/*
 * Code licensed under new-style BSD (see LICENSE).
 * All code up to tags/original: Copyright (c) 2013, Joshua Kaplan
 * All code after tags/original: Copyright (c) 2016, DiffPlug
 */
package matlabcontrol;





/**
 * Interacts with MATLAB via the undocumented Java MATLAB Interface (JMI).
 * <br><br>
 * This code is inspired by <a href="mailto:whitehouse@virginia.edu">Kamin Whitehouse</a>'s
 * <a href="http://www.cs.virginia.edu/~whitehouse/matlab/JavaMatlab.html">MatlabControl</a>. Fixes to concurrency
 * bugs in this class have been aided by the feedback of several matlabcontrol users, thank you for your feedback!
 * <br><br>
 * This class runs inside of MATLAB's Java Virtual Machine and relies upon the Java MATLAB Interface which is
 * distributed by MathWorks as {@code jmi.jar}. It allows for Java to send {@code eval} and {@code feval} statements to
 * MATLAB and receive results. {@code jmi.jar} is <b>not</b> distributed with matlabcontrol as it is the property of
 * MathWorks. If you wish to compile the source code you will need to reference the version of {@code jmi.jar} that is
 * distributed with your copy of MATLAB. It is located at {@code matlabroot/java/jar/jmi.jar} where {@code matlabroot}
 * is the location of your MATLAB installation. The location of {@code matlabroot} can be determined by executing the
 * {@code matlabroot} command in the MATLAB Command Window.
 * <br><br>
 * This is the only class in matlabcontrol which directly links against code in {@code jmi.jar}. (And therefore also the
 * only class that needs {@code jmi.jar} to be on the classpath in order to compile.) {@link Configuration} also uses
 * code in {@code jmi.jar} but uses reflection to interact with it.
 *
 * @since 3.0.0
 * 
 * @author <a href="mailto:nonother@gmail.com">Joshua Kaplan</a>
 */
class JMIWrapper {
	private static final MatlabThreadOperations THREAD_OPERATIONS = new MatlabThreadOperations();

	private static final EventQueue EVENT_QUEUE = Toolkit.getDefaultToolkit().getSystemEventQueue();
	private static final Method EVENT_QUEUE_DISPATCH_METHOD;

	static {
		try {
			EVENT_QUEUE_DISPATCH_METHOD = EventQueue.class.getDeclaredMethod("dispatchEvent", AWTEvent.class);
		} catch (NoSuchMethodException e) {
			throw new IllegalStateException("java.awt.EventQueue's protected void dispatchEvent(java.awt.AWTEvent) " +
					"method could not be found", e);
		}

		EVENT_QUEUE_DISPATCH_METHOD.setAccessible(true);
	}

	private JMIWrapper() {}

	/**
	 * Exits MATLAB without waiting for MATLAB to return, because MATLAB will not return when exiting.
	 * 
	 * @throws MatlabInvocationException 
	 */
	@SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "False positive.")
	static void exit() {
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				try {
					Matlab.mtFevalConsoleOutput("exit", null, 0);