001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
018    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
019    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
020    import com.liferay.portal.kernel.nio.charset.CharsetDecoderUtil;
021    import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
022    
023    import java.io.IOException;
024    import java.io.InputStream;
025    import java.io.InputStreamReader;
026    import java.io.PrintStream;
027    import java.io.PrintWriter;
028    import java.io.Reader;
029    
030    import java.lang.reflect.Method;
031    
032    import java.nio.ByteBuffer;
033    import java.nio.CharBuffer;
034    import java.nio.charset.CharsetDecoder;
035    import java.nio.charset.CharsetEncoder;
036    
037    import java.util.Collections;
038    import java.util.Enumeration;
039    import java.util.Iterator;
040    import java.util.List;
041    import java.util.Map;
042    import java.util.Properties;
043    
044    /**
045     * @author Brian Wing Shun Chan
046     * @author Shuyang Zhou
047     */
048    public class PropertiesUtil {
049    
050            public static void copyProperties(
051                    Properties sourceProperties, Properties targetProperties) {
052    
053                    for (Map.Entry<Object, Object> entry : sourceProperties.entrySet()) {
054                            String key = (String)entry.getKey();
055                            String value = (String)entry.getValue();
056    
057                            targetProperties.setProperty(key, value);
058                    }
059            }
060    
061            public static Properties fromMap(Map<String, String> map) {
062                    Properties properties = new Properties();
063    
064                    Iterator<Map.Entry<String, String>> itr = map.entrySet().iterator();
065    
066                    while (itr.hasNext()) {
067                            Map.Entry<String, String> entry = itr.next();
068    
069                            String key = entry.getKey();
070                            String value = entry.getValue();
071    
072                            if (value != null) {
073                                    properties.setProperty(key, value);
074                            }
075                    }
076    
077                    return properties;
078            }
079    
080            public static Properties fromMap(Properties properties) {
081                    return properties;
082            }
083    
084            public static void fromProperties(
085                    Properties properties, Map<String, String> map) {
086    
087                    map.clear();
088    
089                    Iterator<Map.Entry<Object, Object>> itr =
090                            properties.entrySet().iterator();
091    
092                    while (itr.hasNext()) {
093                            Map.Entry<Object, Object> entry = itr.next();
094    
095                            map.put((String)entry.getKey(), (String)entry.getValue());
096                    }
097            }
098    
099            public static Properties getProperties(
100                    Properties properties, String prefix, boolean removePrefix) {
101    
102                    Properties newProperties = new Properties();
103    
104                    Enumeration<String> enu =
105                            (Enumeration<String>)properties.propertyNames();
106    
107                    while (enu.hasMoreElements()) {
108                            String key = enu.nextElement();
109    
110                            if (key.startsWith(prefix)) {
111                                    String value = properties.getProperty(key);
112    
113                                    if (removePrefix) {
114                                            key = key.substring(prefix.length());
115                                    }
116    
117                                    newProperties.setProperty(key, value);
118                            }
119                    }
120    
121                    return newProperties;
122            }
123    
124            public static String list(Map<String, String> map) {
125                    Properties properties = fromMap(map);
126    
127                    return list(properties);
128            }
129    
130            public static void list(Map<String, String> map, PrintStream printWriter) {
131                    Properties properties = fromMap(map);
132    
133                    properties.list(printWriter);
134            }
135    
136            public static void list(Map<String, String> map, PrintWriter printWriter) {
137                    Properties properties = fromMap(map);
138    
139                    properties.list(printWriter);
140            }
141    
142            public static String list(Properties properties) {
143                    UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
144                            new UnsyncByteArrayOutputStream();
145    
146                    PrintStream printStream = new PrintStream(unsyncByteArrayOutputStream);
147    
148                    properties.list(printStream);
149    
150                    return unsyncByteArrayOutputStream.toString();
151            }
152    
153            public static Properties load(InputStream is, String charsetName)
154                    throws IOException {
155    
156                    if (JavaDetector.isJDK6()) {
157                            return loadJDK6(new InputStreamReader(is, charsetName));
158                    }
159                    else {
160                            return loadJDK5(is, charsetName);
161                    }
162            }
163    
164            public static void load(Properties properties, String s)
165                    throws IOException {
166    
167                    if (Validator.isNull(s)) {
168                            return;
169                    }
170    
171                    s = UnicodeFormatter.toString(s);
172    
173                    s = StringUtil.replace(s, "\\u003d", "=");
174                    s = StringUtil.replace(s, "\\u000a", "\n");
175                    s = StringUtil.replace(s, "\\u0021", "!");
176                    s = StringUtil.replace(s, "\\u0023", "#");
177                    s = StringUtil.replace(s, "\\u0020", " ");
178                    s = StringUtil.replace(s, "\\u005c", "\\");
179    
180                    properties.load(new UnsyncByteArrayInputStream(s.getBytes()));
181    
182                    List<String> propertyNames = Collections.list(
183                            (Enumeration<String>)properties.propertyNames());
184    
185                    for (int i = 0; i < propertyNames.size(); i++) {
186                            String key = propertyNames.get(i);
187    
188                            String value = properties.getProperty(key);
189    
190                            // Trim values because it may leave a trailing \r in certain Windows
191                            // environments. This is a known case for loading SQL scripts in SQL
192                            // Server.
193    
194                            if (value != null) {
195                                    value = value.trim();
196    
197                                    properties.setProperty(key, value);
198                            }
199                    }
200            }
201    
202            public static Properties load(String s) throws IOException {
203                    return load(s, StringPool.UTF8);
204            }
205    
206            public static Properties load(String s, String charsetName)
207                    throws IOException {
208    
209                    if (JavaDetector.isJDK6()) {
210                            return loadJDK6(new UnsyncStringReader(s));
211                    }
212                    else {
213                            ByteBuffer byteBuffer = CharsetEncoderUtil.encode(charsetName, s);
214    
215                            InputStream is = new UnsyncByteArrayInputStream(
216                                    byteBuffer.array(), byteBuffer.arrayOffset(),
217                                    byteBuffer.limit());
218    
219                            return loadJDK5(is, charsetName);
220                    }
221            }
222    
223            public static Properties loadJDK5(InputStream is, String charsetName)
224                    throws IOException {
225    
226                    Properties iso8859_1Properties = new Properties();
227    
228                    iso8859_1Properties.load(is);
229    
230                    Properties properties = new Properties();
231    
232                    CharsetEncoder charsetEncoder = CharsetEncoderUtil.getCharsetEncoder(
233                            StringPool.ISO_8859_1);
234    
235                    CharsetDecoder charsetDecoder = CharsetDecoderUtil.getCharsetDecoder(
236                            charsetName);
237    
238                    for (Map.Entry<Object, Object> entry : iso8859_1Properties.entrySet()) {
239                            String key = (String)entry.getKey();
240                            String value = (String)entry.getValue();
241    
242                            key = charsetDecoder.decode(
243                                    charsetEncoder.encode(CharBuffer.wrap(key))).toString();
244                            value = charsetDecoder.decode(
245                                    charsetEncoder.encode(CharBuffer.wrap(value))).toString();
246    
247                            properties.put(key, value);
248                    }
249    
250                    return properties;
251            }
252    
253            public static Properties loadJDK6(Reader reader) throws IOException {
254                    try {
255                            Properties properties = new Properties();
256    
257                            if (_jdk6LoadMethod == null) {
258                                    _jdk6LoadMethod = ReflectionUtil.getDeclaredMethod(
259                                            Properties.class, "load", Reader.class);
260                            }
261    
262                            _jdk6LoadMethod.invoke(properties, reader);
263    
264                            return properties;
265                    }
266                    catch (Exception e) {
267                            Throwable cause = e.getCause();
268    
269                            if (cause instanceof IOException) {
270                                    throw (IOException)cause;
271                            }
272    
273                            throw new IllegalStateException(
274                                    "Failed to invoke java.util.Properties.load(Reader reader)", e);
275                    }
276            }
277    
278            public static void merge(Properties properties1, Properties properties2) {
279                    Enumeration<String> enu =
280                            (Enumeration<String>)properties2.propertyNames();
281    
282                    while (enu.hasMoreElements()) {
283                            String key = enu.nextElement();
284                            String value = properties2.getProperty(key);
285    
286                            properties1.setProperty(key, value);
287                    }
288            }
289    
290            public static String toString(Properties properties) {
291                    SafeProperties safeProperties = null;
292    
293                    if (properties instanceof SafeProperties) {
294                            safeProperties = (SafeProperties)properties;
295                    }
296    
297                    StringBundler sb = null;
298    
299                    if (properties.isEmpty()) {
300                            sb = new StringBundler();
301                    }
302                    else {
303                            sb = new StringBundler(properties.size() * 4);
304                    }
305    
306                    Enumeration<String> enu =
307                            (Enumeration<String>)properties.propertyNames();
308    
309                    while (enu.hasMoreElements()) {
310                            String key = enu.nextElement();
311    
312                            sb.append(key);
313                            sb.append(StringPool.EQUAL);
314    
315                            if (safeProperties != null) {
316                                    sb.append(safeProperties.getEncodedProperty(key));
317                            }
318                            else {
319                                    sb.append(properties.getProperty(key));
320                            }
321    
322                            sb.append(StringPool.NEW_LINE);
323                    }
324    
325                    return sb.toString();
326            }
327    
328            public static void trimKeys(Properties properties) {
329                    Enumeration<String> enu =
330                            (Enumeration<String>)properties.propertyNames();
331    
332                    while (enu.hasMoreElements()) {
333                            String key = enu.nextElement();
334                            String value = properties.getProperty(key);
335    
336                            String trimmedKey = key.trim();
337    
338                            if (!key.equals(trimmedKey)) {
339                                    properties.remove(key);
340                                    properties.setProperty(trimmedKey, value);
341                            }
342                    }
343            }
344    
345            private static Method _jdk6LoadMethod;
346    
347    }