1 | package org.apache.velocity.util; |
2 | |
3 | /* |
4 | * Copyright 2001,2004 The Apache Software Foundation. |
5 | * |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * you may not use this file except in compliance with the License. |
8 | * You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, software |
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * See the License for the specific language governing permissions and |
16 | * limitations under the License. |
17 | */ |
18 | |
19 | import java.io.File; |
20 | import java.io.FileReader; |
21 | import java.io.ByteArrayOutputStream; |
22 | import java.io.PrintWriter; |
23 | |
24 | import java.net.MalformedURLException; |
25 | |
26 | import java.util.ArrayList; |
27 | import java.util.Hashtable; |
28 | import java.util.List; |
29 | import java.util.StringTokenizer; |
30 | import java.util.Map; |
31 | |
32 | |
33 | /** |
34 | * This class provides some methods for dynamically |
35 | * invoking methods in objects, and some string |
36 | * manipulation methods used by torque. The string |
37 | * methods will soon be moved into the turbine |
38 | * string utilities class. |
39 | * |
40 | * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> |
41 | * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> |
42 | * @version $Id: StringUtils.java,v 1.16.8.1 2004/03/03 23:23:07 geirm Exp $ |
43 | */ |
44 | public class StringUtils |
45 | { |
46 | /** |
47 | * Line separator for the OS we are operating on. |
48 | */ |
49 | private static final String EOL = System.getProperty("line.separator"); |
50 | |
51 | /** |
52 | * Length of the line separator. |
53 | */ |
54 | private static final int EOL_LENGTH = EOL.length(); |
55 | |
56 | /** |
57 | * Concatenates a list of objects as a String. |
58 | * |
59 | * @param list The list of objects to concatenate. |
60 | * @return A text representation of the concatenated objects. |
61 | */ |
62 | public String concat(List list) |
63 | { |
64 | StringBuffer sb = new StringBuffer(); |
65 | int size = list.size(); |
66 | |
67 | for (int i = 0; i < size; i++) |
68 | { |
69 | sb.append(list.get(i).toString()); |
70 | } |
71 | return sb.toString(); |
72 | } |
73 | |
74 | /** |
75 | * Return a package name as a relative path name |
76 | * |
77 | * @param String package name to convert to a directory. |
78 | * @return String directory path. |
79 | */ |
80 | static public String getPackageAsPath(String pckge) |
81 | { |
82 | return pckge.replace( '.', File.separator.charAt(0) ) + File.separator; |
83 | } |
84 | |
85 | /** |
86 | * <p> |
87 | * Remove underscores from a string and replaces first |
88 | * letters with capitals. Other letters are changed to lower case. |
89 | * </p> |
90 | * |
91 | * <p> |
92 | * For example <code>foo_bar</code> becomes <code>FooBar</code> |
93 | * but <code>foo_barBar</code> becomes <code>FooBarbar</code>. |
94 | * </p> |
95 | * |
96 | * @param data string to remove underscores from. |
97 | * @return String |
98 | * @deprecated Use the org.apache.commons.util.StringUtils class |
99 | * instead. Using its firstLetterCaps() method in conjunction |
100 | * with a StringTokenizer will achieve the same result. |
101 | */ |
102 | static public String removeUnderScores (String data) |
103 | { |
104 | String temp = null; |
105 | StringBuffer out = new StringBuffer(); |
106 | temp = data; |
107 | |
108 | StringTokenizer st = new StringTokenizer(temp, "_"); |
109 | |
110 | while (st.hasMoreTokens()) |
111 | { |
112 | String element = (String) st.nextElement(); |
113 | out.append ( firstLetterCaps(element)); |
114 | } |
115 | |
116 | return out.toString(); |
117 | } |
118 | |
119 | /** |
120 | * <p> |
121 | * 'Camels Hump' replacement of underscores. |
122 | * </p> |
123 | * |
124 | * <p> |
125 | * Remove underscores from a string but leave the capitalization of the |
126 | * other letters unchanged. |
127 | * </p> |
128 | * |
129 | * <p> |
130 | * For example <code>foo_barBar</code> becomes <code>FooBarBar</code>. |
131 | * </p> |
132 | * |
133 | * @param data string to hump |
134 | * @return String |
135 | */ |
136 | static public String removeAndHump (String data) |
137 | { |
138 | return removeAndHump(data,"_"); |
139 | } |
140 | |
141 | /** |
142 | * <p> |
143 | * 'Camels Hump' replacement. |
144 | * </p> |
145 | * |
146 | * <p> |
147 | * Remove one string from another string but leave the capitalization of the |
148 | * other letters unchanged. |
149 | * </p> |
150 | * |
151 | * <p> |
152 | * For example, removing "_" from <code>foo_barBar</code> becomes <code>FooBarBar</code>. |
153 | * </p> |
154 | * |
155 | * @param data string to hump |
156 | * @param replaceThis string to be replaced |
157 | * @return String |
158 | */ |
159 | static public String removeAndHump (String data,String replaceThis) |
160 | { |
161 | String temp = null; |
162 | StringBuffer out = new StringBuffer(); |
163 | temp = data; |
164 | |
165 | StringTokenizer st = new StringTokenizer(temp, replaceThis); |
166 | |
167 | while (st.hasMoreTokens()) |
168 | { |
169 | String element = (String) st.nextElement(); |
170 | out.append ( capitalizeFirstLetter(element)); |
171 | }//while |
172 | |
173 | return out.toString(); |
174 | } |
175 | |
176 | /** |
177 | * <p> |
178 | * Makes the first letter caps and the rest lowercase. |
179 | * </p> |
180 | * |
181 | * <p> |
182 | * For example <code>fooBar</code> becomes <code>Foobar</code>. |
183 | * </p> |
184 | * |
185 | * @param data capitalize this |
186 | * @return String |
187 | */ |
188 | static public String firstLetterCaps ( String data ) |
189 | { |
190 | String firstLetter = data.substring(0,1).toUpperCase(); |
191 | String restLetters = data.substring(1).toLowerCase(); |
192 | return firstLetter + restLetters; |
193 | } |
194 | |
195 | /** |
196 | * <p> |
197 | * Capitalize the first letter but leave the rest as they are. |
198 | * </p> |
199 | * |
200 | * <p> |
201 | * For example <code>fooBar</code> becomes <code>FooBar</code>. |
202 | * </p> |
203 | * |
204 | * @param data capitalize this |
205 | * @return String |
206 | */ |
207 | static public String capitalizeFirstLetter ( String data ) |
208 | { |
209 | String firstLetter = data.substring(0,1).toUpperCase(); |
210 | String restLetters = data.substring(1); |
211 | return firstLetter + restLetters; |
212 | } |
213 | |
214 | /** |
215 | * Create a string array from a string separated by delim |
216 | * |
217 | * @param line the line to split |
218 | * @param delim the delimter to split by |
219 | * @return a string array of the split fields |
220 | */ |
221 | public static String [] split(String line, String delim) |
222 | { |
223 | List list = new ArrayList(); |
224 | StringTokenizer t = new StringTokenizer(line, delim); |
225 | while (t.hasMoreTokens()) |
226 | { |
227 | list.add(t.nextToken()); |
228 | } |
229 | return (String []) list.toArray(new String[list.size()]); |
230 | } |
231 | |
232 | /** |
233 | * Chop i characters off the end of a string. |
234 | * This method assumes that any EOL characters in String s |
235 | * and the platform EOL will be the same. |
236 | * A 2 character EOL will count as 1 character. |
237 | * |
238 | * @param string String to chop. |
239 | * @param i Number of characters to chop. |
240 | * @return String with processed answer. |
241 | */ |
242 | public static String chop(String s, int i) |
243 | { |
244 | return chop(s, i, EOL); |
245 | } |
246 | |
247 | /** |
248 | * Chop i characters off the end of a string. |
249 | * A 2 character EOL will count as 1 character. |
250 | * |
251 | * @param string String to chop. |
252 | * @param i Number of characters to chop. |
253 | * @param eol A String representing the EOL (end of line). |
254 | * @return String with processed answer. |
255 | */ |
256 | public static String chop(String s, int i, String eol) |
257 | { |
258 | if ( i == 0 || s == null || eol == null ) |
259 | { |
260 | return s; |
261 | } |
262 | |
263 | int length = s.length(); |
264 | |
265 | /* |
266 | * if it is a 2 char EOL and the string ends with |
267 | * it, nip it off. The EOL in this case is treated like 1 character |
268 | */ |
269 | if ( eol.length() == 2 && s.endsWith(eol )) |
270 | { |
271 | length -= 2; |
272 | i -= 1; |
273 | } |
274 | |
275 | if ( i > 0) |
276 | { |
277 | length -= i; |
278 | } |
279 | |
280 | if ( length < 0) |
281 | { |
282 | length = 0; |
283 | } |
284 | |
285 | return s.substring( 0, length); |
286 | } |
287 | |
288 | public static StringBuffer stringSubstitution( String argStr, |
289 | Hashtable vars ) |
290 | { |
291 | return stringSubstitution( argStr, (Map) vars ); |
292 | } |
293 | |
294 | /** |
295 | * Perform a series of substitutions. The substitions |
296 | * are performed by replacing $variable in the target |
297 | * string with the value of provided by the key "variable" |
298 | * in the provided hashtable. |
299 | * |
300 | * @param String target string |
301 | * @param Hashtable name/value pairs used for substitution |
302 | * @return String target string with replacements. |
303 | */ |
304 | public static StringBuffer stringSubstitution(String argStr, |
305 | Map vars) |
306 | { |
307 | StringBuffer argBuf = new StringBuffer(); |
308 | |
309 | for (int cIdx = 0 ; cIdx < argStr.length();) |
310 | { |
311 | char ch = argStr.charAt(cIdx); |
312 | |
313 | switch (ch) |
314 | { |
315 | case '$': |
316 | StringBuffer nameBuf = new StringBuffer(); |
317 | for (++cIdx ; cIdx < argStr.length(); ++cIdx) |
318 | { |
319 | ch = argStr.charAt(cIdx); |
320 | if (ch == '_' || Character.isLetterOrDigit(ch)) |
321 | nameBuf.append(ch); |
322 | else |
323 | break; |
324 | } |
325 | |
326 | if (nameBuf.length() > 0) |
327 | { |
328 | String value = |
329 | (String) vars.get(nameBuf.toString()); |
330 | |
331 | if (value != null) |
332 | { |
333 | argBuf.append(value); |
334 | } |
335 | } |
336 | break; |
337 | |
338 | default: |
339 | argBuf.append(ch); |
340 | ++cIdx; |
341 | break; |
342 | } |
343 | } |
344 | |
345 | return argBuf; |
346 | } |
347 | |
348 | /** |
349 | * Read the contents of a file and place them in |
350 | * a string object. |
351 | * |
352 | * @param String path to file. |
353 | * @return String contents of the file. |
354 | */ |
355 | public static String fileContentsToString(String file) |
356 | { |
357 | String contents = ""; |
358 | |
359 | File f = new File(file); |
360 | |
361 | if (f.exists()) |
362 | { |
363 | try |
364 | { |
365 | FileReader fr = new FileReader(f); |
366 | char[] template = new char[(int) f.length()]; |
367 | fr.read(template); |
368 | contents = new String(template); |
369 | } |
370 | catch (Exception e) |
371 | { |
372 | System.out.println(e); |
373 | e.printStackTrace(); |
374 | } |
375 | } |
376 | |
377 | return contents; |
378 | } |
379 | |
380 | /** |
381 | * Remove/collapse multiple newline characters. |
382 | * |
383 | * @param String string to collapse newlines in. |
384 | * @return String |
385 | */ |
386 | public static String collapseNewlines(String argStr) |
387 | { |
388 | char last = argStr.charAt(0); |
389 | StringBuffer argBuf = new StringBuffer(); |
390 | |
391 | for (int cIdx = 0 ; cIdx < argStr.length(); cIdx++) |
392 | { |
393 | char ch = argStr.charAt(cIdx); |
394 | if (ch != '\n' || last != '\n') |
395 | { |
396 | argBuf.append(ch); |
397 | last = ch; |
398 | } |
399 | } |
400 | |
401 | return argBuf.toString(); |
402 | } |
403 | |
404 | /** |
405 | * Remove/collapse multiple spaces. |
406 | * |
407 | * @param String string to remove multiple spaces from. |
408 | * @return String |
409 | */ |
410 | public static String collapseSpaces(String argStr) |
411 | { |
412 | char last = argStr.charAt(0); |
413 | StringBuffer argBuf = new StringBuffer(); |
414 | |
415 | for (int cIdx = 0 ; cIdx < argStr.length(); cIdx++) |
416 | { |
417 | char ch = argStr.charAt(cIdx); |
418 | if (ch != ' ' || last != ' ') |
419 | { |
420 | argBuf.append(ch); |
421 | last = ch; |
422 | } |
423 | } |
424 | |
425 | return argBuf.toString(); |
426 | } |
427 | |
428 | /** |
429 | * Replaces all instances of oldString with newString in line. |
430 | * Taken from the Jive forum package. |
431 | * |
432 | * @param String original string. |
433 | * @param String string in line to replace. |
434 | * @param String replace oldString with this. |
435 | * @return String string with replacements. |
436 | */ |
437 | public static final String sub(String line, String oldString, |
438 | String newString) |
439 | { |
440 | int i = 0; |
441 | if ((i = line.indexOf(oldString, i)) >= 0) |
442 | { |
443 | char [] line2 = line.toCharArray(); |
444 | char [] newString2 = newString.toCharArray(); |
445 | int oLength = oldString.length(); |
446 | StringBuffer buf = new StringBuffer(line2.length); |
447 | buf.append(line2, 0, i).append(newString2); |
448 | i += oLength; |
449 | int j = i; |
450 | while ((i = line.indexOf(oldString, i)) > 0) |
451 | { |
452 | buf.append(line2, j, i - j).append(newString2); |
453 | i += oLength; |
454 | j = i; |
455 | } |
456 | buf.append(line2, j, line2.length - j); |
457 | return buf.toString(); |
458 | } |
459 | return line; |
460 | } |
461 | |
462 | /** |
463 | * Returns the output of printStackTrace as a String. |
464 | * |
465 | * @param e A Throwable. |
466 | * @return A String. |
467 | */ |
468 | public static final String stackTrace(Throwable e) |
469 | { |
470 | String foo = null; |
471 | try |
472 | { |
473 | // And show the Error Screen. |
474 | ByteArrayOutputStream ostr = new ByteArrayOutputStream(); |
475 | e.printStackTrace( new PrintWriter(ostr,true) ); |
476 | foo = ostr.toString(); |
477 | } |
478 | catch (Exception f) |
479 | { |
480 | // Do nothing. |
481 | } |
482 | return foo; |
483 | } |
484 | |
485 | /** |
486 | * Return a context-relative path, beginning with a "/", that represents |
487 | * the canonical version of the specified path after ".." and "." elements |
488 | * are resolved out. If the specified path attempts to go outside the |
489 | * boundaries of the current context (i.e. too many ".." path elements |
490 | * are present), return <code>null</code> instead. |
491 | * |
492 | * @param path Path to be normalized |
493 | * @return String normalized path |
494 | */ |
495 | public static final String normalizePath(String path) |
496 | { |
497 | // Normalize the slashes and add leading slash if necessary |
498 | String normalized = path; |
499 | if (normalized.indexOf('\\') >= 0) |
500 | { |
501 | normalized = normalized.replace('\\', '/'); |
502 | } |
503 | |
504 | if (!normalized.startsWith("/")) |
505 | { |
506 | normalized = "/" + normalized; |
507 | } |
508 | |
509 | // Resolve occurrences of "//" in the normalized path |
510 | while (true) |
511 | { |
512 | int index = normalized.indexOf("//"); |
513 | if (index < 0) |
514 | break; |
515 | normalized = normalized.substring(0, index) + |
516 | normalized.substring(index + 1); |
517 | } |
518 | |
519 | // Resolve occurrences of "%20" in the normalized path |
520 | while (true) |
521 | { |
522 | int index = normalized.indexOf("%20"); |
523 | if (index < 0) |
524 | break; |
525 | normalized = normalized.substring(0, index) + " " + |
526 | normalized.substring(index + 3); |
527 | } |
528 | |
529 | // Resolve occurrences of "/./" in the normalized path |
530 | while (true) |
531 | { |
532 | int index = normalized.indexOf("/./"); |
533 | if (index < 0) |
534 | break; |
535 | normalized = normalized.substring(0, index) + |
536 | normalized.substring(index + 2); |
537 | } |
538 | |
539 | // Resolve occurrences of "/../" in the normalized path |
540 | while (true) |
541 | { |
542 | int index = normalized.indexOf("/../"); |
543 | if (index < 0) |
544 | break; |
545 | if (index == 0) |
546 | return (null); // Trying to go outside our context |
547 | int index2 = normalized.lastIndexOf('/', index - 1); |
548 | normalized = normalized.substring(0, index2) + |
549 | normalized.substring(index + 3); |
550 | } |
551 | |
552 | // Return the normalized path that we have completed |
553 | return (normalized); |
554 | } |
555 | |
556 | /** |
557 | * If state is true then return the trueString, else |
558 | * return the falseString. |
559 | * |
560 | * @param boolean |
561 | * @param String trueString |
562 | * @param String falseString |
563 | */ |
564 | public String select(boolean state, String trueString, String falseString) |
565 | { |
566 | if (state) |
567 | { |
568 | return trueString; |
569 | } |
570 | else |
571 | { |
572 | return falseString; |
573 | } |
574 | } |
575 | |
576 | /** |
577 | * Check to see if all the string objects passed |
578 | * in are empty. |
579 | * |
580 | * @param list A list of {@link java.lang.String} objects. |
581 | * @return Whether all strings are empty. |
582 | */ |
583 | public boolean allEmpty(List list) |
584 | { |
585 | int size = list.size(); |
586 | |
587 | for (int i = 0; i < size; i++) |
588 | { |
589 | if (list.get(i) != null && list.get(i).toString().length() > 0) |
590 | { |
591 | return false; |
592 | } |
593 | } |
594 | return true; |
595 | } |
596 | } |