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.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          String value = getProperty(key);
81  
82          if (value == null) {
83              return defaultValue;
84          }
85          else {
86              return value;
87          }
88      }
89  
90      public boolean isSafe() {
91          return _safe;
92      }
93  
94      public void load(String props) throws IOException {
95          if (Validator.isNull(props)) {
96              return;
97          }
98  
99          UnsyncBufferedReader unsyncBufferedReader = null;
100 
101         try {
102             unsyncBufferedReader = new UnsyncBufferedReader(
103                 new UnsyncStringReader(props));
104 
105             String line = unsyncBufferedReader.readLine();
106 
107             while (line != null) {
108                 put(line);
109                 line = unsyncBufferedReader.readLine();
110             }
111         }
112         finally {
113             if (unsyncBufferedReader != null) {
114                 try {
115                     unsyncBufferedReader.close();
116                 }
117                 catch (Exception e) {
118                 }
119             }
120         }
121     }
122 
123     private void put(String line) {
124         line = line.trim();
125 
126         if (!_isComment(line)) {
127             int pos = line.indexOf(CharPool.EQUAL);
128 
129             if (pos != -1) {
130                 String key = line.substring(0, pos).trim();
131                 String value = line.substring(pos + 1).trim();
132 
133                 if (_safe) {
134                     value = _decode(value);
135                 }
136 
137                 setProperty(key, value);
138             }
139             else {
140                 _log.error("Invalid property on line " + line);
141             }
142         }
143     }
144 
145     public String put(String key, String value) {
146         if (key == null) {
147             return null;
148         }
149         else {
150             if (value == null) {
151                 return remove(key);
152             }
153             else {
154                 _length += key.length() + value.length() + 2;
155 
156                 return super.put(key, value);
157             }
158         }
159     }
160 
161     public String remove(Object key) {
162         if ((key == null) || !containsKey(key)) {
163             return null;
164         }
165         else {
166             String keyString = (String)key;
167 
168             String value = super.remove(key);
169 
170             _length -= keyString.length() + value.length() + 2;
171 
172             return value;
173         }
174     }
175 
176     public String setProperty(String key, String value) {
177         return put(key, value);
178     }
179 
180     public String toString() {
181         StringBuilder sb = new StringBuilder(_length);
182 
183         for (String key : keySet()) {
184             String value = get(key);
185 
186             if (Validator.isNotNull(value)) {
187                 if (_safe) {
188                     value = _encode(value);
189                 }
190 
191                 sb.append(key);
192                 sb.append(StringPool.EQUAL);
193                 sb.append(value);
194                 sb.append(StringPool.NEW_LINE);
195             }
196         }
197 
198         return sb.toString();
199     }
200 
201     protected int getToStringLength() {
202         return _length;
203     }
204 
205     private static String _decode(String value) {
206         return StringUtil.replace(
207             value, _SAFE_NEWLINE_CHARACTER, StringPool.NEW_LINE);
208     }
209 
210     private static String _encode(String value) {
211         return StringUtil.replace(
212             value,
213             new String[] {
214                 StringPool.RETURN_NEW_LINE, StringPool.NEW_LINE,
215                 StringPool.RETURN
216             },
217             new String[] {
218                 _SAFE_NEWLINE_CHARACTER, _SAFE_NEWLINE_CHARACTER,
219                 _SAFE_NEWLINE_CHARACTER
220             });
221     }
222 
223     private boolean _isComment(String line) {
224         return line.length() == 0 || line.startsWith(StringPool.POUND);
225     }
226 
227     private static final String _SAFE_NEWLINE_CHARACTER =
228         "_SAFE_NEWLINE_CHARACTER_";
229 
230     private static Log _log = LogFactoryUtil.getLog(UnicodeProperties.class);
231 
232     private boolean _safe = false;
233     private int _length;
234 
235 }