001    /**
002     * Copyright (c) 2000-2012 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.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.nio.charset.CharsetDecoderUtil;
023    import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
024    
025    import java.io.IOException;
026    import java.io.InputStream;
027    import java.io.InputStreamReader;
028    import java.io.PrintStream;
029    import java.io.PrintWriter;
030    import java.io.Reader;
031    
032    import java.lang.reflect.Method;
033    
034    import java.nio.ByteBuffer;
035    import java.nio.CharBuffer;
036    import java.nio.charset.CharsetDecoder;
037    import java.nio.charset.CharsetEncoder;
038    
039    import java.util.Collections;
040    import java.util.Enumeration;
041    import java.util.Iterator;
042    import java.util.List;
043    import java.util.Map;
044    import java.util.Properties;
045    
046    /**
047     * @author Brian Wing Shun Chan
048     * @author Shuyang Zhou
049     */
050    public class PropertiesUtil {
051    
052            public static void copyProperties(
053                    Properties sourceProperties, Properties targetProperties) {
054    
055                    for (Map.Entry<Object, Object> entry : sourceProperties.entrySet()) {
056                            String key = (String)entry.getKey();
057                            String value = (String)entry.getValue();
058    
059                            targetProperties.setProperty(key, value);
060                    }
061            }
062    
063            public static Properties fromMap(Map<String, String> map) {
064                    Properties properties = new Properties();
065    
066                    Iterator<Map.Entry<String, String>> itr = map.entrySet().iterator();
067    
068                    while (itr.hasNext()) {
069                            Map.Entry<String, String> entry = itr.next();
070    
071                            String key = entry.getKey();
072                            String value = entry.getValue();
073    
074                            if (value != null) {
075                                    properties.setProperty(key, value);
076                            }
077                    }
078    
079                    return properties;
080            }
081    
082            public static Properties fromMap(Properties properties) {
083                    return properties;
084            }
085    
086            public static void fromProperties(
087                    Properties properties, Map<String, String> map) {
088    
089                    map.clear();
090    
091                    Iterator<Map.Entry<Object, Object>> itr =
092                            properties.entrySet().iterator();
093    
094                    while (itr.hasNext()) {
095                            Map.Entry<Object, Object> entry = itr.next();
096    
097                            map.put((String)entry.getKey(), (String)entry.getValue());
098                    }
099            }
100    
101            public static Properties getProperties(
102                    Properties properties, String prefix, boolean removePrefix) {
103    
104                    Properties subProperties = new Properties();
105    
106                    Enumeration<String> enu =
107                            (Enumeration<String>)properties.propertyNames();
108    
109                    while (enu.hasMoreElements()) {
110                            String key = enu.nextElement();
111    
112                            if (key.startsWith(prefix)) {
113                                    String value = properties.getProperty(key);
114    
115                                    if (removePrefix) {
116                                            key = key.substring(prefix.length());
117                                    }
118    
119                                    subProperties.setProperty(key, value);
120                            }
121                    }
122    
123                    return subProperties;
124            }
125    
126            public static String list(Map<String, String> map) {
127                    Properties properties = fromMap(map);
128    
129                    return list(properties);
130            }
131    
132            public static void list(Map<String, String> map, PrintStream printWriter) {
133                    Properties properties = fromMap(map);
134    
135                    properties.list(printWriter);
136            }
137    
138            public static void list(Map<String, String> map, PrintWriter printWriter) {
139                    Properties properties = fromMap(map);
140    
141                    properties.list(printWriter);
142            }
143    
144            public static String list(Properties properties) {
145                    UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
146                            new UnsyncByteArrayOutputStream();
147    
148                    PrintStream printStream = new PrintStream(unsyncByteArrayOutputStream);
149    
150                    properties.list(printStream);
151    
152                    return unsyncByteArrayOutputStream.toString();
153            }
154    
155            public static Properties load(InputStream is, String charsetName)
156                    throws IOException {
157    
158                    if (JavaProps.isJDK6()) {
159                            return loadJDK6(new InputStreamReader(is, charsetName));
160                    }
161                    else {
162                            return loadJDK5(is, charsetName);
163                    }
164            }
165    
166            public static void load(Properties properties, String s)
167                    throws IOException {
168    
169                    if (Validator.isNotNull(s)) {
170                            s = UnicodeFormatter.toString(s);
171    
172                            s = StringUtil.replace(s, "\\u003d", "=");
173                            s = StringUtil.replace(s, "\\u000a", "\n");
174                            s = StringUtil.replace(s, "\\u0021", "!");
175                            s = StringUtil.replace(s, "\\u0023", "#");
176                            s = StringUtil.replace(s, "\\u0020", " ");
177                            s = StringUtil.replace(s, "\\u005c", "\\");
178    
179                            properties.load(new UnsyncByteArrayInputStream(s.getBytes()));
180    
181                            List<String> propertyNames = Collections.list(
182                                    (Enumeration<String>)properties.propertyNames());
183    
184                            for (int i = 0; i < propertyNames.size(); i++) {
185                                    String key = propertyNames.get(i);
186    
187                                    String value = properties.getProperty(key);
188    
189                                    // Trim values because it may leave a trailing \r in certain
190                                    // Windows environments. This is a known case for loading SQL
191                                    // scripts in SQL Server.
192    
193                                    if (value != null) {
194                                            value = value.trim();
195    
196                                            properties.setProperty(key, value);
197                                    }
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 (JavaProps.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                            _jdk6LoadMethod.invoke(properties, reader);
258    
259                            return properties;
260                    }
261                    catch (Exception e) {
262                            Throwable cause = e.getCause();
263    
264                            if (cause instanceof IOException) {
265                                    throw (IOException)cause;
266                            }
267    
268                            throw new IllegalStateException(
269                                    "Failed to invoke java.util.Properties.load(Reader reader)", e);
270                    }
271            }
272    
273            public static void merge(Properties properties1, Properties properties2) {
274                    Enumeration<String> enu =
275                            (Enumeration<String>)properties2.propertyNames();
276    
277                    while (enu.hasMoreElements()) {
278                            String key = enu.nextElement();
279                            String value = properties2.getProperty(key);
280    
281                            properties1.setProperty(key, value);
282                    }
283            }
284    
285            public static String toString(Properties properties) {
286                    SafeProperties safeProperties = null;
287    
288                    if (properties instanceof SafeProperties) {
289                            safeProperties = (SafeProperties)properties;
290                    }
291    
292                    StringBundler sb = null;
293    
294                    if (properties.isEmpty()) {
295                            sb = new StringBundler();
296                    }
297                    else {
298                            sb = new StringBundler(properties.size() * 4);
299                    }
300    
301                    Enumeration<String> enu =
302                            (Enumeration<String>)properties.propertyNames();
303    
304                    while (enu.hasMoreElements()) {
305                            String key = enu.nextElement();
306    
307                            sb.append(key);
308                            sb.append(StringPool.EQUAL);
309    
310                            if (safeProperties != null) {
311                                    sb.append(safeProperties.getEncodedProperty(key));
312                            }
313                            else {
314                                    sb.append(properties.getProperty(key));
315                            }
316    
317                            sb.append(StringPool.NEW_LINE);
318                    }
319    
320                    return sb.toString();
321            }
322    
323            public static void trimKeys(Properties properties) {
324                    Enumeration<String> enu =
325                            (Enumeration<String>)properties.propertyNames();
326    
327                    while (enu.hasMoreElements()) {
328                            String key = enu.nextElement();
329                            String value = properties.getProperty(key);
330    
331                            String trimmedKey = key.trim();
332    
333                            if (!key.equals(trimmedKey)) {
334                                    properties.remove(key);
335                                    properties.setProperty(trimmedKey, value);
336                            }
337                    }
338            }
339    
340            private static Log _log = LogFactoryUtil.getLog(PropertiesUtil.class);
341    
342            private static Method _jdk6LoadMethod;
343    
344            static {
345                    if (JavaProps.isJDK6()) {
346                            try {
347                                    _jdk6LoadMethod = ReflectionUtil.getDeclaredMethod(
348                                            Properties.class, "load", Reader.class);
349                            }
350                            catch (Exception e) {
351                                    _log.error(e, e);
352                            }
353                    }
354            }
355    
356    }