matlabcontrol.MatlabProxyFactoryOptions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of matconsolectl Show documentation
Show all versions of matconsolectl Show documentation
MatConsoleCtl - control MATLAB from Java
/*
* 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;
import java.io.File;
import java.io.Writer;
import java.util.concurrent.atomic.AtomicLong;
import matlabcontrol.MatlabProxyFactory.CopyPasteCallback;
/**
* Options that configure how a factory operates. Use a {@link Builder} to create an instance of this class.
*
* This class is unconditionally thread-safe.
*
* @see MatlabProxyFactory#MatlabProxyFactory(matlabcontrol.MatlabProxyFactoryOptions)
* @since 4.0.0
* @author Joshua Kaplan
*/
public class MatlabProxyFactoryOptions {
private final String _matlabLocation;
private final File _startingDirectory;
private final boolean _hidden;
private final boolean _usePreviouslyControlled;
private final boolean _osgiClassloaderFriendly;
private final CopyPasteCallback _copyPasteCallback;
private final long _proxyTimeout;
private final String _logFile;
private final Integer _jdbPort;
private final String _licenseFile;
private final boolean _useSingleCompThread;
private final int _port;
private final Writer _outputWriter;
private final Writer _errorWriter;
private MatlabProxyFactoryOptions(Builder options) {
_matlabLocation = options._matlabLocation;
_startingDirectory = options._startingDirectory;
_hidden = options._hidden;
_usePreviouslyControlled = options._usePreviouslyControlled;
_osgiClassloaderFriendly = options._osgiClassloaderFriendly;
_copyPasteCallback = options._copyPasteCallback;
_proxyTimeout = options._proxyTimeout.get();
_logFile = options._logFile;
_jdbPort = options._jdbPort;
_licenseFile = options._licenseFile;
_useSingleCompThread = options._useSingleCompThread;
_port = options._port;
_outputWriter = options._outputWriter;
_errorWriter = options._errorWriter;
}
String getMatlabLocation() {
return _matlabLocation;
}
File getStartingDirectory() {
return _startingDirectory;
}
boolean getHidden() {
return _hidden;
}
boolean getOsgiClassloaderFriendly() {
return _osgiClassloaderFriendly;
}
boolean getUsePreviouslyControlledSession() {
return _usePreviouslyControlled;
}
CopyPasteCallback getCopyPasteCallback() {
return _copyPasteCallback;
}
long getProxyTimeout() {
return _proxyTimeout;
}
String getLogFile() {
return _logFile;
}
Integer getJavaDebugger() {
return _jdbPort;
}
String getLicenseFile() {
return _licenseFile;
}
boolean getUseSingleComputationalThread() {
return _useSingleCompThread;
}
int getPort() {
return _port;
}
Writer getOutputWriter() {
return _outputWriter;
}
Writer getErrorWriter() {
return _errorWriter;
}
/**
* Creates instances of {@link MatlabProxyFactoryOptions}. Any and all of these properties may be left unset, if so
* then a default will be used. Depending on how the factory operates, not all properties may be used. Currently all
* properties are used only when running outside MATLAB, but future releases may add additional options.
*
* Calls on this class may be chained together to easily create factory options. Example usage:
*
* {@code
* MatlabProxyFactoryOptions options = new MatlabProxyFactoryOptions.Builder()
* .setHidden(true)
* .setProxyTimeout(30000L)
* .build();
* }
*
* This class is unconditionally thread-safe.
*
* @since 4.0.0
* @author Joshua Kaplan
*/
public static class Builder {
private volatile String _matlabLocation = null;
private volatile File _startingDirectory = null;
private volatile boolean _hidden = false;
private volatile boolean _usePreviouslyControlled = false;
private volatile boolean _osgiClassloaderFriendly = false;
private volatile CopyPasteCallback _copyPasteCallback = null;
private volatile String _logFile = null;
private volatile Integer _jdbPort = null;
private volatile String _licenseFile = null;
private volatile boolean _useSingleCompThread = false;
private volatile int _port = 2100;
private volatile Writer _outputWriter = null;
private volatile Writer _errorWriter = null;
//Assigning to a long is not atomic, so use an AtomicLong so that a thread always sees an intended value
private final AtomicLong _proxyTimeout = new AtomicLong(180000L);
/**
* Sets the location of the MATLAB executable or script that will launch MATLAB. If the value set cannot be
* successfully used to launch MATLAB, an exception will be thrown when attempting to create a proxy.
*
* The absolute path to the MATLAB executable can be determined by running MATLAB. On OS X or Linux, evaluate
* {@code [matlabroot '/bin/matlab']} in the Command Window. On Windows, evaluate
* {@code [matlabroot '/bin/matlab.exe']} in the Command Window. The location provided does not have to be an
* absolute path so long as the operating system can resolve the path.
*
* Windows
* Locations relative to the following will be understood:
*
* - The current working directory
* - The {@code Windows} directory only (no subdirectories are searched)
* - The {@code Windows\System32} directory
* - Directories listed in the {@code PATH} environment variable
* - App Paths defined in the registry with key
* {@code HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths}
*
* By default on Windows, MATLAB adds itself to the {@code PATH} environment variable as well as places an
* App Path entry in the registry so that {@code matlab} can be used to launch MATLAB. If this property is not
* set, then the {@code PATH} environment variable or the App Path entry will be used.
*
* OS X
* Locations relative to the following will be understood:
*
* - The current working directory
* - Directories listed in the {@code PATH} environment variable
*
* On OS X, MATLAB is installed in {@code /Applications/} as an application bundle. If this property is not set,
* the executable inside of the application bundle will be used.
*
* Linux
* Locations relative to the following will be understood:
*
* - The current working directory
* - Directories listed in the {@code PATH} environment variable
*
* During the installation process on Linux, MATLAB can create a symbolic link named {@code matlab} that can be
* used to launch MATLAB. If this property is not set, this symbolic link will be used.
*
* @param matlabLocation
*/
public final Builder setMatlabLocation(String matlabLocation) {
_matlabLocation = matlabLocation;
return this;
}
/**
* Sets the starting directory for MATLAB.
*
* @param dir
* @throws NullPointerException if {@code dir} is {@code null}
* @throws IllegalArgumentException if {@code dir} does not exist or is not a directory
*/
public final Builder setMatlabStartingDirectory(File dir) {
if (dir == null) {
throw new NullPointerException("dir may not be null");
}
if (!dir.exists()) {
throw new IllegalArgumentException("dir specifies a directory that does not exist");
}
if (!dir.isDirectory()) {
throw new IllegalArgumentException("dir does not specify a directory");
}
_startingDirectory = dir;
return this;
}
/**
* Sets whether MATLAB should appear hidden. By default this property is set to {@code false}. If set to
* {@code true} then the splash screen will not be shown and:
*
* Windows
* The MATLAB Command Window will appear fully minimized.
*
* OS X
* MATLAB will be entirely hidden. The MATLAB session will terminate when the Java application terminates.
*
* Linux
* MATLAB will be entirely hidden. The MATLAB session will terminate when the Java application terminates.
*
* @param hidden
*/
public final Builder setHidden(boolean hidden) {
_hidden = hidden;
return this;
}
/**
* Sets whether to have MATLAB log any output to the MATLAB Command Window (including crash reports) to the
* file specified by {@code logFile}. The validity of {@code logFile} is not checked by matlabcontrol. By
* default output is not logged.
*
* @param logFile
*/
public final Builder setLogFile(String logFile) {
_logFile = logFile;
return this;
}
/**
* Sets whether to enable use of the Java debugger on the MATLAB session using port {@code portnumber}. The
* {@code portnumber} may be in the range {@code 0-65535} so long as it is not reserved or otherwise in use. By
* default the Java debugger is not enabled.
*
* @param portnumber
* @throws IllegalArgumentException if {@code portnumber} is not in the range {@code 0-65535}
*/
public final Builder setJavaDebugger(int portnumber) {
if (portnumber < 0 || portnumber > 65535) {
throw new IllegalArgumentException("port number [" + portnumber + "] must be in the range 0-65535");
}
_jdbPort = portnumber;
return this;
}
/**
* Sets the license file used by MATLAB. By default no license file is specified. On Linux and OS X
* {@code licenseFile} may have the form {@code port@host} or a colon-separated list of license filenames. On
* Windows {@code licenseFile} may have the form {@code port@host}. Setting this option causes the
* {@code LM_LICENSE_FILE} and {@code MLM_LICENSE_FILE} environment variables to be ignored. The validity of
* {@code licenseFile} is not checked by matlabcontrol.
*
* @param licenseFile
*/
public final Builder setLicenseFile(String licenseFile) {
_licenseFile = licenseFile;
return this;
}
/**
* Sets whether the factory should attempt to create a proxy that is connected to a running session of MATLAB.
* By default this property is set to {@code false}.
*
* When this property is {@code true} all options which configure MATLAB such as being hidden or logging are
* ignored. The only criterion used is whether a session of MATLAB is available for connection. In order for the
* factory to connect to the session of MATLAB, it must know about the session. This will be the case if a
* factory started the session of MATLAB and that factory was configured to use the same port as specified by
* {@link #setPort(int)} (or both are using the default port). The factory will only connect to a session that
* does not currently have a proxy controlling it from outside of MATLAB.
*
* To determine if the proxy created is connected to an existing session of MATLAB call
* {@link MatlabProxy#isExistingSession()}. You may wish to clear MATLAB's environment using {@code clear}.
* Doing so will not in anyway interfere with matlabcontrol (including executing {@code clear java}).
*
* If a running session of MATLAB previously loaded classes defined in the controlling application, issues
* can arise. If your application does send to MATLAB or retrieve from MATLAB custom
* {@link java.io.Serializable} or {@link java.rmi.Remote} classes then these issues do not apply.
*
* MATLAB sessions launched by matlabcontrol are able to load classes defined in the controlling application.
* When an existing session of MATLAB is connected to by a newly controlling application it will now be able to
* load classes defined by the newly controlling application but not the previous one. Several problems may
* arise due to this behavior. If an attempt is made to use a class defined in a previously controlling session
* that was not loaded while the application was controlling MATLAB then it will fail with a
* {@code ClassNotFoundException} if it is not also defined in the newly controlling application. If the class
* is defined it will fail to load it if the serializable definition is not compatible. A similar issue is if
* the newly controlling application attempts to send to MATLAB an instance of a class that was also defined by
* the previously controlling application but the serializable definition is not compatible. These above issues
* can easily be encountered when developing an application while changing {@code Serializable} or
* {@code Remote} classes and using the same session of MATLAB repeatedly. This will particularly be the case if
* the classes do not define a {@code serialVersionUID}. If multiple instances of the same application do not
* vary in their definition of {@code Serializable} and {@code Remote} classes then connecting to a previously
* controlled session of MATLAB will not cause any issues in this regard.
*
* @param usePreviouslyControlled
*/
public final Builder setUsePreviouslyControlledSession(boolean usePreviouslyControlled) {
_usePreviouslyControlled = usePreviouslyControlled;
return this;
}
/**
* If this is set, then RMI will be initiated in a way
* that doesn't get bogged down by OSGi.
*/
public final Builder setOSGiClassloaderFriendly(boolean osgiClassloaderFriendly) {
_osgiClassloaderFriendly = osgiClassloaderFriendly;
return this;
}
/**
* If this is set, then the factory will pass some MATLAB code to the given callback,
* which should be pasted into the MATLAB command prompt to initiate the connection.
*
* This trumps every other property besides setProxyTimeout().
*/
public final Builder setCopyPasteCallback(CopyPasteCallback copyPasteCallback) {
_copyPasteCallback = copyPasteCallback;
return this;
}
/**
* Sets the amount of time in milliseconds to wait for a proxy to be created when requested via the blocking
* method {@link MatlabProxyFactory#getProxy()}. By default this property is set to {@code 180000} milliseconds.
*
* @param timeout
*
* @throws IllegalArgumentException if timeout is negative
*/
public final Builder setProxyTimeout(long timeout) {
if (timeout < 0L) {
throw new IllegalArgumentException("timeout [" + timeout + "] may not be negative");
}
_proxyTimeout.set(timeout);
return this;
}
/**
* Sets whether to limit MATLAB to a single computational thread. By default this property is set to
* {@code false}.
*
* @param useSingleCompThread
*/
public final Builder setUseSingleComputationalThread(boolean useSingleCompThread) {
_useSingleCompThread = useSingleCompThread;
return this;
}
/**
* Sets the port matlabcontrol uses to communicate with MATLAB. By default port {@code 2100} is used. The port
* value may not be negative. It is recommended to be in the range of {@code 1024} to {@code 49151}, but this
* range is not enforced. The port should be otherwise unused; however, any number of {@link MatlabProxyFactory}
* instances (even those running in completely separate applications) may use the same port. A
* {@code MatlabProxyFactory} will only be able to connect to a previously controlled running session that was
* started by a factory using the same {@code port}.
*
* @param port
* @throws IllegalArgumentException if port is negative
*/
public final Builder setPort(int port) {
if (port < 0) {
throw new IllegalArgumentException("port [" + port + "] may not be negative");
}
_port = port;
return this;
}
/**
* Sets the output writer where the standard output of the created matlab process is written to.
* This is only used when an actual process is spawned for the matlab proxy instance.
*
* @param outputWriter
*/
public final Builder setOutputWriter(Writer outputWriter) {
_outputWriter = outputWriter;
return this;
}
/**
* Sets the error writer where the error output of the created matlab process is written to.
* This is only used when an actual process is spawned for the matlab proxy instance.
*
* @param errorWriter
*/
public final Builder setErrorWriter(Writer errorWriter) {
_errorWriter = errorWriter;
return this;
}
/**
* Builds a {@code MatlabProxyFactoryOptions} instance.
*
* @return factory options
*/
public final MatlabProxyFactoryOptions build() {
return new MatlabProxyFactoryOptions(this);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy