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