1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.kernel.util;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  
28  import java.io.BufferedReader;
29  import java.io.IOException;
30  import java.io.StringReader;
31  
32  import java.util.HashMap;
33  
34  /**
35   * <a href="UnicodeProperties.java.html"><b><i>View Source</i></b></a>
36   *
37   * <p>
38   * This is a rewrite of java.util.Properties that is not synchronized and
39   * natively supports non-ASCII encodings. It can also be configured to be
40   * "safe", allowing the values to have new line characters. When stored to a
41   * given BufferedWriter, "safe" properties will replace all new line characters
42   * with a _SAFE_NEWLINE_CHARACTER_.
43   * </p>
44   *
45   * <p>
46   * In its current form, this is not intended to replace java.util.Properties for
47   * reading properties flat files. This class is not thread-safe.
48   * </p>
49   *
50   * @author Alexander Chow
51   */
52  public class UnicodeProperties extends HashMap<String, String> {
53  
54      public UnicodeProperties() {
55          super();
56      }
57  
58      public UnicodeProperties(boolean safe) {
59          super();
60  
61          _safe = safe;
62      }
63  
64      public String getProperty(String key) {
65          return get(key);
66      }
67  
68      public String getProperty(String key, String defaultValue) {
69          if (containsKey(key)) {
70              return getProperty(key);
71          }
72          else {
73              return defaultValue;
74          }
75      }
76  
77      public boolean isSafe() {
78          return _safe;
79      }
80  
81      public void load(String props) throws IOException {
82          if (Validator.isNull(props)) {
83              return;
84          }
85  
86          BufferedReader br = null;
87  
88          try {
89              br = new BufferedReader(new StringReader(props));
90  
91              String line = br.readLine();
92  
93              while (line != null) {
94                  line = line.trim();
95  
96                  if (_isComment(line)) {
97                      line = br.readLine();
98  
99                      continue;
100                 }
101 
102                 int pos = line.indexOf(StringPool.EQUAL);
103 
104                 if (pos != -1) {
105                     String key = line.substring(0, pos).trim();
106                     String value = line.substring(pos + 1).trim();
107 
108                     if (_safe) {
109                         value = _decode(value);
110                     }
111 
112                     setProperty(key, value);
113                 }
114                 else {
115                     _log.error("Invalid property on line " + line);
116                 }
117 
118                 line = br.readLine();
119             }
120         }
121         finally {
122             if (br != null) {
123                 try {
124                     br.close();
125                 }
126                 catch (Exception e) {
127                 }
128             }
129         }
130     }
131 
132     public String put(String key, String value) {
133         if (key == null) {
134             return null;
135         }
136         else {
137             if (value == null) {
138                 return remove(key);
139             }
140             else {
141                 _length += key.length() + value.length() + 2;
142 
143                 return super.put(key, value);
144             }
145         }
146     }
147 
148     public String remove(Object key) {
149         if ((key == null) || !containsKey(key)) {
150             return null;
151         }
152         else {
153             String keyString = (String)key;
154 
155             String value = super.remove(key);
156 
157             _length -= keyString.length() + value.length() + 2;
158 
159             return value;
160         }
161     }
162 
163     public String setProperty(String key, String value) {
164         return put(key, value);
165     }
166 
167     public String toString() {
168         StringBuilder sb = new StringBuilder(_length);
169 
170         for (String key : keySet()) {
171             String value = get(key);
172 
173             if (Validator.isNotNull(value)) {
174                 if (_safe) {
175                     value = _encode(value);
176                 }
177 
178                 sb.append(key);
179                 sb.append(StringPool.EQUAL);
180                 sb.append(value);
181                 sb.append(StringPool.NEW_LINE);
182             }
183         }
184 
185         return sb.toString();
186     }
187 
188     protected int getToStringLength() {
189         return _length;
190     }
191 
192     private static String _decode(String value) {
193         return StringUtil.replace(
194             value, _SAFE_NEWLINE_CHARACTER, StringPool.NEW_LINE);
195     }
196 
197     private static String _encode(String value) {
198         return StringUtil.replace(
199             value,
200             new String[] {
201                 StringPool.RETURN_NEW_LINE, StringPool.NEW_LINE,
202                 StringPool.RETURN
203             },
204             new String[] {
205                 _SAFE_NEWLINE_CHARACTER, _SAFE_NEWLINE_CHARACTER,
206                 _SAFE_NEWLINE_CHARACTER
207             });
208     }
209 
210     private boolean _isComment(String line) {
211         return line.length() == 0 || line.startsWith(StringPool.POUND);
212     }
213 
214     private static final String _SAFE_NEWLINE_CHARACTER =
215         "_SAFE_NEWLINE_CHARACTER_";
216 
217     private static Log _log = LogFactoryUtil.getLog(UnicodeProperties.class);
218 
219     private boolean _safe = false;
220     private int _length;
221 
222 }