001: /* *****************************************************************************
002: * StringUtils.java
003: * ****************************************************************************/
004:
005: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006: * Copyright 2001-2006 Laszlo Systems, Inc. All Rights Reserved. *
007: * Use is subject to license terms. *
008: * J_LZ_COPYRIGHT_END *********************************************************/
009:
010: package org.openlaszlo.utils;
011:
012: import java.util.*;
013:
014: /**
015: * A utility class containing string utility functions.
016: *
017: * @author Oliver Steele
018: */
019: public abstract class StringUtils {
020: /**
021: * Splits a string containing <var>n</var> occurrences of
022: * <var>delim</var> into <var>n+1</var> strings that don't contain
023: * <var>delim</var> (and whose occurrences in <var>str</var> are
024: * bounded by <var>delim</var>).
025: *
026: * <p>For example, <code>split("a,b,,c", ",")<code> evaluates to
027: * <code>{"a", "b", "", "c"}</code>.
028:
029: * <p><code>split("/", "/") -> ["", ""]</code>
030: *
031: * @param str a <code>String</code> value
032: * @param delim a <code>char</code> value
033: * @return a <code>String[]</code> value
034: */
035: public static String[] split(String str, String delim) {
036: List lines = new Vector();
037: int startPos = 0;
038: while (true) {
039: int endPos = indexOf(str, delim, startPos);
040: if (endPos == -1) {
041: if (startPos > 0 || startPos < str.length()) {
042: lines.add(str.substring(startPos));
043: }
044: break;
045: }
046: lines.add(str.substring(startPos, endPos));
047: startPos = endPos + delim.length();
048: }
049: {
050: String[] result = new String[lines.size()];
051: int i = 0;
052: for (Iterator e = lines.iterator(); e.hasNext();) {
053: result[i] = (String) e.next();
054: i++;
055: }
056: return result;
057: }
058: }
059:
060: /**
061: * Returns a single string that interpolates the strings in
062: * <var>lines</var> by the delimiters <var>delim</var>.
063: *
064: * For example, <code>join({"a","b","c"}, ",")</code> would
065: * evaluate to <code>"a,b,c"</code> (if Java had a literal
066: * expression notation for arrays).
067: *
068: * @param lines a <code>String[]</code> value
069: * @param delim a <code>char</code> value
070: * @return a <code>String</code> value
071: */
072: public static String join(String[] lines, String delim) {
073: StringBuffer buffer = new StringBuffer();
074: for (int i = 0; i < lines.length; i++) {
075: if (i > 0) {
076: buffer.append(delim);
077: }
078: buffer.append(lines[i]);
079: }
080: return buffer.toString();
081: }
082:
083: /** List<Object>, String -> String */
084: public static String join(List words, String delim) {
085: StringBuffer buffer = new StringBuffer();
086: for (Iterator iter = words.iterator(); iter.hasNext();) {
087: buffer.append(iter.next());
088: if (iter.hasNext()) {
089: buffer.append(delim);
090: }
091: }
092: return buffer.toString();
093: }
094:
095: /** Return the index of the first occurrence of value in str that
096: * is later than or equal to offset.
097: * @param str a String
098: * @param value a String
099: * @param offset a String
100: * @return an int
101: */
102: public static int indexOf(String str, String value, int offset) {
103: if (value.length() == 0) {
104: throw new IllegalArgumentException();
105: }
106: while (offset < str.length()) {
107: int pos = str.indexOf(value.charAt(0), offset);
108: if (pos == -1) {
109: return pos;
110: }
111: for (int i = 1;; i++) {
112: if (i >= value.length()) {
113: return pos;
114: }
115: if (pos + i >= str.length()
116: || str.charAt(pos + i) != value.charAt(i)) {
117: break;
118: }
119: }
120: offset = pos + 1;
121: }
122: return -1;
123: }
124:
125: /** Turn CRs into LFs.
126: *
127: * Note: not implemented for DOS (CRLF) line feeds. Will turn
128: * them into double lines, which will mess up multi-line string
129: * literals.
130: *
131: * @param src a string
132: * @return a string
133: */
134: public static String normalizeLineEndings(String src) {
135: if (src.indexOf('\r') >= 0) {
136: return StringUtils.join(StringUtils.split(src, "\r"), "\n");
137: }
138: return src;
139: }
140:
141: /**
142: * Parse an int, interpreting a leading 0x or # to mean
143: * the text is in hexidecimal
144: *
145: * @param src a string
146: */
147: public static int parseInt(String src) {
148: if (src.length() > 1 && src.charAt(0) == '#') {
149: return Integer.parseInt(src.substring(1), 16);
150: } else if (src.length() > 2 && src.charAt(0) == '0'
151: && src.charAt(1) == 'x') {
152: return Integer.parseInt(src.substring(2), 16);
153: } else {
154: return Integer.parseInt(src);
155: }
156: }
157:
158: /**
159: * Replaces old character with new string.
160: *
161: * @param str string to replace old character with new string
162: * @param oldChar old character to replace in string
163: * @param newStr new string to replace old character with
164: * @return string with replaced string
165: */
166: public static String replace(String str, char oldChar, String newStr) {
167: // offset: length(newString) - length(oldChar)
168: int os = newStr.length() - 1;
169: int bufOS = 0;
170: StringBuffer buf = new StringBuffer(str);
171: int i = str.indexOf(oldChar);
172: while (i != -1) {
173: // Index of buffer needs to be adjusted by the number of times new
174: // string is replaced
175: buf.replace(i + bufOS, i + bufOS + 1, newStr);
176: bufOS += os;
177: i = str.indexOf(oldChar, i + 1);
178: }
179: return buf.toString();
180: }
181:
182: /**
183: * Replace index in string with given character
184: * @param str string to start with
185: * @param x to use
186: * @param c to replace with
187: * @return str with char replaced
188: */
189: public static String setCharAt(String str, int x, char c)
190: throws IndexOutOfBoundsException {
191:
192: StringBuffer buf = new StringBuffer(str);
193: buf.setCharAt(x, c);
194: return buf.toString();
195:
196: }
197:
198: /**
199: * Replaces old string with new string.
200: *
201: * @param str string to replace old character with new string
202: * @param oldStr old string to replace in string
203: * @param newStr new string to replace old character with
204: * @return string with replaced string
205: */
206: public static String replace(String str, String oldStr,
207: String newStr) {
208: StringBuffer buf = new StringBuffer();
209: int curIndex = 0;
210: int len = oldStr.length();
211:
212: while (true) {
213: int x = str.indexOf(oldStr, curIndex);
214: if (x != -1) {
215: buf.append(str.substring(curIndex, x));
216: buf.append(newStr);
217: curIndex = x + len;
218: } else {
219: buf.append(str.substring(curIndex));
220: break;
221: }
222: }
223:
224: return buf.toString();
225: }
226:
227: /**
228: * Expand property values in a string. Property values need to be enclosed
229: * in ${}. For example, the string
230: * "${file.separator}lps${file.separator}logs" will be converted to
231: * "/lps/logs".
232: * @param str string to expand property values
233: * @return expanded string or null, if a property variable wasn't closed
234: * properly or a specified property value doesn't exist.
235: */
236: public static String expandPropertyValues(String str)
237: throws Exception {
238: StringBuffer buf = new StringBuffer();
239:
240: int i0, i1;
241: int pos = 0;
242: String propName;
243: String propValue;
244: while (pos < str.length()) {
245: i0 = str.indexOf("${", pos);
246: if (i0 == -1) {
247: buf.append(str.substring(pos));
248: break;
249: }
250: i1 = str.indexOf('}', i0);
251: if (i1 == -1)
252: throw new Exception(
253: /* (non-Javadoc)
254: * @i18n.test
255: * @org-mes="missing close bracket: '}'"
256: */
257: org.openlaszlo.i18n.LaszloMessages.getMessage(
258: StringUtils.class.getName(), "051018-262"));
259:
260: // Append part of string we've skipped
261: if (i0 > pos)
262: buf.append(str.substring(pos, i0));
263:
264: propName = str.substring(i0 + 2, i1);
265: try {
266: propValue = System.getProperty(propName);
267: if (propValue == null)
268: throw new Exception(
269: /* (non-Javadoc)
270: * @i18n.test
271: * @org-mes="System property " + p[0] + " does not exist"
272: */
273: org.openlaszlo.i18n.LaszloMessages.getMessage(
274: StringUtils.class.getName(), "051018-279",
275: new Object[] { propName }));
276: } catch (SecurityException e) {
277: // TODO [2004-07-14 bloch]: log exception?
278: propValue = "";
279: }
280:
281: buf.append(propValue);
282:
283: pos = i1 + 1;
284: }
285: return buf.toString();
286: }
287: }
|