// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/Environment.java,v $
// $RCSfile: Environment.java,v $
// $Revision: 1.7.2.2 $
// $Date: 2004/10/14 18:26:36 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap;
import java.applet.Applet;
import java.awt.Color;
import java.io.File;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.JRootPane;
import javax.swing.JLayeredPane;
import javax.swing.JApplet;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;
/**
* An Environment is a set of property lists that together specify the
* runtime environment for this process.
* <p>
* There is only one Environment, and it is accessed through static
* member functions.
* <p>
* The environment is comprised of at least three property lists:
* <ul>
* <li>System properties form the basis of the environment. For
* applications, This can be the System.getProperties(), or something
* else. In the case of applets, this is a list of the ten system
* properties that applets are allowed to access plus any applet
* parameters.
* <p>
* <li>Runtime properties are checked next. These are properties that
* exist only while the process is running. They are calculated during
* Environment initialization and are not persistent.
* <p>
* <li>Hardcoded properties form the last level. These properties are
* hardcoded default values that are specified in the code of this
* file. They are meant to be used as a last resort.
* <p>
* </ul>
* When <code>Environment.get()</code> is called, all lists are
* searched until the property is found. System properties are
* searched first, then runtime properties, and then hardcoded
* properties.
* <p>
* This search pattern allows system properties and properties
* specified as applet parameters or command line properties (using
* -DProperty=value Java flag) to override more hardcoded properties
* specified elsewhere, say in a user preferences file.
*
* @see java.util.Properties
*
* <pre>
*
*
*
* # metanames of the names of the variables used in the OpenMap
* # system to configure the Enivironment class from the properties.
* openmap.Title - String for title of application window.
* openmap.Version - Version number of application.
* openmap.BuildDate - Build data of code base.
* openmap.WebBrowser - The launch command to launch a browser.
* openmap.TempDirectory - A path to a directory to use for temporary files.
* openmap.UseInternalFrames - For an application, to direct it to use InternalFrames for other windows.
* openmap.Latitude - Starting latitude for map projection.
* openmap.Longitude - Starting longitude for map projection.
* openmap.Scale - Starting scale for map projection.
* openmap.Projection - Starting projection type for map projection.
* openmap.Width - Pixel width for map.
* openmap.Height - Pixel height for map.
* openmap.HelpURL - The URL to use for OpenMap/Application help pages.
* openmap.BackgroundColor - An ARGB integer to use for the background (sea) color.
* openmap.Debug - Debug tokens to activate for printout. @see com.bbn.openmap.util.Debug
*
* openmap.UniqueID String for unique identification of OpenMap instance (calculated)
*
*
*
* </pre>
*/
public class Environment extends Properties {
/*--------------------------------------------------
* To Do:
*
* Save user properties
*
* User properties editor
*
*--------------------------------------------------*/
protected static Environment env;
protected Properties hardcodedProps;
protected Properties runtimeProps;
protected JLayeredPane desktop = null;
protected static Applet applet;
private static int counter = 0;
private static transient Vector extraPaths = new Vector();
// user preferences file (used for later references)
public static transient final String OpenMapPrefix = "openmap";
public static transient final String PreferencesURL = OpenMapPrefix
+ ".PreferencesURL";
// metanames of the names of the variables used in the OpenMap
// system
public static transient final String Title = OpenMapPrefix + ".Title";
public static transient final String Version = OpenMapPrefix + ".Version";
public static transient final String BuildDate = OpenMapPrefix
+ ".BuildDate";
public static transient final String UniqueID = OpenMapPrefix + ".UniqueID";
public static transient final String WebBrowser = OpenMapPrefix
+ ".WebBrowser";
public static transient final String TmpDir = OpenMapPrefix
+ ".TempDirectory";
public static transient final String UseInternalFrames = OpenMapPrefix
+ ".UseInternalFrames";
public static transient final String Latitude = OpenMapPrefix + ".Latitude";
public static transient final String Longitude = OpenMapPrefix
+ ".Longitude";
public static transient final String Scale = OpenMapPrefix + ".Scale";
public static transient final String Projection = OpenMapPrefix
+ ".Projection";
public static transient final String Width = OpenMapPrefix + ".Width";
public static transient final String Height = OpenMapPrefix + ".Height";
public static transient final String HelpURL = OpenMapPrefix + ".HelpURL";
public static transient final String BackgroundColor = OpenMapPrefix
+ ".BackgroundColor";
public static transient final String DebugList = OpenMapPrefix + ".Debug";
// default to false
private static transient boolean isXWindows = false;
// Will do it if isXWindows
public static transient boolean doingXWindowsWorkaround = false;
public final static transient String title = "$$Title=" + MapBean.title;
public final static transient String version = "$$Version="
+ MapBean.version;
// autobuild should set this.
public final static transient String build = "$$BuildDate=";
/**
* Hardcoded default properties.
* <p>
* These should be edited before each new version/installation of
* OpenMap. They are declared in such a way that they can be
* easily edited from a build script.
*
* @param p Properties
*/
protected final static void initHardCodedProperties(Properties p) {
StringTokenizer tokenizer;
tokenizer = new StringTokenizer(title, "=");
tokenizer.nextToken();
p.put(Title, tokenizer.nextToken());
tokenizer = new StringTokenizer(version, "=");
tokenizer.nextToken();
p.put(Version, tokenizer.nextToken());
tokenizer = new StringTokenizer(build, "=");
tokenizer.nextToken();
try {
p.put(BuildDate, tokenizer.nextToken());
} catch (NoSuchElementException e) {
}// no BuildDate
}
/**
* Initializes the environment of an applet.
*
* @param applet An applet
* @see java.applet.Applet
*/
public static void init(Applet applet) {
if (applet == null) {
init(System.getProperties());
} else {
if (env != null) {
// overwrite properties
Debug.output("Reinitializing Applet Environment!");
setApplet(applet);
env.setAppletProperties(applet, env);
return;
}
new Environment(applet);
}
if (Debug.debugging("env")) {
env.list(System.out);
}
}
/**
* Initializes the environment of an application.
*
* @param sysProps Runtime/System Properties (Toplevel)
*/
public static void init(Properties sysProps) {
if (env != null) {
// Debug.output("Reinitializing Environment!");
// overwrite properties
env.installProps(sysProps);
return;
}
new Environment(sysProps);
if (Debug.debugging("env"))
env.list(System.out);
}
/**
* Initializes the OpenMap environment. Installs the default
* System Properties into the Environment.
*/
public static void init() {
init(System.getProperties());
}
/**
* Creates an Environment based on applet properties.
*
* @param applet an Applet
*/
protected Environment(Applet applet) {
env = this;
setApplet(applet);
setAppletProperties(applet, this);
commonInit();
}
/**
* Creates an Environment with the specified system properties.
*
* @param sysProps system properties
*/
protected Environment(Properties sysProps) {
env = this;
installProps(sysProps);
commonInit();
}
/**
* install Properties directly into the toplevel Environment list.
*
* @param sysProps system properties
*
*/
private void installProps(Properties sysProps) {
// Copy the specified property list
Enumeration e = sysProps.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String val = (String) sysProps.getProperty(key);
try {
this.put(key, val);
} catch (NullPointerException ex) {
// Key or Value must have been null. C'est la vie.
}
}
}
/**
* Adds runtime, user, and base properties to the Environment.
*/
protected void commonInit() {
hardcodedProps = new Properties();
runtimeProps = new Properties(hardcodedProps);
// the Environment defaults are the properties lists just
// constructed
defaults = runtimeProps;
initHardCodedProperties(hardcodedProps);
initRuntimeProperties(runtimeProps);
}
/**
* Populates the system properties for an applet. Currently this
* property list contains the ten system properties available to
* applets and any applet parameters specified in
* Applet.getParameterInfo().
*
* @param applet the applet
* @see java.applet.Applet#getParameterInfo
*/
protected void setAppletProperties(Applet applet, Properties props) {
/*
* These are the ten properties available to applets.
*/
final String[] appletProps = { "java.version", "java.vendor",
"java.vendor.url", "java.class.version", "os.name", "os.arch",
"os.version", "file.separator", "path.separator",
"line.separator" };
int i;
for (i = 0; i < appletProps.length; i++) {
String prop = appletProps[i];
props.put(prop, System.getProperty(prop));
}
String[][] pinfo = applet.getParameterInfo();
if (pinfo == null)
return;
for (i = 0; i < pinfo.length; i++) {
try {
String key = pinfo[i][0];
String value = applet.getParameter(key);
Debug.message("env", "Applet Parameter " + key + " has value "
+ value);
props.put(key, value);
} catch (NullPointerException e) {
}
}
}
/**
* Initializes the runtime properties list. Runtime properties are
* those properties that exist only while the program is running.
* They are not persistent. Persistent properties should be stored
* in the user properties list.
*
* @param p The runtime properties list
*/
protected static void initRuntimeProperties(Properties p) {
if (isApplet()) {
p.put("user.name", "appletUser");//for convenience
}
java.net.InetAddress addr = null;
try {
addr = java.net.InetAddress.getLocalHost();
} catch (NullPointerException npe) {
// Linux threw a npe when unconnected.
Debug.output("Environment.init: Can't get hostname from InetAddress!");
} catch (java.net.UnknownHostException e) {
Debug.output("Environment.init: I don't know my hostname!");
} catch (IndexOutOfBoundsException ioobe) {
// Caught something weird here a couple of times when
// running unconnected.
Debug.output("Environment.init: network may not be available");
}
// the UniqueID is generated from other runtime values. This
// should
// be unique for this Java VM. Note that for security reasons,
// you
// might not want to ship around this value on a network
// because it
// details some interesting tidbits about the running
// application.
p.put(UniqueID, "_" + Environment.get("user.name") + "_"
+ Environment.get(Version) + "_" + Environment.get("os.arch")
+ "_" + Environment.get("os.name") + "_"
+ ((addr != null) ? addr.getHostName() : "nohost") + "_"
+ timestamp() + "_");
// determine window system (for HACKing around
// Java-under-XWindows
// polygon wraparound bug.
String osname = Environment.get("os.name");
if (osname == null) {
isXWindows = false;
doingXWindowsWorkaround = false;
Debug.message("env", "Environment: is applet, Web Start.");
return;
}
if (osname.equalsIgnoreCase("solaris")
|| osname.equalsIgnoreCase("SunOS")) {
isXWindows = true;
doingXWindowsWorkaround = true;
Debug.message("env", "Environment: is X Windows!");
} else if (osname.equalsIgnoreCase("linux")) {
isXWindows = true;
doingXWindowsWorkaround = true;
Debug.message("env", "Environment: is X Windows!");
} else if (osname.startsWith("Windows")) {
isXWindows = false;
doingXWindowsWorkaround = false;
isXWindows = true;
doingXWindowsWorkaround = true;
Debug.message("env", "Environment: is MS Windows!");
} else if (osname.equalsIgnoreCase("Mac OS")) {
isXWindows = false;
doingXWindowsWorkaround = false;
Debug.message("env", "Environment: is Mac OS!");
} else if (osname.equalsIgnoreCase("Mac OS X")) {
isXWindows = true;
doingXWindowsWorkaround = true;
// isXWindows = false;
// doingXWindowsWorkaround = false;
com.bbn.openmap.omGraphics.DrawingAttributes.alwaysSetTextToBlack = true;
Debug.message("env", "Environment: Excellent! Mac OS X!");
} else {
System.err.println("Environment.initRuntimeProperties(): "
+ "running on unknown/untested OS: " + osname);
}
// should have initialized user properties already
if (Environment.get(OpenMapPrefix + ".noXWindowsWorkaround") != null) {
Debug.message("env", "Environment.initRuntimeProperties(): "
+ "not working around XWindows clipping bug.");
doingXWindowsWorkaround = false;
}
}
/**
* Indicates whether the current process is an applet.
*
* @return <code>true</code> if process is an applet;
* <code>false</code> otherwise.
*/
public static boolean isApplet() {
return (applet != null);
}
protected static void setApplet(Applet applet) {
Environment.applet = applet;
if (applet instanceof JApplet) {
Environment.useInternalFrames(((JApplet) applet).getRootPane());
}
}
/**
* Indicates whether the current process is an application.
*
* @return <code>true</code> if process is an application;
* <code>false</code> otherwise.
*/
public static boolean isApplication() {
return (applet == null);
}
/**
* Searches for the named property in the environment. If the key
* is not found, null is returned. All three property lists,
* runtime, user, and system are searched in that order.
*
* @param key the property key
* @return the value of the property with the specified key or
* <code>null</code> if there is no property with that
* key.
*/
public static String get(String key) {
return Environment.get(key, null);
}
/**
* Searches for the named property in the environment. If the key
* is not found, the default value is returned. All three property
* lists, runtime, user, and system are searched in that order.
*
* @param key the property key
* @param defaultValue a default value
* @return the value of the property with the specified key or
* <code>defaultValue</code> if there is no property
* with that key.
*/
public static String get(String key, String defaultValue) {
if (env == null) {
if (Debug.debugging("env")) {
System.err.println("Environment.get(" + key + ", "
+ defaultValue + ") called with null environment");
}
return defaultValue;
} else {
return env.getProperty(key, defaultValue);
}
}
/**
* Puts a property into the environment.
*
* @param key the property key.
* @param value the value to the key.
* @return the value of the property set, or null if the
* environment isn't ready for it.
*/
public static String set(String key, String value) {
if (env == null) {
if (Debug.debugging("env")) {
System.err.println("Can't Environment.put(" + key + ", "
+ value + ") - no environment yet.");
}
return null;
} else {
return (String) env.put(key, value);
}
}
/**
* Gets a boolean value out of the Environment.
*
* @param key the property key
* @return the boolean value of the property or false if there is
* no property with that key
*
*/
public static boolean getBoolean(String key) {
return getBoolean(key, false);
}
/**
* Gets a boolean value out of the Environment.
*
* @param key the property key
* @param defaultValue a default value
* @return the boolean value of the property or defaultValue if
* there is no property with that key
*
*/
public static boolean getBoolean(String key, boolean defaultValue) {
String str = Environment.get(key, null);
if (str == null) {
return defaultValue;
}
return (Boolean.valueOf(str)).booleanValue();
}
/**
* Gets an integer value out of the Environment.
*
* @param key the property key
* @return the integer value of the property or defaultValue if
* there is no property with that key
*
*/
public static int getInteger(String key) {
return getInteger(key, Integer.MIN_VALUE, 10);
}
/**
* Gets an integer value out of the Environment.
*
* @param key the property key
* @param defaultValue a default value
* @return the integer value of the property or defaultValue if
* there is no property with that key
*
*/
public static int getInteger(String key, int defaultValue) {
return getInteger(key, defaultValue, 10);
}
/**
* Gets an integer value out of the Environment.
*
* @param key the property key
* @param defaultValue a default value
* @param radix base value
* @return the integer value of the property or defaultValue if
* there is no property with that key
*
*/
public static int getInteger(String key, int defaultValue, int radix) {
String str = Environment.get(key, null);
if (str == null) {
return defaultValue;
}
try {
return Integer.parseInt(str, radix);
} catch (NumberFormatException e) {
return defaultValue;
}
}
/**
* Gets a float value out of the Environment.
*
* @param key the property key
* @return the float value of the property or defaultValue if
* there is no property with that key
*
*/
public static float getFloat(String key) {
return getFloat(key, Float.NaN);
}
/**
* Gets a float value out of the Environment.
*
* @param key the property key
* @param defaultValue a default value
* @return the float value of the property or defaultValue if
* there is no property with that key
*
*/
public static float getFloat(String key, float defaultValue) {
String str = Environment.get(key, null);
if (str == null) {
return defaultValue;
}
try {
return Float.valueOf(str).floatValue();
} catch (NumberFormatException e) {
return defaultValue;
}
}
/**
* Gets a double value out of the Environment.
*
* @param key the property key
* @return the double value of the property or defaultValue if
* there is no property with that key
*
*/
public static double getDouble(String key) {
return getDouble(key, Double.NaN);
}
/**
* Gets a double value out of the Environment.
*
* @param key the property key
* @param defaultValue a default value
* @return the double value of the property or defaultValue if
* there is no property with that key
*
*/
public static double getDouble(String key, double defaultValue) {
String str = Environment.get(key, null);
if (str == null) {
return defaultValue;
}
try {
return Double.valueOf(str).doubleValue();
} catch (NumberFormatException e) {
return defaultValue;
}
}
/**
* Gets the applet associated with this process.
*
* @return the applet, or null if process is an application
*/
public static Applet getApplet() {
return applet;
}
/**
* Adds a key/value pair to the Environment's system properties
* list.
*
* @param key the key, used later for retrieval
* @param value the associate value
* @see Environment#get
*/
public static void addSystemProperty(String key, String value) {
env.put(key, value);
}
/**
* Adds a key/value pair to the Environment's runtime properties
* list.
*
* @param key the key, used later for retrieval
* @param value the associate value
* @see Environment#get
*/
public static void addRuntimeProperty(String key, String value) {
env.runtimeProps.put(key, value);
}
/**
* Returns the toplevel Properties list of the Environment.
*
* @return Properties system properties
*
*/
public static Properties getProperties() {
return env;
}
/**
* Returns a stringified value of the current time.
* <p>
* Note: you probably don't want to call this in a tight loop.
*
* @return String timestamp YYYYMMDDhhmmss
*
*/
public static String timestamp() {
Calendar calendar = Calendar.getInstance();
return "" + calendar.get(Calendar.YEAR) + calendar.get(Calendar.MONTH)
+ calendar.get(Calendar.DAY_OF_MONTH)
+ calendar.get(Calendar.HOUR) + calendar.get(Calendar.MINUTE)
+ calendar.get(Calendar.SECOND);
}
/**
* Check if this is an XWindows-based VM.
* <p>
* Note: this only returns a valid result if the Environment has
* been initialized.
* <p>
*
* @return boolean
*
*/
public final static boolean isXWindowSystem() {
return isXWindows;
}
/**
* Generate a unique string. This should be unique compared to
* other strings generated this way.
*
* @return String
* @see Environment#timestamp
*/
public static String generateUniqueString() {
return Environment.get(UniqueID) + (counter++);
}
/**
* Returns elements of the CLASSPATH that are directories.
* CLASSPATH elements that are not directories are not returned.
*
* @return Vector of Strings
*/
public final static Vector getClasspathDirs() {
Vector v = new Vector();
try {
String classPath = System.getProperty("java.class.path");
StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator);
while (st.hasMoreTokens()) {
String path = st.nextToken();
if ((new File(path)).isDirectory()) {
v.addElement(path);
}
}
} catch (java.security.AccessControlException ace) {
// Running as an applet?!?
}
v.addAll(extraPaths);
return v;
}
/**
* Add a resource path to internal Vector. This path will get
* added to the classpath, if the Environment is asked for
* classpaths.
*/
public static void addPathToClasspaths(String path) {
extraPaths.addElement(path);
}
/**
* Checks the Environment to see if a BackgroundColor string, set
* as a hex ARGB string, has been set. If it hasn't or if it
* doesn't represent a valid color number, then null is returned,
* which should be interpreted as an excuse to use the default
* pretty blue embedded in the projection.
*/
public static Color getCustomBackgroundColor() {
String colorRep = get(BackgroundColor);
if (colorRep == null) {
return null;
} else {
try {
return PropUtils.parseColor(colorRep);
} catch (NumberFormatException nfe) {
return null;
}
}
}
/**
* A method to set the Environment to be able to tell other
* components to InternalFrames.
*
* @param rootPane to use for the internal frames - the method
* gets the LayeredPane from the rootPane.
*/
public static void useInternalFrames(JRootPane rootPane) {
if (rootPane != null) {
useInternalFrames(rootPane.getLayeredPane());
} else {
useInternalFrames((JLayeredPane) null);
}
}
/**
* A method to set the Environment to be able to tell other
* components to InternalFrames.
*
* @param layeredPane to use for the internal frames.
*/
public static void useInternalFrames(JLayeredPane layeredPane) {
if (layeredPane != null) {
env.desktop = layeredPane;
env.desktop.setOpaque(true);
set(UseInternalFrames, "true");
} else {
env.desktop = null;
set(UseInternalFrames, "false");
}
}
/**
* Get the JLayeredPane to use for Internal Frames. May be null if
* the Environment hasn't be set with the root pane.
*/
public static JLayeredPane getInternalFrameDesktop() {
return env.desktop;
}
private static I18n i18n = new BasicI18n();
/**
* Get the Internationalization instance.
*/
public static I18n getI18n() {
return i18n;
}
}