001: /*
002: * $Id: PropertiesUtils.java 10489 2008-01-23 17:53:38Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.util;
012:
013: import org.mule.config.i18n.CoreMessages;
014: import org.mule.config.i18n.Message;
015:
016: import java.io.IOException;
017: import java.io.InputStream;
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Map;
022: import java.util.Properties;
023:
024: import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
025:
026: /**
027: * <code>PropertiesHelper</code> is a utility class for manipulating and filtering
028: * property Maps.
029: */
030: // @ThreadSafe
031: public final class PropertiesUtils {
032: // @GuardedBy(itself)
033: private static final List maskedProperties = new CopyOnWriteArrayList();
034:
035: static {
036: // When printing property lists mask password fields
037: // Users can register their own fields to mask
038: registerMaskedPropertyName("password");
039: }
040:
041: /** Do not instanciate. */
042: protected PropertiesUtils() {
043: // no-op
044: }
045:
046: /**
047: * Register a property name for masking. This will prevent certain values from
048: * leaking e.g. into debugging output or logfiles.
049: *
050: * @param name the key of the property to be masked.
051: * @throws IllegalArgumentException is name is null or empty.
052: */
053: public static void registerMaskedPropertyName(String name) {
054: if (StringUtils.isNotEmpty(name)) {
055: maskedProperties.add(name);
056: } else {
057: throw new IllegalArgumentException(
058: "Cannot mask empty property name.");
059: }
060: }
061:
062: /**
063: * Returns the String representation of the property value or a masked String if
064: * the property key has been registered previously via
065: * {@link #registerMaskedPropertyName(String)}.
066: *
067: * @param property a key/value pair
068: * @return String of the property value or a "masked" String that hides the
069: * contents, or <code>null</code> if the property, its key or its value
070: * is <code>null</code>.
071: */
072: public static String maskedPropertyValue(Map.Entry property) {
073: if (property == null) {
074: return null;
075: }
076:
077: Object key = property.getKey();
078: Object value = property.getValue();
079:
080: if (key == null || value == null) {
081: return null;
082: }
083:
084: if (maskedProperties.contains(key)) {
085: return ("*****");
086: } else {
087: return value.toString();
088: }
089: }
090:
091: /**
092: * Read in the properties from a properties file. The file may be on the file
093: * system or the classpath.
094: *
095: * @param fileName - The name of the properties file
096: * @param callingClass - The Class which is calling this method. This is used to
097: * determine the classpath.
098: * @return a java.util.Properties object containing the properties.
099: */
100: public static synchronized Properties loadProperties(
101: String fileName, final Class callingClass)
102: throws IOException {
103: InputStream is = IOUtils.getResourceAsStream(fileName,
104: callingClass,
105: /* tryAsFile */true, /* tryAsUrl */false);
106: if (is == null) {
107: Message error = CoreMessages
108: .cannotLoadFromClasspath(fileName);
109: throw new IOException(error.toString());
110: }
111:
112: try {
113: Properties props = new Properties();
114: props.load(is);
115: return props;
116: } finally {
117: is.close();
118: }
119: }
120:
121: public static String removeXmlNamespacePrefix(String eleName) {
122: int i = eleName.indexOf(':');
123: return (i == -1 ? eleName : eleName.substring(i + 1, eleName
124: .length()));
125: }
126:
127: public static String removeNamespacePrefix(String eleName) {
128: int i = eleName.lastIndexOf('.');
129: return (i == -1 ? eleName : eleName.substring(i + 1, eleName
130: .length()));
131: }
132:
133: public static Map removeNamespaces(Map properties) {
134: HashMap props = new HashMap(properties.size());
135: Map.Entry entry;
136: for (Iterator iter = properties.entrySet().iterator(); iter
137: .hasNext();) {
138: entry = (Map.Entry) iter.next();
139: props.put(removeNamespacePrefix((String) entry.getKey()),
140: entry.getValue());
141:
142: }
143: return props;
144: }
145:
146: /**
147: * Will create a map of properties where the names have a prefix Allows the
148: * callee to supply the target map so a comparator can be set
149: *
150: * @param props the source set of properties
151: * @param prefix the prefix to filter on
152: * @param newProps return map containing the filtered list of properties or an
153: * empty map if no properties matched the prefix
154: */
155: public static void getPropertiesWithPrefix(Map props,
156: String prefix, Map newProps) {
157: if (props == null) {
158: return;
159: }
160:
161: for (Iterator iterator = props.entrySet().iterator(); iterator
162: .hasNext();) {
163: Map.Entry entry = (Map.Entry) iterator.next();
164: Object key = entry.getKey();
165: if (key.toString().startsWith(prefix)) {
166: newProps.put(key, entry.getValue());
167: }
168: }
169: }
170:
171: public static Map getPropertiesWithoutPrefix(Map props,
172: String prefix) {
173: Map newProps = new HashMap();
174: for (Iterator iterator = props.entrySet().iterator(); iterator
175: .hasNext();) {
176: Map.Entry entry = (Map.Entry) iterator.next();
177: Object key = entry.getKey();
178: if (!key.toString().startsWith(prefix)) {
179: newProps.put(key, entry.getValue());
180: }
181: }
182: return newProps;
183: }
184:
185: public static Properties getPropertiesFromQueryString(String query) {
186: Properties props = new Properties();
187:
188: if (query == null) {
189: return props;
190: }
191:
192: query = new StringBuffer(query.length() + 1).append('&')
193: .append(query).toString();
194:
195: int x = 0;
196: while ((x = addProperty(query, x, '&', props)) != -1) {
197: // run
198: }
199:
200: return props;
201: }
202:
203: public static Properties getPropertiesFromString(String query,
204: char separator) {
205: Properties props = new Properties();
206:
207: if (query == null) {
208: return props;
209: }
210:
211: query = new StringBuffer(query.length() + 1).append(separator)
212: .append(query).toString();
213:
214: int x = 0;
215: while ((x = addProperty(query, x, separator, props)) != -1) {
216: // run
217: }
218:
219: return props;
220: }
221:
222: private static int addProperty(String query, int start,
223: char separator, Properties properties) {
224: int i = query.indexOf(separator, start);
225: int i2 = query.indexOf(separator, i + 1);
226: String pair;
227: if (i > -1 && i2 > -1) {
228: pair = query.substring(i + 1, i2);
229: } else if (i > -1) {
230: pair = query.substring(i + 1);
231: } else {
232: return -1;
233: }
234: int eq = pair.indexOf('=');
235:
236: if (eq <= 0) {
237: String key = pair;
238: String value = StringUtils.EMPTY;
239: properties.setProperty(key, value);
240: } else {
241: String key = pair.substring(0, eq);
242: String value = (eq == pair.length() ? StringUtils.EMPTY
243: : pair.substring(eq + 1));
244: properties.setProperty(key, value);
245: }
246: return i2;
247: }
248:
249: /** @deprecated Use {@link MapUtils#toString(Map, boolean)} instead */
250: public static String propertiesToString(Map props, boolean newline) {
251: return MapUtils.toString(props, newline);
252: }
253:
254: }
|