1
14
15 package com.liferay.portal.kernel.util;
16
17 import com.liferay.portal.kernel.log.Log;
18 import com.liferay.portal.kernel.log.LogFactoryUtil;
19
20 import java.io.IOException;
21 import java.io.Writer;
22
23 import java.lang.reflect.Constructor;
24
25
35 public class StringBundler {
36
37 public static final int UNSAFE_CREATE_THRESHOLD = GetterUtil.getInteger(
38 System.getProperty(
39 StringBundler.class.getName() + ".unsafe.create.threshold"));
40
41 public StringBundler() {
42 _array = new String[_DEFAULT_ARRAY_CAPACITY];
43 }
44
45 public StringBundler(int initialCapacity) {
46 if (initialCapacity <= 0) {
47 throw new IllegalArgumentException();
48 }
49
50 _array = new String[initialCapacity];
51 }
52
53 public StringBundler(String s) {
54 _array = new String[_DEFAULT_ARRAY_CAPACITY];
55
56 _array[0] = s;
57
58 _arrayIndex = 1;
59 }
60
61 public StringBundler(String[] stringArray) {
62 this(stringArray, 0);
63 }
64
65 public StringBundler(String[] stringArray, int extraSpace) {
66 _array = new String[stringArray.length + extraSpace];
67
68 for (int i = 0; i < stringArray.length; i++) {
69 String s = stringArray[i];
70
71 if ((s != null) && (s.length() > 0)) {
72 _array[_arrayIndex++] = s;
73 }
74 }
75 }
76
77 public StringBundler append(boolean b) {
78 if (b) {
79 return append(_TRUE);
80 }
81 else {
82 return append(_FALSE);
83 }
84 }
85
86 public StringBundler append(char c) {
87 return append(String.valueOf(c));
88 }
89
90 public StringBundler append(char[] charArray) {
91 if (charArray == null) {
92 return append("null");
93 }
94 else {
95 return append(new String(charArray));
96 }
97 }
98
99 public StringBundler append(double d) {
100 return append(Double.toString(d));
101 }
102
103 public StringBundler append(float f) {
104 return append(Float.toString(f));
105 }
106
107 public StringBundler append(int i) {
108 return append(Integer.toString(i));
109 }
110
111 public StringBundler append(long l) {
112 return append(Long.toString(l));
113 }
114
115 public StringBundler append(Object obj) {
116 return append(String.valueOf(obj));
117 }
118
119 public StringBundler append(String s) {
120 if (s == null) {
121 s = StringPool.NULL;
122 }
123
124 if (s.length() == 0) {
125 return this;
126 }
127
128 if (_arrayIndex >= _array.length) {
129 expandCapacity(_array.length * 2);
130 }
131
132 _array[_arrayIndex++] = s;
133
134 return this;
135 }
136
137 public StringBundler append(String[] stringArray) {
138 if ((stringArray == null) || (stringArray.length == 0)) {
139 return this;
140 }
141
142 if ((_array.length - _arrayIndex) < stringArray.length) {
143 expandCapacity((_array.length + stringArray.length) * 2);
144 }
145
146 for (int i = 0; i < stringArray.length; i++) {
147 String s = stringArray[i];
148
149 if ((s != null) && (s.length() > 0)) {
150 _array[_arrayIndex++] = s;
151 }
152 }
153
154 return this;
155 }
156
157 public StringBundler append(StringBundler sb) {
158 if ((sb == null) || (sb._arrayIndex == 0)) {
159 return this;
160 }
161
162 if ((_array.length - _arrayIndex) < sb._arrayIndex) {
163 expandCapacity((_array.length + sb._arrayIndex) * 2);
164 }
165
166 System.arraycopy(sb._array, 0, _array, _arrayIndex, sb._arrayIndex);
167
168 _arrayIndex += sb._arrayIndex;
169
170 return this;
171 }
172
173 public int capacity() {
174 return _array.length;
175 }
176
177 public int index() {
178 return _arrayIndex;
179 }
180
181 public int length() {
182 int length = 0;
183
184 for (int i = 0; i < _arrayIndex; i++) {
185 length += _array[i].length();
186 }
187
188 return length;
189 }
190
191 public void setIndex(int newIndex) {
192 if (newIndex < 0) {
193 throw new ArrayIndexOutOfBoundsException(newIndex);
194 }
195
196 if (newIndex > _array.length) {
197 String[] newArray = new String[newIndex];
198
199 System.arraycopy(_array, 0, newArray, 0, _arrayIndex);
200
201 _array = newArray;
202 }
203
204 if (_arrayIndex < newIndex) {
205 for (int i = _arrayIndex; i < newIndex; i++) {
206 _array[i] = StringPool.BLANK;
207 }
208 }
209
210 if (_arrayIndex > newIndex) {
211 for (int i = newIndex; i < _arrayIndex; i++) {
212 _array[i] = null;
213 }
214 }
215
216 _arrayIndex = newIndex;
217 }
218
219 public void setStringAt(String s, int index) {
220 if ((index < 0) || (index >= _arrayIndex)) {
221 throw new ArrayIndexOutOfBoundsException(index);
222 }
223
224 _array[index] = s;
225 }
226
227 public String stringAt(int index) {
228 if ((index < 0) || (index >= _arrayIndex)) {
229 throw new ArrayIndexOutOfBoundsException(index);
230 }
231
232 return _array[index];
233 }
234
235 public String toString() {
236 if (_arrayIndex == 0) {
237 return StringPool.BLANK;
238 }
239
240 if (_arrayIndex == 1) {
241 return _array[0];
242 }
243
244 if (_arrayIndex == 2) {
245 return _array[0].concat(_array[1]);
246 }
247
248 int length = 0;
249
250 for (int i = 0; i < _arrayIndex; i++) {
251 length += _array[i].length();
252 }
253
254 if ((_unsafeStringConstructor != null) &&
255 (length >= UNSAFE_CREATE_THRESHOLD)) {
256
257 return unsafeCreate(_array, _arrayIndex, length);
258 }
259 else if (_arrayIndex == 3) {
260 return _array[0].concat(_array[1]).concat(_array[2]);
261 }
262 else {
263 return safeCreate(_array, _arrayIndex, length);
264 }
265 }
266
267 public void writeTo(Writer writer) throws IOException {
268 for (int i = 0; i < _arrayIndex; i++) {
269 writer.write(_array[i]);
270 }
271 }
272
273 protected void expandCapacity(int newCapacity) {
274 String[] newArray = new String[newCapacity];
275
276 System.arraycopy(_array, 0, newArray, 0, _arrayIndex);
277
278 _array = newArray;
279 }
280
281 protected String safeCreate(String[] array, int index, int length) {
282 StringBuilder sb = new StringBuilder(length);
283
284 for (int i = 0; i < index; i++) {
285 sb.append(array[i]);
286 }
287
288 return sb.toString();
289 }
290
291 protected String unsafeCreate(String[] array, int index, int length) {
292 char[] charArray = new char[length];
293
294 int offset = 0;
295
296 for (int i = 0; i < index; i++) {
297 String s = array[i];
298
299 s.getChars(0, s.length(), charArray, offset);
300
301 offset += s.length();
302 }
303
304 try {
305 return _unsafeStringConstructor.newInstance(0, length, charArray);
306 }
307 catch (Exception e) {
308 throw new IllegalStateException(e);
309 }
310 }
311
312 private static final int _DEFAULT_ARRAY_CAPACITY = 16;
313
314 private static final String _FALSE = "false";
315
316 private static final String _TRUE = "true";
317
318 private static Log _log = LogFactoryUtil.getLog(StringBundler.class);
319
320 private static Constructor<String> _unsafeStringConstructor;
321
322 static {
323 if (UNSAFE_CREATE_THRESHOLD > 0) {
324 try {
325 _unsafeStringConstructor = String.class.getDeclaredConstructor(
326 int.class, int.class, char[].class);
327
328 _unsafeStringConstructor.setAccessible(true);
329 }
330 catch (Exception e) {
331 _log.error(e, e);
332 }
333 }
334 }
335
336 private String[] _array;
337 private int _arrayIndex;
338
339 }