1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.kernel.util;
16  
17  import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
18  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  
22  import java.io.IOException;
23  
24  import java.util.HashMap;
25  
26  /**
27   * <a href="UnicodeProperties.java.html"><b><i>View Source</i></b></a>
28   *
29   * <p>
30   * This is a rewrite of java.util.Properties that is not synchronized and
31   * natively supports non-ASCII encodings. It can also be configured to be
32   * "safe", allowing the values to have new line characters. When stored to a
33   * given BufferedWriter, "safe" properties will replace all new line characters
34   * with a _SAFE_NEWLINE_CHARACTER_.
35   * </p>
36   *
37   * <p>
38   * In its current form, this is not intended to replace java.util.Properties for
39   * reading properties flat files. This class is not thread-safe.
40   * </p>
41   *
42   * @author Alexander Chow
43   */
44  public class UnicodeProperties extends HashMap<String, String> {
45  
46      public UnicodeProperties() {
47          super();
48      }
49  
50      public UnicodeProperties(boolean safe) {
51          super();
52  
53          _safe = safe;
54      }
55  
56      public void fastLoad(String props) {
57          if (Validator.isNull(props)) {
58              return;
59          }
60  
61          int x = props.indexOf(CharPool.NEW_LINE);
62          int y = 0;
63  
64          while (x != -1) {
65              put(props.substring(y, x));
66  
67              y = x;
68  
69              x = props.indexOf(CharPool.NEW_LINE, y + 1);
70          }
71  
72          put(props.substring(y));
73      }
74  
75      public String getProperty(String key) {
76          return get(key);
77      }
78  
79      public String getProperty(String key, String defaultValue) {
80          if (containsKey(key)) {
81              return getProperty(key);
82          }
83          else {
84              return defaultValue;
85          }
86      }
87  
88      public boolean isSafe() {
89          return _safe;
90      }
91  
92      public void load(String props) throws IOException {
93          if (Validator.isNull(props)) {
94              return;
95          }
96  
97          UnsyncBufferedReader unsyncBufferedReader = null;
98  
99          try {
100             unsyncBufferedReader = new UnsyncBufferedReader(
101                 new UnsyncStringReader(props));
102 
103             String line = unsyncBufferedReader.readLine();
104 
105             while (line != null) {
106                 put(line);
107                 line = unsyncBufferedReader.readLine();
108             }
109         }
110         finally {
111             if (unsyncBufferedReader != null) {
112                 try {
113                     unsyncBufferedReader.close();
114                 }
115                 catch (Exception e) {
116                 }
117             }
118         }
119     }
120 
121     private void put(String line) {
122         line = line.trim();
123 
124         if (!_isComment(line)) {
125             int pos = line.indexOf(StringPool.EQUAL);
126 
127             if (pos != -1) {
128                 String key = line.substring(0, pos).trim();
129                 String value = line.substring(pos + 1).trim();
130 
131                 if (_safe) {
132                     value = _decode(value);
133                 }
134 
135                 setProperty(key, value);
136             }
137             else {
138                 _log.error("Invalid property on line " + line);
139             }
140         }
141     }
142 
143     public String put(String key, String value) {
144         if (key == null) {
145             return null;
146         }
147         else {
148             if (value == null) {
149                 return remove(key);
150             }
151             else {
152                 _length += key.length() + value.length() + 2;
153 
154                 return super.put(key, value);
155             }
156         }
157     }
158 
159     public String remove(Object key) {
160         if ((key == null) || !containsKey(key)) {
161             return null;
162         }
163         else {
164             String keyString = (String)key;
165 
166             String value = super.remove(key);
167 
168             _length -= keyString.length() + value.length() + 2;
169 
170             return value;
171         }
172     }
173 
174     public String setProperty(String key, String value) {
175         return put(key, value);
176     }
177 
178     public String toString() {
179         StringBuilder sb = new StringBuilder(_length);
180 
181         for (String key : keySet()) {
182             String value = get(key);
183 
184             if (Validator.isNotNull(value)) {
185                 if (_safe) {
186                     value = _encode(value);
187                 }
188 
189                 sb.append(key);
190                 sb.append(StringPool.EQUAL);
191                 sb.append(value);
192                 sb.append(StringPool.NEW_LINE);
193             }
194         }
195 
196         return sb.toString();
197     }
198 
199     protected int getToStringLength() {
200         return _length;
201     }
202 
203     private static String _decode(String value) {
204         return StringUtil.replace(
205             value, _SAFE_NEWLINE_CHARACTER, StringPool.NEW_LINE);
206     }
207 
208     private static String _encode(String value) {
209         return StringUtil.replace(
210             value,
211             new String[] {
212                 StringPool.RETURN_NEW_LINE, StringPool.NEW_LINE,
213                 StringPool.RETURN
214             },
215             new String[] {
216                 _SAFE_NEWLINE_CHARACTER, _SAFE_NEWLINE_CHARACTER,
217                 _SAFE_NEWLINE_CHARACTER
218             });
219     }
220 
221     private boolean _isComment(String line) {
222         return line.length() == 0 || line.startsWith(StringPool.POUND);
223     }
224 
225     private static final String _SAFE_NEWLINE_CHARACTER =
226         "_SAFE_NEWLINE_CHARACTER_";
227 
228     private static Log _log = LogFactoryUtil.getLog(UnicodeProperties.class);
229 
230     private boolean _safe = false;
231     private int _length;
232 
233 }