blob: 47bded01aa2deb080b68b5f6a9e9782329720057 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.common.ui.internal.utils;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import org.eclipse.jst.jsf.common.ui.JSFUICommonPlugin;
/**
* The main purpose of this class is to give better access methods for property
* and resource bundle access.
*
* @author mengbo
*/
public final class PropertyUtils {
private static final String ENCODED_CHAR_PERCENT = "%25"; //$NON-NLS-1$
private static final String ENCODED_CHAR_CARRIAGE_RETURN = "%0d"; //$NON-NLS-1$
private static final String ENCODED_CHAR_TAB = "%09"; //$NON-NLS-1$
private static final String ENCODED_CHAR_NEWLINE = "%0a"; //$NON-NLS-1$
private static final String ENCODED_CHAR_SPACE = "%20"; //$NON-NLS-1$
private static final String ENCODED_CHAR_COLON = "%3a"; //$NON-NLS-1$
private static final String ENCODED_CHAR_EQUALS = "%3d"; //$NON-NLS-1$
// WARNING: There can be NO static logging line here since the logger uses
// this class to figure out the preferences
// for the logging system. "Logging" an error here would be useless since
// you might be setting up the logging system
// via a call to PropertyUtils.getServerProperty() instead it uses
// "System.err.println".
// This is the name for the properties file.
// The prop-name will be prepended to this string....
private static final String NAME_PROPERTIES = ".props"; //$NON-NLS-1$
private static final String STR_BOUNDS_END = ".bounds"; // assumes the //$NON-NLS-1$
// window name or
// name list is
// prepended
// //////////////////////////////////////////////////////////////////////////
// Property get methods.
// //////////////////////////////////////////////////////////////////////////
/**
* @param props
* @param key
* @param theDefault
* @return the property
*/
public static String getProperty(Properties props, String key,
String theDefault) {
try {
String value = props.getProperty(key, theDefault);
if ((value != null) && (value.length() == 0)) {
value = null;
}
// check again for null, since some versions of the jdk ignore the
// default
// if an empty property exists.
if (value == null) {
value = theDefault;
}
return value;
} catch (Exception ee) {
return theDefault;
}
}
/**
* @param props
* @param key
* @return the value for key in props, may return null
*/
public static String getProperty(Properties props, String key) {
try {
String value = props.getProperty(key);
if ((value != null) && (value.length() == 0)) {
value = null;
}
return value;
} catch (Exception ee) {
return null;
}
}
/**
* @param props
* @param key
* @param defaultValue
* @param minimumValue
* @return the integer property value for key, or defaultValue
* if none. Enforces minimumValue in all cases
*/
public static int getPropertyValue(Properties props, String key,
int defaultValue, int minimumValue) {
int theValue = getPropertyValue(props, key, defaultValue);
if (theValue < minimumValue) {
theValue = minimumValue;
}
return theValue;
}
/**
* @param props
* @param key
* @param defaultValue
* @return the integer value for key in props or defaultValue if none
*/
public static int getPropertyValue(Properties props, String key,
int defaultValue) {
String stringValue = getProperty(props, key);
if (stringValue != null) {
try {
return Integer.parseInt(stringValue);
} catch (NumberFormatException ee)// NOPMD
{
// the property value maybe an invalid value, the editor should
// show these to user.
}
}
return defaultValue;
}
/**
* @param props
* @param key
* @param defaultValue
* @return the long value for key props or defaultValue if none
*/
public static long getPropertyLongValue(Properties props, String key,
long defaultValue) {
String stringValue = getProperty(props, key);
if (stringValue != null) {
try {
return Long.parseLong(stringValue);
} catch (NumberFormatException ee)// NOPMD
{
// the property value maybe an invalid value, the editor should
// show these to user.
}
}
return defaultValue;
}
/**
* @param props
* @param key
* @param bDefault
* @return true if props has a value for key
*/
public static boolean isProperty(Properties props, String key,
boolean bDefault) {
return getProperty(props, key, "" + bDefault).equals("" + true); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* @param props
* @param key
* @return the string values in props for key tokenized from
* a comma-separated string
*/
public static String[] getPropertyStrings(Properties props, String key) {
String tokenString = getProperty(props, key);
if (tokenString == null) {
return new String[0];
}
StringTokenizer tokenizer = new StringTokenizer(tokenString, ","); //$NON-NLS-1$
String[] pNames = new String[tokenizer.countTokens()];
for (int ii = 0; ii < pNames.length; ii++) {
pNames[ii] = ((String) tokenizer.nextElement()).trim();
}
return pNames;
}
// //////////////////////////////////////////////////////////////////////////
// Resource bundle get methods.
// //////////////////////////////////////////////////////////////////////////
/**
* @param bundle
* @param key
* @param theDefault
* @return the string value from bundle for key or default if none
*/
public static String getResourceProperty(ResourceBundle bundle, String key,
String theDefault) {
try {
String value = bundle.getString(key);
if ((value == null) || (value.length() == 0)) {
value = theDefault;
}
return value;
}
catch(NullPointerException npe)
{
return theDefault;
}
catch (MissingResourceException mre)
{
return theDefault;
}
catch (ClassCastException cce)
{
return theDefault;
}
}
/**
* @param bundle
* @param key
* @return the value for key in bundle or null if none
*/
public static String getResourceProperty(ResourceBundle bundle, String key) {
try
{
String value = bundle.getString(key);
if ((value != null) && (value.length() == 0))
{
value = null;
}
return value;
}
catch(NullPointerException npe)
{
return null;
}
catch (MissingResourceException mre)
{
return null;
}
catch (ClassCastException cce)
{
return null;
}
}
/**
* @param bundle
* @param key
* @param defaultValue
* @param minimumValue
* @return the integer value for key in bundle or defaultValue if none
* Enforces minimum value in all cases
*/
public static int getResourcePropertyValue(ResourceBundle bundle,
String key, int defaultValue, int minimumValue) {
int theValue = getResourcePropertyValue(bundle, key, defaultValue);
if (theValue < minimumValue) {
theValue = minimumValue;
}
return theValue;
}
/**
* @param bundle
* @param key
* @param defaultValue
* @return the integer value for key in bundle or defaultValue if none
*/
public static int getResourcePropertyValue(ResourceBundle bundle,
String key, int defaultValue) {
String stringValue = getResourceProperty(bundle, key);
if (stringValue != null) {
try {
return Integer.parseInt(stringValue);
} catch (NumberFormatException ee)// NOPMD
{
// the property value maybe an invalid value, the editor should
// show these to user.
}
}
return defaultValue;
}
/**
* @param bundle
* @param key
* @param defaultValue
* @return the long value for key in bundle or default value if none
*/
public static long getResourcePropertyLongValue(ResourceBundle bundle,
String key, long defaultValue) {
String stringValue = getResourceProperty(bundle, key);
if (stringValue != null) {
try {
return Long.parseLong(stringValue);
} catch (NumberFormatException ee)// NOPMD
{
// the property value maybe an invalid value, the editor should
// show these to user.
}
}
return defaultValue;
}
/**
* @param bundle
* @param key
* @param bDefault
* @return true if bundle has a value for key
*/
public static boolean isResourceProperty(ResourceBundle bundle, String key,
boolean bDefault) {
return getResourceProperty(bundle, key, "" + bDefault) //$NON-NLS-1$
.equals("" + true); //$NON-NLS-1$
}
// ///////////////////////////////////////////////////////////////////////
// Property misc routines
// ///////////////////////////////////////////////////////////////////////
/**
* @param theName
* @return the encoded name
*/
public static String encodeName(String theName) {
int theSize = theName.length();
StringBuffer encoded = new StringBuffer(theSize);
char ch;
for (int ii = 0; ii < theSize; ii++) {
ch = theName.charAt(ii);
switch (ch) {
// these are the set of illegal characters in a Property name
case '=': // %3d
encoded.append(ENCODED_CHAR_EQUALS);
break;
case ':': // %3a
encoded.append(ENCODED_CHAR_COLON);
break;
case ' ': // %20
encoded.append(ENCODED_CHAR_SPACE);
break;
case '\n': // %0a
encoded.append(ENCODED_CHAR_NEWLINE);
break;
case '\t': // %09
encoded.append(ENCODED_CHAR_TAB);
break;
case '\r': // %0d
encoded.append(ENCODED_CHAR_CARRIAGE_RETURN);
break;
case '%': // %25
// added because its our encoding flag
encoded.append(ENCODED_CHAR_PERCENT);
break;
default:
encoded.append(ch);
break;
}
}
return encoded.toString();
}
/**
* @param theName
* @return the decoded name
*/
public static String decodeName(String theName) {
int theSize = theName.length();
int kk;
StringBuffer decoded = new StringBuffer(theSize);
char ch;
for (int ii = 0; ii < theSize; ii++) {
ch = theName.charAt(ii);
if (ch == '%') {
ch = theName.charAt(++ii);
kk = Character.digit(ch, 16);
kk *= 16;
ch = theName.charAt(++ii);
kk += Character.digit(ch, 16);
decoded.append((char) kk);
} else {
decoded.append(ch);
}
}
return decoded.toString();
}
/**
* @param propName
* @return the properties
* @throws IOException
* @throws FileNotFoundException
*/
public static Properties openProperties(String propName)
throws IOException, FileNotFoundException {
return openProperties(propName, null, true);
}
/**
* @param propName
* @param propDefaults
* @return the properties
* @throws IOException
* @throws FileNotFoundException
*/
public static Properties openProperties(String propName,
Properties propDefaults) throws IOException, FileNotFoundException {
return openProperties(propName, propDefaults, true);
}
/**
* @param propName
* @param propDefaults
* @param bCreatePropertiesPathname
* @return the properties
* @throws IOException
* @throws FileNotFoundException
*/
public static Properties openProperties(String propName,
Properties propDefaults, boolean bCreatePropertiesPathname)
throws IOException, FileNotFoundException {
Properties theProperties = new Properties(propDefaults);
try {
String propertiesFilename = bCreatePropertiesPathname ? getPropertiesPathname(propName)
: propName;
InputStream theStream = new FileInputStream(propertiesFilename);
theProperties.load(theStream);
theStream.close();
} catch (FileNotFoundException ee) {
if (propDefaults == null) {
throw ee;
}
} catch (IOException ee) {
if (propDefaults == null) {
throw ee;
}
}
return theProperties;
}
/**
* Combines two properties objects, with the second one as the default
* properties
*
* @param localProperties
* @param defaultProperties
* @return the combined properties
* @throws IOException
*/
public static Properties combineProperties(Properties localProperties,
Properties defaultProperties) throws IOException {
Properties theNewProperties = new Properties();
ByteArrayOutputStream os = new ByteArrayOutputStream();
defaultProperties.store(os, ""); //$NON-NLS-1$
localProperties.store(os, ""); //$NON-NLS-1$
byte[] theData = os.toByteArray();
ByteArrayInputStream is = new ByteArrayInputStream(theData);
theNewProperties.load(is);
return theNewProperties;
}
/**
* @param theFilename
* @return the encoded file name
*/
public static String encodeFilename(String theFilename) {
// make theFilename legal on the local system....
String theSeparator = System.getProperty("file.separator"); //$NON-NLS-1$
// replace all occurrances of the file separator with a ' '
for (int ii = 0; ii < theSeparator.length(); ii++) {
char theChar = theSeparator.charAt(ii);
theFilename = theFilename.replace(theChar, ' ');
}
return theFilename;
}
/**
* @param baseName
* @return the properties path
*/
public static String getPropertiesPathname(String baseName) {
if (baseName.endsWith(NAME_PROPERTIES)) {
return System.getProperty("user.dir") //$NON-NLS-1$
+ System.getProperty("file.separator") //$NON-NLS-1$
+ encodeFilename(baseName);
}
return System.getProperty("user.dir") //$NON-NLS-1$
+ System.getProperty("file.separator") //$NON-NLS-1$
+ encodeFilename(baseName) + NAME_PROPERTIES;
}
// /////////////////////////////////////////////////////////////////////////
// These are generic routines that are used to get/set/save window bounds
private static final int INSET = 40;
/**
* Set the initial bounds (size & location) of a component. This will get
* the location from the preferences file based on the values of the "names"
* parameter. These values will be encoded to make a legal properties name,
* joined togther with ".", and the value STR_BOUNDS_END will be appended.
* The resulting name will be used to obtain the intial bounds value from
* the properties file, which will be decoded and the specified component
* will then be set to that value.
* @param props
* @param theComponent
* @param names
* @param defaultValue
*/
public static void setComponentBounds(Properties props,
Component theComponent, String names[], String defaultValue) {
setComponentBounds(props, theComponent, names, defaultValue, false);
}
/**
* @param props
* @param theComponent
* @param names
* @param defaultValue
* @param bEnsureDesktopVisibility
*/
public static void setComponentBounds(Properties props,
Component theComponent, String names[], String defaultValue,
boolean bEnsureDesktopVisibility) {
String tmpString = getComponentPropertyName(names, STR_BOUNDS_END);
setComponentBounds(props, theComponent, tmpString, defaultValue,
bEnsureDesktopVisibility);
}
/**
* @param props
* @param theComponent
* @param thePropertyName
* @param defaultValue
*/
public static void setComponentBounds(Properties props,
Component theComponent, String thePropertyName, String defaultValue) {
setComponentBounds(props, theComponent, thePropertyName, defaultValue,
false);
}
/**
* @param props
* @param theComponent
* @param thePropertyName
* @param defaultValue
* @param bEnsureDesktopVisibility
*/
public static void setComponentBounds(Properties props,
Component theComponent, String thePropertyName,
String defaultValue, boolean bEnsureDesktopVisibility) {
String tmpString = props.getProperty(thePropertyName, defaultValue);
Rectangle theValue = decodeBounds(tmpString);
theComponent.setBounds(theValue);
if (bEnsureDesktopVisibility) {
// make sure that this component is visible on the desktop...
// verify that this window is visible...
Point theLoc = theComponent.getLocation();
// get width/height of desktop....
Dimension portSize = new Dimension(Toolkit.getDefaultToolkit()
.getScreenSize());
if (theLoc.x > portSize.width) // move it to top
theLoc.x = INSET;
if (theLoc.y > portSize.height) // move it to left
theLoc.y = INSET;
theComponent.setLocation(theLoc);
}
}
/**
* @param props
* @param theComponent
* @param names
*/
public static void saveComponentBounds(Properties props,
Component theComponent, String names[]) {
String tmpString = getComponentPropertyName(names, STR_BOUNDS_END);
saveComponentBounds(props, theComponent, tmpString);
}
/**
* @param props
* @param theComponent
* @param thePropertyName
*/
public static void saveComponentBounds(Properties props,
Component theComponent, String thePropertyName) {
Rectangle theBounds = theComponent.getBounds();
String theValue = encodeBounds(theBounds);
props.put(thePropertyName, theValue);
}
/**
* @param names
* @param subsystemName
* @return the component property name or ""
*/
public static String getComponentPropertyName(String names[],
String subsystemName) {
String tmpString = ""; //$NON-NLS-1$
for (int ii = 0; ii < names.length; ii++) {
tmpString = tmpString + (ii > 0 ? "." : "") //$NON-NLS-1$ //$NON-NLS-2$
+ PropertyUtils.encodeName(names[ii]);
}
if (subsystemName.startsWith(".") == false) //$NON-NLS-1$
tmpString += "."; //$NON-NLS-1$
tmpString = tmpString + subsystemName;
return tmpString;
}
/**
* Decode the comma separated values stored in sBounds. This method is
* normally called to decode the location/size of a component which has been
* saved into a Properties object. See encodeBounds(); Order of items in the
* string is (x, y, w, h)
* @param sBounds
* @return the rectangle
*/
public static Rectangle decodeBounds(String sBounds) {
int index;
int ii;
int theValue[] = new int[4];
String tmpString;
String restString = sBounds;
for (ii = 0; ii < 4; ii++) {
theValue[ii] = 0;
}
try {
for (ii = 0; ii < 4; ii++) {
index = restString.indexOf(","); //$NON-NLS-1$
if (index > 0) {
tmpString = restString.substring(0, index);
restString = restString.substring(index + 1);
} else {
tmpString = restString; // should only happen on the last
// one....
restString = null; // will cause an exception if not last
// one...
}
theValue[ii] = Integer.valueOf(tmpString).intValue();
}
} catch (Exception ee)// NOPMD
{
// the property value maybe an invalid value, the editor should show
// these to user.
}
return new Rectangle(theValue[0], theValue[1], theValue[2], theValue[3]);
}
/**
* * Encode the bounds of a component into a comma separated list * that is
* appropriate for storing in a Properties object. * See decodeBounds();
* @param rBounds
* @return the encoded bounds
*/
public static String encodeBounds(Rectangle rBounds) {
return "" + rBounds.x + "," + rBounds.y + "," + rBounds.width + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ rBounds.height;
}
/**
* Methods for creating Properties objects from strings.
*
* Then "Encoded" versions are used on values that are stored into a
* properties file (think of them as sub-properties). They do the encoding
* necessary to turn a properties object into a string that has legal
* "value" syntax (they actually do more than they need to, but its all
* non-destructive).
* @param thePropertyString
* @return the properties from the string
* @throws IOException
*/
public static Properties getPropertiesFromString(String thePropertyString)
throws IOException {
if (thePropertyString == null)
return null;
ByteArrayInputStream in = new ByteArrayInputStream(thePropertyString
.getBytes());
Properties props = new Properties();
props.load(in); // throws IOException
in = null;
return props;
}
/**
* @param theEncodedPropertyString
* @return the properties
* @throws IOException
*/
public static Properties getPropertiesFromEncodedString(
String theEncodedPropertyString) throws IOException {
if (theEncodedPropertyString == null)
return null;
return (getPropertiesFromString(decodeName(theEncodedPropertyString)));
}
/**
* @param theEncodedPropertyString
* @return the properties
*/
public static Properties encodedStringToProperties(
String theEncodedPropertyString) {
try {
return getPropertiesFromEncodedString(theEncodedPropertyString);
} catch (IOException ee) {
return null;
}
}
/**
* @param props
* @param comment
* @return the string
* @throws IOException
*/
public static String savePropertiesToString(Properties props, String comment)
throws IOException {
if (props == null)
return null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
props.store(out, comment);
String tmpString = out.toString();
out = null;
return tmpString;
}
/**
* @param props
* @param comment
* @return the encoded string
* @throws IOException
*/
public static String savePropertiesToEncodedString(Properties props,
String comment) throws IOException {
if (props == null)
return null;
return encodeName(savePropertiesToString(props, comment));
}
/**
* @param props
* @return the encoded string
*/
public static String propertiesToEncodedString(Properties props) {
try {
return savePropertiesToEncodedString(props, ""); //$NON-NLS-1$
} catch (IOException ee)// NOPMD
{
JSFUICommonPlugin.getLogger(PropertyUtils.class).error("saving properties", ee); //$NON-NLS-1$
}
return null;
}
private PropertyUtils()
{
// no instantiation
}
}