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

matlabcontrol.MatlabProxyFactoryOptions Maven / Gradle / Ivy

There is a newer version: 4.6.0
Show newest version
/*
 * 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