1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.kernel.util;
16  
17  import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
18  import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
19  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
20  import com.liferay.portal.kernel.log.Log;
21  import com.liferay.portal.kernel.log.LogFactoryUtil;
22  import com.liferay.portal.kernel.nio.charset.CharsetDecoderUtil;
23  import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
24  
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.InputStreamReader;
28  import java.io.PrintStream;
29  import java.io.PrintWriter;
30  import java.io.Reader;
31  
32  import java.lang.reflect.Method;
33  
34  import java.nio.ByteBuffer;
35  import java.nio.CharBuffer;
36  import java.nio.charset.CharsetDecoder;
37  import java.nio.charset.CharsetEncoder;
38  
39  import java.util.Collections;
40  import java.util.Enumeration;
41  import java.util.Iterator;
42  import java.util.List;
43  import java.util.Map;
44  import java.util.Properties;
45  
46  /**
47   * <a href="PropertiesUtil.java.html"><b><i>View Source</i></b></a>
48   *
49   * @author Brian Wing Shun Chan
50   * @author Shuyang Zhou
51   */
52  public class PropertiesUtil {
53  
54      public static void copyProperties(
55          Properties sourceProperties, Properties targetProperties) {
56  
57          for (Map.Entry<Object, Object> entry : sourceProperties.entrySet()) {
58              String key = (String)entry.getKey();
59              String value = (String)entry.getValue();
60  
61              targetProperties.setProperty(key, value);
62          }
63      }
64  
65      public static Properties fromMap(Map<String, String> map) {
66          Properties properties = new Properties();
67  
68          Iterator<Map.Entry<String, String>> itr = map.entrySet().iterator();
69  
70          while (itr.hasNext()) {
71              Map.Entry<String, String> entry = itr.next();
72  
73              String key = entry.getKey();
74              String value = entry.getValue();
75  
76              if (value != null) {
77                  properties.setProperty(key, value);
78              }
79          }
80  
81          return properties;
82      }
83  
84      public static Properties fromMap(Properties properties) {
85          return properties;
86      }
87  
88      public static void fromProperties(
89          Properties properties, Map<String, String> map) {
90  
91          map.clear();
92  
93          Iterator<Map.Entry<Object, Object>> itr =
94              properties.entrySet().iterator();
95  
96          while (itr.hasNext()) {
97              Map.Entry<Object, Object> entry = itr.next();
98  
99              map.put((String)entry.getKey(), (String)entry.getValue());
100         }
101     }
102 
103     public static Properties getProperties(
104         Properties properties, String prefix, boolean removePrefix) {
105 
106         Properties subProperties = new Properties();
107 
108         Enumeration<String> enu =
109             (Enumeration<String>)properties.propertyNames();
110 
111         while (enu.hasMoreElements()) {
112             String key = enu.nextElement();
113 
114             if (key.startsWith(prefix)) {
115                 String value = properties.getProperty(key);
116 
117                 if (removePrefix) {
118                     key = key.substring(prefix.length());
119                 }
120 
121                 subProperties.setProperty(key, value);
122             }
123         }
124 
125         return subProperties;
126     }
127 
128     public static String list(Map<String, String> map) {
129         Properties properties = fromMap(map);
130 
131         return list(properties);
132     }
133 
134     public static void list(Map<String, String> map, PrintStream printWriter) {
135         Properties properties = fromMap(map);
136 
137         properties.list(printWriter);
138     }
139 
140     public static void list(Map<String, String> map, PrintWriter printWriter) {
141         Properties properties = fromMap(map);
142 
143         properties.list(printWriter);
144     }
145 
146     public static String list(Properties properties) {
147         UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
148             new UnsyncByteArrayOutputStream();
149 
150         PrintStream printStream = new PrintStream(unsyncByteArrayOutputStream);
151 
152         properties.list(printStream);
153 
154         return unsyncByteArrayOutputStream.toString();
155     }
156 
157     public static void load(Properties properties, String s)
158         throws IOException {
159 
160         if (Validator.isNotNull(s)) {
161             s = UnicodeFormatter.toString(s);
162 
163             s = StringUtil.replace(s, "\\u003d", "=");
164             s = StringUtil.replace(s, "\\u000a", "\n");
165             s = StringUtil.replace(s, "\\u0021", "!");
166             s = StringUtil.replace(s, "\\u0023", "#");
167             s = StringUtil.replace(s, "\\u0020", " ");
168             s = StringUtil.replace(s, "\\u005c", "\\");
169 
170             properties.load(new UnsyncByteArrayInputStream(s.getBytes()));
171 
172             List<String> propertyNames = Collections.list(
173                 (Enumeration<String>)properties.propertyNames());
174 
175             for (int i = 0; i < propertyNames.size(); i++) {
176                 String key = propertyNames.get(i);
177 
178                 String value = properties.getProperty(key);
179 
180                 // Trim values because it may leave a trailing \r in certain
181                 // Windows environments. This is a known case for loading SQL
182                 // scripts in SQL Server.
183 
184                 if (value != null) {
185                     value = value.trim();
186 
187                     properties.setProperty(key, value);
188                 }
189             }
190         }
191     }
192 
193     public static Properties load(String s) throws IOException {
194         return load(s, StringPool.UTF8);
195     }
196 
197     public static Properties load(String s, String charsetName)
198         throws IOException {
199 
200         if (JavaProps.isJDK6()) {
201             return loadJDK6(new UnsyncStringReader(s));
202         }
203         else {
204             ByteBuffer byteBuffer = CharsetEncoderUtil.encode(charsetName, s);
205 
206             InputStream is = new UnsyncByteArrayInputStream(
207                 byteBuffer.array(), byteBuffer.arrayOffset(),
208                 byteBuffer.limit());
209 
210             return loadJDK5(is, charsetName);
211         }
212     }
213 
214     public static Properties load(InputStream is, String charsetName)
215         throws IOException {
216 
217         if (JavaProps.isJDK6()) {
218             return loadJDK6(new InputStreamReader(is, charsetName));
219         }
220         else {
221             return loadJDK5(is, charsetName);
222         }
223     }
224 
225     public static Properties loadJDK5(InputStream is, String charsetName)
226         throws IOException {
227 
228         Properties iso8859_1Properties = new Properties();
229 
230         iso8859_1Properties.load(is);
231 
232         Properties properties = new Properties();
233 
234         CharsetEncoder charsetEncoder = CharsetEncoderUtil.getCharsetEncoder(
235             StringPool.ISO_8859_1);
236 
237         CharsetDecoder charsetDecoder = CharsetDecoderUtil.getCharsetDecoder(
238             charsetName);
239 
240         for (Map.Entry<Object, Object> entry : iso8859_1Properties.entrySet()) {
241             String key = (String)entry.getKey();
242             String value = (String)entry.getValue();
243 
244             key = charsetDecoder.decode(
245                 charsetEncoder.encode(CharBuffer.wrap(key))).toString();
246             value = charsetDecoder.decode(
247                 charsetEncoder.encode(CharBuffer.wrap(value))).toString();
248 
249             properties.put(key, value);
250         }
251 
252         return properties;
253     }
254 
255     public static Properties loadJDK6(Reader reader) throws IOException {
256         try {
257             Properties properties = new Properties();
258 
259             _jdk6LoadMethod.invoke(properties, reader);
260 
261             return properties;
262         }
263         catch (Exception e) {
264             Throwable cause = e.getCause();
265 
266             if (cause instanceof IOException) {
267                 throw (IOException)cause;
268             }
269 
270             throw new IllegalStateException(
271                 "Failed to invoke java.util.Properties.load(Reader reader)", e);
272         }
273     }
274 
275     public static void merge(Properties properties1, Properties properties2) {
276         Enumeration<String> enu =
277             (Enumeration<String>)properties2.propertyNames();
278 
279         while (enu.hasMoreElements()) {
280             String key = enu.nextElement();
281             String value = properties2.getProperty(key);
282 
283             properties1.setProperty(key, value);
284         }
285     }
286 
287     public static String toString(Properties properties) {
288         SafeProperties safeProperties = null;
289 
290         if (properties instanceof SafeProperties) {
291             safeProperties = (SafeProperties)properties;
292         }
293 
294         StringBundler sb = null;
295 
296         if (properties.isEmpty()) {
297             sb = new StringBundler();
298         }
299         else {
300             sb = new StringBundler(properties.size() * 4);
301         }
302 
303         Enumeration<String> enu =
304             (Enumeration<String>)properties.propertyNames();
305 
306         while (enu.hasMoreElements()) {
307             String key = enu.nextElement();
308 
309             sb.append(key);
310             sb.append(StringPool.EQUAL);
311 
312             if (safeProperties != null) {
313                 sb.append(safeProperties.getEncodedProperty(key));
314             }
315             else {
316                 sb.append(properties.getProperty(key));
317             }
318 
319             sb.append(StringPool.NEW_LINE);
320         }
321 
322         return sb.toString();
323     }
324 
325     public static void trimKeys(Properties properties) {
326         Enumeration<String> enu =
327             (Enumeration<String>)properties.propertyNames();
328 
329         while (enu.hasMoreElements()) {
330             String key = enu.nextElement();
331             String value = properties.getProperty(key);
332 
333             String trimmedKey = key.trim();
334 
335             if (!key.equals(trimmedKey)) {
336                 properties.remove(key);
337                 properties.setProperty(trimmedKey, value);
338             }
339         }
340     }
341 
342     private static Log _log = LogFactoryUtil.getLog(PropertiesUtil.class);
343 
344     private static Method _jdk6LoadMethod;
345 
346     static {
347         if (JavaProps.isJDK6()) {
348             try {
349                 _jdk6LoadMethod = ReflectionUtil.getDeclaredMethod(
350                     Properties.class, "load", Reader.class);
351             }
352             catch (Exception e) {
353                 _log.error(e, e);
354             }
355         }
356     }
357 
358 }