// ********************************************************************** // // // // BBN Technologies // 10 Moulton Street // Cambridge, MA 02138 // (617) 873-8000 // // Copyright (C) BBNT Solutions LLC. All rights reserved. // // // ********************************************************************** // // $Source: // /cvs/distapps/openmap/src/openmap/com/bbn/openmap/util/PropUtils.java,v // $ // $RCSfile: PropUtils.java,v $ // $Revision: 1.6.2.6 $ // $Date: 2006/01/18 17:51:03 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.util; /* Java Core */ import java.awt.Color; import java.awt.Paint; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.Enumeration; import java.util.NoSuchElementException; import java.util.Properties; import java.util.StringTokenizer; import java.util.Vector; import javax.swing.JFileChooser; import com.bbn.openmap.Environment; import com.bbn.openmap.I18n; import com.bbn.openmap.PropertyConsumer; public class PropUtils { /** * Parse a list of marker names from a space separated list within a String. *

* * @param markerList a string containing a space delimited list of marker * names. * @return Vector of marker names. */ public static Vector parseSpacedMarkers(String markerList) { return parseMarkers(markerList, " "); } /** * Parse a list of marker names from a space separated list within a String. *

* * @param markerList a string containing a space delimited list of marker * names. * @param delim the list of tokens to look for which separate the list * elements. * @return Vector of marker names. */ public static Vector parseMarkers(String markerList, String delim) { Vector vector = null; if (markerList == null) { Debug.message("propertiesdetail", "PropUtils: marker list null!"); return new Vector(0); } if (Debug.debugging("propertiesdetail")) { Debug.output("PropertyHandler: parsing marker list |" + markerList + "|"); } // First, get rid of the quotation marks; markerList = markerList.replace('\"', '\0'); // Next, tokenize the space delimited string StringTokenizer tokens = new StringTokenizer(markerList, delim); vector = new Vector(tokens.countTokens()); while (tokens.hasMoreTokens()) { String name = tokens.nextToken().trim(); vector.addElement(name); } return vector; } /** Borrowed from Properites.java */ public static final String keyValueSeparators = "=: \t\r\n\f"; /** Borrowed from Properites.java */ public static final String strictKeyValueSeparators = "=:"; /** Borrowed from Properites.java */ public static final String whiteSpaceChars = " \t\r\n\f"; /** As defined in the OGC Web Mapping Testbed. */ public static final String propertySeparators = "&"; /** * Take a property list, defined in a single string, and return a Properties * object. The properties, as key-value pairs, are separated by another type * of symbol. In this method, the key-values are assumed to be separated * from other key-value pairs by PropUtils.propertySeparators String * characters, and each key is separated from its value by any character in * the PropUtils.keyValueSeparators list. * * @param list the properties list string. * @return Properties object containing keys and values. * @throws PropertyStringFormatException if a key doesn't have a value. */ public static Properties parsePropertyList(String list) throws PropertyStringFormatException { return parsePropertyList(list, propertySeparators, keyValueSeparators); } /** * Take a property list, defined in a single string, and return a Properties * object. The properties, as key-value pairs, are separated by another type * of symbol. * * @param list the properties list string. * @return Properties object containing keys and values. * @param propertySeparators the key-values are assumed to be separated from * other key-value pairs by any character in this String. * @param keyValueSeparators each key is separated from its value by any * character in this String. * @throws PropertyStringFormatException if a key doesn't have a value. */ public static Properties parsePropertyList(String list, String propertySeparators, String keyValueSeparators) throws PropertyStringFormatException { Properties props = new Properties(); Vector keyValuePairs = parseMarkers(list, propertySeparators); for (int i = 0; i < keyValuePairs.size(); i++) { // Next, tokenize the space delimited string StringTokenizer tokens = new StringTokenizer((String) keyValuePairs.elementAt(i), keyValueSeparators); try { String key = tokens.nextToken().trim(); String value = tokens.nextToken().trim(); props.put(key, value); } catch (NoSuchElementException nsee) { throw new PropertyStringFormatException(list); } } return props; } /** * Copy the contents from one properties object to another. * * @param from the source Properties object. * @param to the destination Properties object. */ public static void copyProperties(Properties from, Properties to) { Enumeration keys = from.keys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); to.put(key, from.getProperty(key)); } } /** * Load the named file from the named directory into the given * Properties instance. If the file is not found a warning is * issued. If an IOException occurs, a fatal error is printed. * * @param props the instance to receive the loaded properties * @param dir the directory where the properties file resides * @param file the name of the file * @return true if the properties file exists and was loaded. */ public static boolean loadProperties(Properties props, String dir, String file) { File propsFile = new File(dir, file); try { InputStream propsStream = new FileInputStream(propsFile); props.load(propsStream); if (Debug.debugging("properties")) { Debug.output("PropUtils: Found " + propsFile); } return true; } catch (java.io.FileNotFoundException e) { if (Debug.debugging("properties")) { Debug.output("PropUtils: File not found - \"" + propsFile + "\""); } } catch (java.io.IOException e) { Debug.error("PropUtils: Caught IO Exception reading \"" + propsFile + "\""); e.printStackTrace(); } catch (java.security.AccessControlException ace) { } return false; } /** * Loads properties from a java resource. This will load the named resource * identifier into the given properties instance. * * @param properties the Properties instance to receive the properties. * @param propsIn an InputStream to read properties from * @return true if the properties file exists and was loaded. */ public static boolean loadProperties(Properties properties, InputStream propsIn) { try { properties.load(propsIn); return true; } catch (java.io.IOException e) { if (Debug.debugging("properties")) { Debug.error("PropUtils: Caught IOException loading properties from InputStream."); } return false; } } /** * A function that brings up a file chooser window in order to have the user * look for a valid Java properties file. * * @return properties object with selected file contents. */ public static Properties promptUserForProperties() { JFileChooser fileChooser = new JFileChooser(); int retvalue = fileChooser.showOpenDialog(null); Properties props = new Properties(); if (retvalue != JFileChooser.APPROVE_OPTION) { return props; } try { FileInputStream inputStream = new FileInputStream(fileChooser.getSelectedFile()); props.load(inputStream); return props; } catch (Exception ioe) { System.err.println("PropUtils.promptUserForProperties: Exception reading properties file."); System.err.println(ioe.getMessage()); ioe.printStackTrace(); return props; } } /** * It seems like every PropertyConsumer wrestles with having a prefix or * not. This method lets you just get the prefix with a period on the end * (for scoping purposes), or just returns an empty String. Either way, you * get a String you can slap on the beginning of your defined propery names * to get a valid property based on what the prefix is. */ public static String getScopedPropertyPrefix(PropertyConsumer pc) { return getScopedPropertyPrefix(pc.getPropertyPrefix()); } /** * Given the string, check if it's null or empty. If it is, return an empty * string. If it isn't, check to see if it ends with a period, and do * nothing if it does. If it doesn't end in a period, add one, and then * return that. The returned string should be good for prepending to other * properties. */ public static String getScopedPropertyPrefix(String pre) { if ((pre == null) || (pre.length() == 0)) { return ""; } else if (pre.endsWith(".")) { return pre; } else { return pre + "."; } } /** * It kills Properties to have null values set. You can wrap a property * value in this in PropertyConsumer.getProperties() to not worry about it. * Returns "" if prop == null, else returns what was passed in. */ public static String unnull(String prop) { if (prop == null) { return ""; } return prop; } /** * Takes a string of `;' separated paths and returns an array of parsed * strings. NOTE: this method currently doesn't support appropriate quoting * of the `;' character, although it probably should... * * @param p properties * @param propName the name of the property * @return Array of strings representing paths. */ public static String[] initPathsFromProperties(Properties p, String propName) { return initPathsFromProperties(p, propName, null); } /** * Takes a string of `;' separated paths and returns an array of parsed * strings. NOTE: this method currently doesn't support appropriate quoting * of the `;' character, although it probably should... * * @param p properties * @param propName the name of the property * @param defaultPaths the value of the paths to set if the property doesn't * exist, or if is doesn't contain anything. * @return Array of strings representing paths. */ public static String[] initPathsFromProperties(Properties p, String propName, String[] defaultPaths) { String[] ret = stringArrayFromProperties(p, propName, ";"); if (ret == null) { ret = defaultPaths; } return ret; } /** * Gets an integer out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return integer value associated with the property. */ public static int intFromProperties(Properties p, String propName, int defaultValue) { int ret = defaultValue; String intString = p.getProperty(propName); if (intString != null) { try { ret = Integer.parseInt(intString.trim()); } catch (NumberFormatException e) { ret = defaultValue; } } return ret; } /** * Gets an float out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return float value associated with the property. */ public static float floatFromProperties(Properties p, String propName, float defaultValue) { float ret = defaultValue; String floatString = p.getProperty(propName); if (floatString != null) { try { ret = Float.parseFloat(floatString.trim()); } catch (NumberFormatException e) { ret = defaultValue; } } return ret; } /** * Gets an boolean out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return boolean value associated with the property. */ public static boolean booleanFromProperties(Properties p, String propName, boolean defaultValue) { boolean ret = defaultValue; String booleanString = p.getProperty(propName); if (booleanString != null) { ret = booleanString.trim().toLowerCase().equals("true"); } return ret; } /** * Creates an object out of a property name. If anything fails, return null. * * @param p properties * @param propName name of class to instantiate. * @return null on failure, otherwise, a default constructed instance of the * class named in the property. */ public static Object objectFromProperties(Properties p, String propName) { Object ret = null; String objectName = p.getProperty(propName); if (objectName != null) { ret = ComponentFactory.create(objectName); } return ret; } /** * Takes a string of representing token separated properties and returns an * array of parsed strings. NOTE: this method currently doesn't support * appropriate quoting of the token, although it probably should... * * @param p properties * @param propName the name of the property * @param tok the characters separating the strings. * @return Array of strings between the tokens. */ public static String[] stringArrayFromProperties(Properties p, String propName, String tok) { String[] ret = null; String raw = p.getProperty(propName); if (raw != null && raw.length() != 0) { try { StringTokenizer token = new StringTokenizer(raw, tok); int numPaths = token.countTokens(); ret = new String[numPaths]; for (int i = 0; i < numPaths; i++) { ret[i] = token.nextToken(); } return ret; } catch (java.util.NoSuchElementException e) { e.printStackTrace(); } } return ret; } /** * Gets a double out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return double value associated with the property. */ public static double doubleFromProperties(Properties p, String propName, double defaultValue) { double ret = defaultValue; String doubleString = p.getProperty(propName); if (doubleString != null) { try { ret = Double.parseDouble(doubleString.trim()); } catch (NumberFormatException e) { ret = defaultValue; } } return ret; } /** * Gets a long out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return long value associated with the property. */ public static long longFromProperties(Properties p, String propName, long defaultValue) { long ret = defaultValue; String longString = p.getProperty(propName); if (longString != null) { try { ret = Long.parseLong(longString.trim()); } catch (NumberFormatException e) { ret = defaultValue; } } return ret; } /** * Take a string from a properties file, representing the 24bit RGB or 32bit * ARGB hex values for a color, and convert it to a java.awt.Color. * * @param p properties * @param propName the name of the property * @param dfault color to use if the property value doesn't work * @return java.awt.Color * @exception NumberFormatException if the specified string cannot be * interpreted as a hexidecimal integer * @see ColorFactory#parseColorFromProperties(Properties, String, String, * boolean) */ public static Color parseColorFromProperties(Properties p, String propName, String dfault) throws NumberFormatException { return ColorFactory.parseColorFromProperties(p, propName, dfault, false); } /** * Take a string from a properties file, representing the 24bit RGB or 32bit * ARGB hex values for a color, and convert it to a java.awt.Color. * * @param p properties * @param propName the name of the property * @param dfault color to use if the property value doesn't work * @return java.awt.Color * @see ColorFactory#parseColorFromProperties(Properties, String, String, * boolean) */ public static Paint parseColorFromProperties(Properties p, String propName, Paint dfault) { return ColorFactory.parseColorFromProperties(p, propName, dfault); } /** * Convert a string representing a 24/32bit hex color value into a Color * value. NOTE: *

* * @param colorString the 24/32bit hex string value (ARGB) * @return java.awt.Color (24bit RGB on JDK 1.1, 24/32bit ARGB on JDK1.2) * @exception NumberFormatException if the specified string cannot be * interpreted as a hexidecimal integer * @see ColorFactory#parseColor(String, boolean) */ public static Color parseColor(String colorString) throws NumberFormatException { return ColorFactory.parseColor(colorString, false); } /** * Returns a string representing a color, properly buffered for zeros for * different alpha values. * * @param color * @return string for color with alpha values. */ public static String getProperty(Color color) { StringBuffer hexstring = new StringBuffer(Integer.toHexString(color.getRGB())); while (hexstring.length() < 8) { hexstring.insert(0, '0'); } return hexstring.toString(); } /** * Converts a properties object to an array of Strings. The resulting array * will consist of alternating key-value strings. * * @param props the properties object to convert. * @return an array of Strings representing key-value pairs. */ public static String[] getPropertiesAsStringArray(Properties props) { int size = props.size(); String[] ret = new String[size * 2]; // key and value int count = 0; Enumeration things = props.propertyNames(); while (things.hasMoreElements()) { ret[count] = (String) things.nextElement(); ret[count + 1] = (String) props.getProperty(ret[count]); count += 2; } return ret; } /** * Returns a URL that names either a resource, a local file, or an internet * URL. Resources are checked for in the general classpath. * * @param name name of the resource, file or URL. * @throws java.net.MalformedURLException * @return URL */ public static URL getResourceOrFileOrURL(String name) throws java.net.MalformedURLException { return getResourceOrFileOrURL(null, name); } /** * Returns a URL that names either a resource, a local file, or an internet * URL. * * @param askingClass the object asking for the URL. * @param name name of the resource, file or URL. * @throws java.net.MalformedURLException * @return URL */ public static URL getResourceOrFileOrURL(Object askingClass, String name) throws java.net.MalformedURLException { return getResourceOrFileOrURL(askingClass.getClass(), name); } /** * Returns a URL that names either a resource, a local file, or an internet * URL. * * @param askingClass the class asking for the URL. Can be null. * @param name name of the resource, file or URL. * @throws java.net.MalformedURLException * @return URL */ public static URL getResourceOrFileOrURL(Class askingClass, String name) throws java.net.MalformedURLException { boolean DEBUG = Debug.debugging("proputils"); if (name == null) { if (DEBUG) Debug.output("PropUtils.getROFOU(): null file name"); return null; } URL retval = null; if (DEBUG) Debug.output("PropUtils.getROFOU(): looking for " + name); if (askingClass != null) { // First see if we have a resource by that name if (DEBUG) Debug.output("PropUtils.getROFOU(): checking as resource"); retval = askingClass.getResource(name); } if (retval == null) { // Check the general classpath... if (DEBUG) Debug.output("PropUtils.getROFOU(): checking in general classpath"); retval = Thread.currentThread() .getContextClassLoader() .getResource(name); } if (retval == null && !Environment.isApplet()) { // Check the classpath plus the share directory, which may // be in the openmap.jar file or in the development // environment. if (DEBUG) Debug.output("PropUtils.getROFOU(): checking with ClassLoader"); retval = ClassLoader.getSystemResource("share/" + name); } if (retval == null && Environment.isApplet()) { if (DEBUG) Debug.output("PropUtils.getROFOU(): checking with URLClassLoader"); URL[] cba = new URL[1]; cba[0] = Environment.getApplet().getCodeBase(); URLClassLoader ucl = URLClassLoader.newInstance(cba); retval = ucl.getResource(name); } // If there was no resource by that name available if (retval == null) { if (DEBUG) Debug.output("PropUtils.getROFOU(): not found as resource"); try { java.io.File file = new java.io.File(name); if (file.exists()) { retval = file.toURL(); if (DEBUG) Debug.output("PropUtils.getROFOU(): found as file :)"); } else { // Otherwise treat it as a raw URL. if (DEBUG) Debug.output("PropUtils.getROFOU(): Not a file, checking as URL"); retval = new URL(name); java.io.InputStream is = retval.openStream(); is.close(); if (DEBUG) Debug.output("PropUtils.getROFOU(): OK as URL :)"); } } catch (java.io.IOException ioe) { retval = null; } catch (java.security.AccessControlException ace) { Debug.error("PropUtils: AccessControlException trying to access " + name); retval = null; } catch (Exception e) { Debug.error("PropUtils: caught exception " + e.getMessage()); retval = null; } } if (DEBUG) { if (retval != null) { Debug.output("Resource " + name + "=" + retval.toString()); } else { Debug.output("Resource " + name + " can't be found..."); } } return retval; } /** * Simple space saving implementation of common I18n Property Info setting. * * @param i18n i18n object to use to search for internationalized strings. * @param info the properties class being used to set information into. * @param classToSetFor class to use for i18n search. * @param propertyName property to set for. * @param label label to use for GUI (can be null if N/A). * @param tooltip tooltip to use for GUI (can be null if N/A). * @param editor editor class string to use for GUI (can be null if N/A). * @return Properties object passed in, or new one if null Properties passed * in. */ public static Properties setI18NPropertyInfo(I18n i18n, Properties info, Class classToSetFor, String propertyName, String label, String tooltip, String editor) { if (info == null) { info = new Properties(); } if (i18n != null) { if (tooltip != null) { String internString = i18n.get(classToSetFor, propertyName, I18n.TOOLTIP, tooltip); info.put(propertyName, internString); } if (label != null) { String internString = i18n.get(classToSetFor, propertyName, label); info.put(propertyName + PropertyConsumer.LabelEditorProperty, internString); } if (editor != null) { info.put(propertyName + PropertyConsumer.ScopedEditorProperty, editor); } } return info; } }