View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.util;
8   
9   import org.mule.config.i18n.CoreMessages;
10  import org.mule.config.i18n.Message;
11  
12  import java.io.IOException;
13  import java.io.InputStream;
14  import java.net.URL;
15  import java.util.HashMap;
16  import java.util.Iterator;
17  import java.util.List;
18  import java.util.Map;
19  import java.util.Properties;
20  
21  import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
22  
23  /**
24   * <code>PropertiesHelper</code> is a utility class for manipulating and filtering
25   * property Maps.
26   */
27  // @ThreadSafe
28  public final class PropertiesUtils
29  {
30      // @GuardedBy(itself)
31      private static final List maskedProperties = new CopyOnWriteArrayList();
32  
33      static
34      {
35          // When printing property lists mask password fields
36          // Users can register their own fields to mask
37          registerMaskedPropertyName("password");
38      }
39  
40      /** Do not instanciate. */
41      protected PropertiesUtils()
42      {
43          // no-op
44      }
45  
46      /**
47       * Register a property name for masking. This will prevent certain values from
48       * leaking e.g. into debugging output or logfiles.
49       *
50       * @param name the key of the property to be masked.
51       * @throws IllegalArgumentException is name is null or empty.
52       */
53      public static void registerMaskedPropertyName(String name)
54      {
55          if (StringUtils.isNotEmpty(name))
56          {
57              maskedProperties.add(name);
58          }
59          else
60          {
61              throw new IllegalArgumentException("Cannot mask empty property name.");
62          }
63      }
64  
65      /**
66       * Returns the String representation of the property value or a masked String if
67       * the property key has been registered previously via
68       * {@link #registerMaskedPropertyName(String)}.
69       *
70       * @param property a key/value pair
71       * @return String of the property value or a "masked" String that hides the
72       *         contents, or <code>null</code> if the property, its key or its value
73       *         is <code>null</code>.
74       */
75      public static String maskedPropertyValue(Map.Entry property)
76      {
77          if (property == null)
78          {
79              return null;
80          }
81  
82          Object key = property.getKey();
83          Object value = property.getValue();
84  
85          if (key == null || value == null)
86          {
87              return null;
88          }
89  
90          if (maskedProperties.contains(key))
91          {
92              return ("*****");
93          }
94          else
95          {
96              return value.toString();
97          }
98      }
99  
100     /**
101      * Read in the properties from a properties file. The file may be on the file
102      * system or the classpath.
103      *
104      * @param fileName     - The name of the properties file
105      * @param callingClass - The Class which is calling this method. This is used to
106      *                     determine the classpath.
107      * @return a java.util.Properties object containing the properties.
108      */
109     public static synchronized Properties loadProperties(String fileName, final Class callingClass)
110             throws IOException
111     {
112         InputStream is = IOUtils.getResourceAsStream(fileName, callingClass,
113                 /* tryAsFile */true, /* tryAsUrl */false);
114         if (is == null)
115         {
116             Message error = CoreMessages.cannotLoadFromClasspath(fileName);
117             throw new IOException(error.toString());
118         }
119         
120         return loadProperties(is);
121     }
122     
123     public static Properties loadProperties(URL url) throws IOException
124     {
125         if (url == null)
126         {
127             Message error = CoreMessages.objectIsNull("url");
128             throw new IOException(error.toString());
129         }
130         
131         return loadProperties(url.openStream());
132     }
133     
134     public static Properties loadProperties(InputStream is) throws IOException
135     {
136         if (is == null)
137         {
138             Message error = CoreMessages.objectIsNull("input stream");
139             throw new IOException(error.toString());
140         }
141 
142         try
143         {
144             Properties props = new Properties();
145             props.load(is);
146             return props;
147         }
148         finally
149         {
150             is.close();
151         }
152     }
153 
154     public static String removeXmlNamespacePrefix(String eleName)
155     {
156         int i = eleName.indexOf(':');
157         return (i == -1 ? eleName : eleName.substring(i + 1, eleName.length()));
158     }
159 
160     public static String removeNamespacePrefix(String eleName)
161     {
162         int i = eleName.lastIndexOf('.');
163         return (i == -1 ? eleName : eleName.substring(i + 1, eleName.length()));
164     }
165 
166     public static Map removeNamespaces(Map properties)
167     {
168         HashMap props = new HashMap(properties.size());
169         Map.Entry entry;
170         for (Iterator iter = properties.entrySet().iterator(); iter.hasNext();)
171         {
172             entry = (Map.Entry) iter.next();
173             props.put(removeNamespacePrefix((String) entry.getKey()), entry.getValue());
174 
175         }
176         return props;
177     }
178 
179     /**
180      * Will create a map of properties where the names have a prefix Allows the
181      * callee to supply the target map so a comparator can be set
182      *
183      * @param props    the source set of properties
184      * @param prefix   the prefix to filter on
185      * @param newProps return map containing the filtered list of properties or an
186      *                 empty map if no properties matched the prefix
187      */
188     public static void getPropertiesWithPrefix(Map props, String prefix, Map newProps)
189     {
190         if (props == null)
191         {
192             return;
193         }
194 
195         for (Iterator iterator = props.entrySet().iterator(); iterator.hasNext();)
196         {
197             Map.Entry entry = (Map.Entry) iterator.next();
198             Object key = entry.getKey();
199             if (key.toString().startsWith(prefix))
200             {
201                 newProps.put(key, entry.getValue());
202             }
203         }
204     }
205 
206     public static Map getPropertiesWithoutPrefix(Map props, String prefix)
207     {
208         Map newProps = new HashMap();
209         for (Iterator iterator = props.entrySet().iterator(); iterator.hasNext();)
210         {
211             Map.Entry entry = (Map.Entry) iterator.next();
212             Object key = entry.getKey();
213             if (!key.toString().startsWith(prefix))
214             {
215                 newProps.put(key, entry.getValue());
216             }
217         }
218         return newProps;
219     }
220 
221     public static Properties getPropertiesFromQueryString(String query)
222     {
223         Properties props = new Properties();
224 
225         if (query == null)
226         {
227             return props;
228         }
229 
230         query = new StringBuffer(query.length() + 1).append('&').append(query).toString();
231 
232         int x = 0;
233         while ((x = addProperty(query, x, '&', props)) != -1)
234         {
235             // run
236         }
237 
238         return props;
239     }
240 
241     public static Properties getPropertiesFromString(String query, char separator)
242     {
243         Properties props = new Properties();
244 
245         if (query == null)
246         {
247             return props;
248         }
249 
250         query = new StringBuffer(query.length() + 1).append(separator).append(query).toString();
251 
252         int x = 0;
253         while ((x = addProperty(query, x, separator, props)) != -1)
254         {
255             // run
256         }
257 
258         return props;
259     }
260 
261     private static int addProperty(String query, int start, char separator, Properties properties)
262     {
263         int i = query.indexOf(separator, start);
264         int i2 = query.indexOf(separator, i + 1);
265         String pair;
266         if (i > -1 && i2 > -1)
267         {
268             pair = query.substring(i + 1, i2);
269         }
270         else if (i > -1)
271         {
272             pair = query.substring(i + 1);
273         }
274         else
275         {
276             return -1;
277         }
278         int eq = pair.indexOf('=');
279 
280         if (eq <= 0)
281         {
282             String key = pair;
283             String value = StringUtils.EMPTY;
284             properties.setProperty(key, value);
285         }
286         else
287         {
288             String key = pair.substring(0, eq);
289             String value = (eq == pair.length() ? StringUtils.EMPTY : pair.substring(eq + 1));
290             properties.setProperty(key, value);
291         }
292         return i2;
293     }
294 
295     /** @deprecated Use {@link MapUtils#toString(Map, boolean)} instead */
296     public static String propertiesToString(Map props, boolean newline)
297     {
298         return MapUtils.toString(props, newline);
299     }
300 }