/*-
* Copyright © 2012 Diamond Light Source Ltd., Science and Technology
* Facilities Council Daresbury Laboratory
*
* This file is part of GDA.
*
* GDA is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 3 as published by the Free
* Software Foundation.
*
* GDA is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with GDA. If not, see <http://www.gnu.org/licenses/>.
*/
package gda.configuration.properties;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.commons.configuration.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A utility singleton class which allows the getting of Java properties from a local source file or standard System
* properties.
*/
public class LocalProperties {
private static final Logger logger = LoggerFactory.getLogger(LocalProperties.class);
/**
* Along with {@link #GDA_GIT_LOC} replaces the gda.root variable.
* <p>
* The system property which defines the location of the some of the GDA installation. Within this folder should be
* the IDE's .metadata folder and the third-party plugin, plus any svn checkouts.
* <p>
* At Diamond, the folder structure is, by convention:
* </p>
* <pre>
* <folder named after GDA release version>/
* |
* |-> workspace/ # GDA_WORKSPACE_LOC relates to this folder
* |->tp # thirdparty plugin
* |->plugins # checkout of plugin projects remaining in svn
* |->features # checkout of feature projects remaining in svn
* |
* |->workspace_loc/ # {@link #GDA_GIT_LOC} relates to this folder
* |->gda-xas-core.git/ # folders of each git repository used in this installation at this level
* |->uk.ac.gda.core/ # each plugin project within this git repository at this level
* </pre>
* <p>
* It should not be assumed that the configuration files are relative to this location. This is defined by
* GDA_CONFIG
*/
public static final String GDA_WORKSPACE_LOC = "gda.install.workspace.loc";
/**
* Along with {@link #GDA_WORKSPACE_LOC} replaces the gda.root variable.
* <p>
* The system property which defines the top-level folder holding the various git repositories which make up this
* gda installation.
* <p>
* It should not be assumed that the configuration files are relative to this location. This is defined by
* GDA_CONFIG
*/
public static final String GDA_GIT_LOC = "gda.install.git.loc";
/**
* Property that sets the top-level directory where data is written to. The actual directory the data writers should
* use is defined by gda.data.scan.datawriter.datadir. That property may be dynamic and vary as the current visit
* varies, but the gda.data property should be static at runtime.
*/
public static final String GDA_DATA = "gda.data";
/**
* Name of class in package gda.data.scan.datawriter that is called when ScanDataPoints are available to be written
* Must support interface DataWriter
*/
public static final String GDA_DATA_SCAN_DATAWRITER_DATAFORMAT = "gda.data.scan.datawriter.dataFormat";
/**
* Property used to provide the 'default' property to gda.data.PathConstructor (in uk.ac.gda.core). This in turn
* is used by *many* classes to determine where scan files or images should be written.
*/
public static final String GDA_DATAWRITER_DIR = "gda.data.scan.datawriter.datadir";
/**
* The directory in which to keep NumTracker files. (See NumTracker for alternative ways to specify this).
*/
public static final String GDA_DATA_NUMTRACKER="gda.data.numtracker";
/**
* Property that specifies the GDA configuration folder.
*/
public static final String GDA_CONFIG = "gda.config";
/**
* The location of a global read-write directory for persistence of information which is continued to be used on the
* same beamline from version to version of GDA.
* <p>
* Has been config/var but the recommended location is outside of the configuration directory, at the same level
* that different GDA installations are located.
* <p>
* Directory in which gda.data.NumTracker files are stored.
*/
public static final String GDA_VAR_DIR = "gda.var";
/**
* Property that specifies the folder into which all logs files should be placed.
*/
public static final String GDA_LOGS_DIR = "gda.logs.dir";
/**
* Property that specifies a single GDA properties file.
*/
public static final String GDA_PROPERTIES_FILE = "gda.propertiesFile";
/**
* Property that allows multiple GDA properties files to be specified as a space-separated list.
*/
public static final String GDA_PROPERTIES_FILES = "gda.propertiesFiles";
/**
* Property that specifies the GDA factory name, e.g. "stnBase" or "i04-1".
*/
public static final String GDA_FACTORY_NAME = "gda.factory.factoryName";
/**
* Property that indicates whether GDA is running in local or remote mode.
*/
public static final String GDA_OE_FACTORY = "gda.oe.oefactory";
/**
* Boolean property that indicates whether GDA is using the dummy mode configuration.
*/
public static final String GDA_DUMMY_MODE_ENABLED = "gda.dummy.mode";
/**
* Boolean property that indicates whether GDA access control is enabled.
*/
public static final String GDA_ACCESS_CONTROL_ENABLED = "gda.accesscontrol.useAccessControl";
/**
* Boolean property that indicates whether GDA baton management is enabled.
*/
public static final String GDA_BATON_MANAGEMENT_ENABLED = "gda.accesscontrol.useBatonControl";
/**
* Boolean property that indicates that clients with the same user and visit can share the baton.
*/
private static final String GDA_BATON_SHARING_ENABLED = "gda.accesscontrol.sameUserVisitShareBaton";
/**
* Property that specifies the server-side XML file.
*/
public static final String GDA_OBJECTSERVER_XML = "gda.objectserver.xml";
/**
* Property that specifies the time in millis between isBusy polls in ScannableBase#waitWhileBusy().
*/
public static final String GDA_SCANNABLEBASE_POLLTIME = "gda.scannablebase.polltime.millis";
/**
* Property that specifies the client-side XML file.
*/
public static final String GDA_GUI_XML = "gda.gui.xml";
/**
* XML file used by the RCP client.
*/
public static final String GDA_GUI_BEANS_XML = "gda.gui.beans.xml";
/**
* File containing beam centre and beam size values for each zoom level; read by gda.images.camera.BeamDataComponent
* in uk.ac.gda.px.
*/
public static final String GDA_IMAGES_DISPLAY_CONFIG_FILE = "gda.images.displayConfigFile";
/**
* When reading {@link #GDA_IMAGES_DISPLAY_CONFIG_FILE}, if this is set to {@code true}, the first {@code
* crosshairX} and {@code crosshairY} values will be used for all zoom levels.
*/
public static final String GDA_IMAGES_SINGLE_BEAM_CENTRE = "gda.images.SingleBeamCenter";
/**
* Beamline name, e.g. {@code "i02"}.
*/
public static final String GDA_BEAMLINE_NAME = "gda.beamline.name";
/**
* The on-screen sample image shows the X axis from left to right, but the image can be flipped. This property
* indicates which edge of the image is the +ve side - {@code "left"} or {@code "right"}.
*/
public static final String GDA_IMAGES_HORIZONTAL_DIRECTION = "gda.images.horizontaldirection";
/**
* Property that allows the beamline-specific orientation of the X/Y/Z axes to be specified. It should be a matrix,
* in the form
*/
public static final String GDA_PX_SAMPLE_CONTROL_AXIS_ORIENTATION = "gda.px.samplecontrol.axisorientation";
/**
* Property that specifies the direction of a +ve omega rotation when viewed from behind the goniometer, with the beam
* going from left to right. Should be "clockwise" or "anticlockwise".
*/
public static final String GDA_PX_SAMPLE_CONTROL_OMEGA_DIRECTION = "gda.px.samplecontrol.omegadirection";
/**
* Whether beam axis movements should be considered when moving the sample. Should be {@code true} or {@code false}.
*/
public static final String GDA_PX_SAMPLE_CONTROL_ALLOW_BEAM_AXIS_MOVEMENT = "gda.px.samplecontrol.allowbeamaxismovement";
/**
* Default visit number if an ICAT system is not specified; or connection to ICAT fails; or user is a member of
* staff and has not other available visit ID in the ICAT system.
*/
public static final String GDA_DEF_VISIT = "gda.defVisit";
/**
* This is the default visit that will be used if no default visit is specified by the {@link #GDA_DEF_VISIT} property.
*/
public static final String DEFAULT_VISIT = "0-0";
/**
* The visit which the current RCP application is running under. This should NOT be set in a java.properties file
* but set at runtime once the RCP process has identified which value it wishes to use.
* <p>
* For times when the metadata value is misleading to client-side objects.
*/
public static final String RCP_APP_VISIT = "gda.rcp.application.this.visit";
/**
* The user name (federalid) which the current RCP application is running under. This should NOT be set in a
* java.properties file but set at runtime once the RCP process has identified which value it wishes to use.
* <p>
* For times when the metadata value is misleading to client-side objects.
*/
public static final String RCP_APP_USER = "gda.rcp.application.this.user";
/**
* Extension to be used for NumTracker - to keep Nexus and SrsDataFile in step
*/
public static final String GDA_DATA_NUMTRACKER_EXTENSION = "gda.data.numtracker.extension";
/**
* The number of ScanDataPoints that can be in a gda.scan.MultithreadedScanDataPointPipeline before it starts
* blocking new requests. i.e. the number of points 'behind' the collection completed points can get.
*/
public static final String GDA_SCAN_MULTITHREADED_SCANDATA_POINT_PIPElINE_LENGTH = "gda.scan.multithreadedScanDataPointPipeline.length";
/**
* The number of ScanDataPoints that can be in a gda.scan.MultithreadedScanDataPointPipeline before it starts
* blocking new requests. i.e. the number of points 'behind' the collection completed points can get.
*/
public static final String GDA_SCAN_CONCURRENTSCAN_READOUT_CONCURRENTLY = "gda.scan.concurrentScan.readoutConcurrently";
/**
* The number of threads used by a scan to convert position Callables from PositionCallableProviding Scannables to
* Object positions.
*/
public static final String GDA_SCAN_MULTITHREADED_SCANDATA_POINT_PIPElINE_POINTS_TO_COMPUTE_SIMULTANEOUSELY = "gda.scan.multithreadedScanDataPointPipeline.pointsToComputeSimultaneousely";
/**
* Option to force application window to open with Intro / Welcome screen (default usually false)
*/
public static final String GDA_GUI_FORCE_INTRO = "gda.gui.window.force.intro";
/**
* Option to save and restore the GUI state between sessions. Default 'true'.
* If 'true' the setting to force the Intro/Welcome Screen may have no effect
*/
public static final String GDA_GUI_SAVE_RESTORE = "gda.gui.save.restore";
/**
* Starting width for the GDA application window
*/
public static final String GDA_GUI_START_WIDTH = "gda.gui.window.start.width";
/**
* Starting height for the GDA application window
*/
public static final String GDA_GUI_START_HEIGHT = "gda.gui.window.start.height";
/**
* Maximise the application window at startup
*/
public static final String GDA_GUI_START_MAXIMISE = "gda.gui.window.start.maximise";
/**
* Prefix for the title of the GDA window
*/
public static final String GDA_GUI_TITLEBAR_PREFIX = "gda.gui.titlebar.prefix";
public static final String GDA_GUI_TITLEBAR_SUFFIX = "gda.gui.titlebar.suffix";
/**
* Option to display RCP Workbench default menus (default usually true)
*/
public static final String GDA_GUI_USE_ACTIONS_NEW = "gda.gui.useNewActions";
public static final String GDA_GUI_USE_ACTIONS_SEARCH = "gda.gui.useSearchActions";
public static final String GDA_GUI_USE_ACTIONS_RUN = "gda.gui.useRunActions";
public static final String GDA_GUI_USE_ACTIONS_PERSPECTIVE_CUSTOM = "gda.gui.usePerspectiveCustomActions";
public static final String GDA_GUI_USE_ACTIONS_NEW_EDITOR = "gda.gui.useNewEditorActions";
public static final String GDA_GUI_USE_ACTIONS_NEW_WINDOW = "gda.gui.useNewWindowActions";
public static final String GDA_GUI_USE_ACTIONS_EXPORT = "gda.gui.useExportActions";
public static final String GDA_GUI_USE_ACTIONS_IMPORT = "gda.gui.useImportActions";
/**
* Option to display the RCP Perspective bar
*/
public static final String GDA_GUI_USE_PERSPECTIVE_BAR = "gda.gui.usePerspectiveBar";
/**
* Option to display the RCP main tool bar
*/
public static final String GDA_GUI_USE_TOOL_BAR = "gda.gui.useToolBar";
private static final String GDA_SCAN_SETS_SCANNUMBER = "gda.scan.sets.scannumber";
public static final String GDA_ACTIVEMQ_BROKER_URI = "gda.activemq.broker.uri";
public static String getActiveMQBrokerURI() {
return get(GDA_ACTIVEMQ_BROKER_URI,
String.format("failover:(tcp://%s:%d)?startupMaxReconnectAttempts=3",
get("gda.server.host", "localhost"),
61616));
}
public static void setActiveMQBrokerURI(final String brokerURI) {
set(GDA_ACTIVEMQ_BROKER_URI, brokerURI);
}
/**
* Use to undo {@link LocalProperties#forceActiveMQEmbeddedBroker()} between unit tests
* i.e. call from @org.junit.AfterClass annotated tearDownClass method.
*/
public static void unsetActiveMQBrokerURI() {
setActiveMQBrokerURI(null);
}
/**
* For <a href="http://activemq.apache.org/how-to-unit-test-jms-code.html"/>unit tests</a>
* i.e. call from @org.junit.BeforeClass annotated setUpClass method.
* Undo with {@link LocalProperties#unsetActiveMQBrokerURI()}
* (or {@link LocalProperties#setActiveMQBrokerURI(String)}).
*/
public static void forceActiveMQEmbeddedBroker() {
setActiveMQBrokerURI("vm://localhost?broker.persistent=false");
}
public static boolean isScanSetsScanNumber(){
return LocalProperties.check(LocalProperties.GDA_SCAN_SETS_SCANNUMBER);
}
public static void setScanSetsScanNumber(boolean enable){
LocalProperties.set(LocalProperties.GDA_SCAN_SETS_SCANNUMBER, Boolean.toString(enable));
}
/**
* Property for setting where there is a dataserver running that can access the SWMR files and provide remote datasets
*/
public static final String GDA_DATASERVER_HOST = "gda.dataserver.host";
/**
* Property for setting which port has a dataserver running that can access the SWMR files and provide remote datasets
*/
public static final String GDA_DATASERVER_PORT = "gda.dataserver.port";
// create Jakarta properties handler object
// README - The JakartaPropertiesConfig class automatically picks up
// system
// properties on creation, so they are guaranteed to be present.
private static PropertiesConfig propConfig = new JakartaPropertiesConfig();
static {
String propertiesFiles = propConfig.getString(GDA_PROPERTIES_FILES, null);
if (propertiesFiles == null || propertiesFiles.isEmpty()) {
propertiesFiles = propConfig.getString(GDA_PROPERTIES_FILE, null);
}
if (propertiesFiles == null || propertiesFiles.isEmpty()) {
// assume file is ${gda.config}/properties/java.properties
propertiesFiles = LocalProperties.getConfigDir() + System.getProperty("file.separator") + "properties"
+ System.getProperty("file.separator") + "java.properties";
}
File testExists = new File(propertiesFiles);
if (!testExists.exists()) {
logger.warn("Neither " + GDA_PROPERTIES_FILES + " nor " + GDA_PROPERTIES_FILE + " is set and "
+ propertiesFiles + " does not exist - no properties are available");
} else {
StringTokenizer st = new StringTokenizer(propertiesFiles, " ");
while (st.hasMoreTokens()) {
String propertiesFile = st.nextToken();
try {
propConfig.loadPropertyData(propertiesFile);
} catch (ConfigurationException ex) {
throw new IllegalArgumentException("Error loading " + propertiesFile, ex);
}
// We attempt to set all the properties loaded into System properties
// This allows properties to be loaded from any bundle without making
// a dependency on this bundle. However if this fails in any way then
// it is a non-fatal error. This means that any bundle in any project may
// check GDA properties without making dependencies. This is desirable for
// instance with DAWN so that its bundles may contain specific code for
// GDA configuration without making a hard dependency on LocalProperties
try {
for (Iterator<String> it = propConfig.getKeys(); it.hasNext();) {
String key = it.next();
String value = propConfig.getString(key, null);
if (System.getProperty(key)==null && value!=null) {
System.setProperty("GDA/" + key, value);
}
// We preface with "GDA/" which should mean that no system
// property is affected and also if System properties are dumped,
// they can be filtered to remove GDA ones.
}
} catch (Exception ne) {
logger.error("Cannot parse to system properties: {}", propertiesFile, ne);
}
}
}
}
private final static Properties loadProperties(final String path) throws IOException {
final File file = new File(path);
return loadProperties(file);
}
private final static Properties loadProperties(final File file) throws IOException {
if (!file.exists()) return new Properties();
return loadProperties(new FileInputStream(file));
}
private final static Properties loadProperties(final InputStream stream) throws IOException {
final Properties fileProps = new Properties();
try (final BufferedInputStream in = new BufferedInputStream(stream)){
fileProps.load(in);
}
return fileProps;
}
public static void dumpProperties() {
propConfig.dumpProperties();
}
/**
* Set a group of string-valued properties. An array of strings is passed in and each string is expected to be of
* the form "A=B". Each string is parsed into its a key (A) and a value (B). A string property is then set using
* each key value pair.
*
* @param propertyPairs
* an array of key-value pair assignment strings
*/
public static void parseProperties(String[] propertyPairs) {
StringTokenizer st;
String propertyName;
String propertyValue;
for (int i = 0; i < propertyPairs.length; i++) {
propertyName = null;
propertyValue = null;
st = new StringTokenizer(propertyPairs[i], "=");
if (st.hasMoreTokens())
propertyName = st.nextToken();
if (st.hasMoreTokens())
propertyValue = st.nextToken();
if ((propertyName != null) && (propertyValue != null))
propConfig.setString(propertyValue, propertyName);
}
}
/**
* Get a string property value using a specified key string with windows path separator "\\" being replaced by "/".
*
* @param propertyName
* the key specified to fetch the string value
* @return the property value to return to the caller
*/
public static String get(String propertyName) {
String propertyValue = null;
// README - must return null, instead of "", eg since ObjectServer
// relies
// on unsupplied mapping file path resulting in a null,
// which causes mapping file to be fetched from gda.factory class path
propertyValue = propConfig.getString(propertyName, null);
// README - we're outlawing backslashes - since no distinction between
// string properties and URL/URI/path properties in GDA code
// so have to do this for all property strings.
// It would be nice to move client code over to using getPath instead!
if (propertyValue != null) {
propertyValue = propertyValue.replace('\\', '/');
}
return propertyValue;
}
/**
* Get a boolean property value using a specified key string. No default is specified and "false" is returned if no
* key is found.
*
* @param propertyName
* the key specified to fetch the boolean value
* @return the property value to return to the caller. Returns false if key is not found.
*/
public static boolean check(String propertyName) {
return check(propertyName, false);
}
/**
* Get a boolean property value using a specified key string.
*
* @param propertyName
* the key specified to fetch the boolean value
* @param defaultCheck
* the default value to return if the key is not found
* @return the property value to return to the caller
*/
public static boolean check(String propertyName, boolean defaultCheck) {
return propConfig.getBoolean(propertyName, defaultCheck);
}
/**
* Get an integer property value using a specified key string.
*
* @param propertyName
* the key specified to fetch the integer value
* @param defaultValue
* the default value to return if the key is not found
* @return the property value to return to the caller
*/
public static int getInt(String propertyName, int defaultValue) {
return propConfig.getInteger(propertyName, defaultValue);
}
/**
* Get a double property value using a specified key string.
*
* @param propertyName
* the key specified to fetch the double value
* @param defaultValue
* the default value to return if the key is not found
* @return the property value to return to the caller
*/
public static double getDouble(String propertyName, double defaultValue) {
return propConfig.getDouble(propertyName, defaultValue);
}
/**
* Get a string property value using a specified key string.
*
* @param propertyName
* the key specified to fetch the string value
* @param defaultValue
* the default value to return if the key is not found
* @return the property value to return to the caller
*/
public static String get(String propertyName, String defaultValue) {
String value = propConfig.getString(propertyName, defaultValue);
// README - we're outlawing backslashes - since no distinction between
// string properties and URL/URI/path properties in GDA code
// so have to do this for all property strings.
// It would be nice to move client code over to using getPath instead!
if (value != null) {
value = value.replace('\\', '/');
}
return value;
}
/**
* Get a file path property value using a specified key string.
*
* @param name
* the key specified to fetch the file path value
* @param defaultValue
* the default value to return if the key is not found
* @return the property value to return to the caller
*/
public static String getPath(String name, String defaultValue) {
// README - backslashes are replaced with forward slashes in here,
// since we know its a path and its safe to do this.
return propConfig.getPath(name, defaultValue);
}
/**
* Get a URL property value using a specified key string.
*
* @param name
* the key specified to fetch the URL value
* @param defaultValue
* the default value to return if the key is not found
* @return the property value to return to the caller
*/
public static URL getURL(String name, URL defaultValue) {
return propConfig.getURL(name, defaultValue);
}
/**
* Assign a string property value to a specified key string.
*
* @param propertyName
* the key specified to assign to the value
* @param value
* the string value to assign to the specified key
*/
public static void set(String propertyName, String value) {
propConfig.setString(value, propertyName);
}
/**
* Determines whether GDA is using the dummy mode configuration.
*
* @return true if GDA is using the dummy mode configuration; false otherwise. False is default to make dummy mode the exception.
*/
public static boolean isDummyModeEnabled() {
return check(LocalProperties.GDA_DUMMY_MODE_ENABLED, false);
}
/**
* Determines whether access control is enabled.
*
* @return true if access control is enabled; false otherwise. False is default to keep original behaviour.
*/
public static boolean isAccessControlEnabled() {
return check(LocalProperties.GDA_ACCESS_CONTROL_ENABLED, false);
}
/**
* Determines whether baton management is enabled.
*
* @return true if baton management is enabled; false otherwise. False is default to keep original behaviour.
*/
public static boolean isBatonManagementEnabled() {
return check(LocalProperties.GDA_BATON_MANAGEMENT_ENABLED, false);
}
/**
* @return true if with the same user and visit ID can share the baton. False by default.
*/
public static boolean canShareBaton() {
return check(LocalProperties.GDA_BATON_SHARING_ENABLED, false);
}
/**
* Returns the location of the 'lib' folder in the 'core' plugin.
*
* @return the location of the core plugin's lib folder
*/
public static String getCoreLibraryDirectory() {
return getParentGitDir() + "gda-core.git/uk.ac.gda.core/lib/";
}
/**
* {@link #GDA_WORKSPACE_LOC}
* @return String
*/
public static String getInstallationWorkspaceDir() {
return appendSeparator(get(GDA_WORKSPACE_LOC));
}
/**
* {@link #GDA_GIT_LOC}
* @return String
*/
public static String getParentGitDir() {
return appendSeparator(get(GDA_GIT_LOC));
}
/**
* {@link #GDA_CONFIG}
* @return String
*/
public static String getConfigDir() {
return appendSeparator(get(GDA_CONFIG));
}
private static String appendSeparator(String file) {
if (file == null || file.isEmpty()) {
return file;
}
if (!file.endsWith(System.getProperty("file.separator"))) {
return file + System.getProperty("file.separator");
}
return file;
}
/**
* If the property gda.var is not defined, then it is assumed that there is a var dir inside the config directory
* (where var was previously recommended to be placed)
*
* @see #GDA_VAR_DIR
*/
public static String getVarDir() {
String gda_var = appendSeparator(get(GDA_VAR_DIR));
if (gda_var == null) {
gda_var = getConfigDir() + "/var";
}
return appendSeparator(gda_var);
}
/**
* @return String
* @see #GDA_DATA
*/
public static String getBaseDataDir() {
return appendSeparator(get(GDA_DATA));
}
/**
* @param s
* @return list of integers from a csv string e.g. 1,2 yields [1,2] returns null if property
*/
public static List<Integer> stringToIntList(String s) {
if (s == null)
return null;
Vector<Integer> ints = new Vector<Integer>();
String[] parts = s.split("[:, \t\r\n]");
for (String part : parts) {
if (!part.isEmpty())
ints.add(Integer.valueOf(part));
}
return ints;
}
/**
* @param propertyName
* @return Value of a property as a list of integers e.g. a value of 1 2 3 returns [1,2,3]. DO NOT USE commas
*/
public static List<Integer> getAsIntList(String propertyName) {
return stringToIntList(get(propertyName));
}
/**
* @param propertyName
* @param defaultValue
* The list of default values to return if the propertyName does not exist
* @return Value of a property as a list of integers e.g. a value of 1 2 3 returns [1,2,3]. DO NOT USE commas
*/
public static List<Integer> getAsIntList(String propertyName, Integer[] defaultValue) {
List<Integer> result = getAsIntList(propertyName);
return result != null ? result : new ArrayList<Integer>(Arrays.asList(defaultValue));
}
/**
* Get the value of the named property as an <code>int</code> value.
* <p>
* This method will throw NullPointerException if the property is undefined. To avoid this, call {@link
* #getAsInt(String, int)} instead.
*
* @param propertyName
* the property to find
* @return the value of the named property, as an int
* @throws NullPointerException
* if the named property is not defined
* @throws NumberFormatException
* if the named property is defined but cannot be parsed as an int
*/
public static int getAsInt(String propertyName) {
String s = get(propertyName);
if (s != null) {
return Integer.valueOf(s).intValue();
}
String message = "Property " + propertyName + " is not defined";
logger.error(message);
// This method used to return Integer, not int (despite the name!)
// In all uses of the method, though, the result was assigned directly to an int without null checking, which
// would throw a NullPointerException if the Integer value was null. Therefore, if the property is not defined,
// we now throw an NPE to ensure behaviour remains the same.
throw new NullPointerException(message);
}
/**
* Get the value of the named property as an <code>int</code> value. If the property is not defined, the given
* default value is returned.
*
* @param propertyName
* the property to find
* @param defaultValue
* the value to return if the propertyName is not defined
* @return the value of the named property, as an int
* @throws NumberFormatException
* if the named property is defined but cannot be parsed as an int
*/
public static int getAsInt(String propertyName, int defaultValue) {
String s = get(propertyName);
return s != null ? Integer.valueOf(s).intValue() : defaultValue;
}
public static boolean contains(String propertyName) {
return propConfig.containsKey(propertyName);
}
/**
* Remove a property from the configuration
*
* @param key
*/
public static void clearProperty(String key) {
propConfig.clearProperty(key);
}
public static void checkForObsoleteProperties() {
final String GDA_OBJECT_DELIMITER = "gda.objectDelimiter";
if (get(GDA_OBJECT_DELIMITER) != null) {
logger.warn("Please remove the '{}' property from your java.properties file - it is not used any more", GDA_OBJECT_DELIMITER);
}
final String GDA_EVENTRECEIVER_PURGE = "gda.eventreceiver.purge";
if (get(GDA_EVENTRECEIVER_PURGE) != null) {
logger.warn("Please remove the '{}' property from your java.properties file - CorbaEventReceiver does not purge events any more",
GDA_EVENTRECEIVER_PURGE);
}
final String GDA_USERS = "gda.users";
if (get(GDA_USERS) != null) {
logger.warn("Please remove the '{}' property from your java.properties file - this property was used ambiguously and should not be used any more",
GDA_USERS);
}
final String GDA_JYTHON_GDASCRIPTDIR = "gda.jython.gdaScriptDir";
if (get(GDA_JYTHON_GDASCRIPTDIR) != null) {
logger.warn(
"Please remove the '{}' property from your java.properties file - script paths are defined in the Spring configuration for the command_server.",
GDA_JYTHON_GDASCRIPTDIR);
}
final String GDA_JYTHON_USERSCRIPTDIR = "gda.jython.userScriptDir";
if (get(GDA_JYTHON_USERSCRIPTDIR) != null) {
logger.warn(
"Please remove the '{}' property from your java.properties file - script paths are defined in the Spring configuration for the command_server.",
GDA_JYTHON_USERSCRIPTDIR);
}
}
public static String[] getStringArray(String propertyName) {
return propConfig.getStringArray(propertyName);
}
}