001: /*
002: * MCS Media Computer Software Copyright (c) 2005 by MCS
003: * -------------------------------------- Created on 16.01.2004 by w.klaas
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
006: * use this file except in compliance with the License. You may obtain a copy of
007: * the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations under
015: * the License.
016: */
017: package de.mcs.utils;
018:
019: import java.io.IOException;
020: import java.security.MessageDigest;
021: import java.security.NoSuchAlgorithmException;
022: import java.util.ArrayList;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.StringTokenizer;
027:
028: import de.mcs.utils.codecs.Base64;
029:
030: /**
031: * This class provides static util methods for String manaipulation that aren't
032: * part of the default JDK functionalities.
033: *
034: * @author w.klaas
035: */
036: public final class StringUtils {
037: /** SPCAE Character. */
038: private static final String SPACE = " ";
039:
040: /**
041: * private constructor, to provide instancing.
042: */
043: private StringUtils() {
044: }
045:
046: /**
047: * Replaces all the occurences of a substring found within a StringBuffer by
048: * a replacement string.
049: *
050: * @param buffer
051: * the StringBuffer in where the replace will take place
052: * @param find
053: * the substring to find and replace
054: * @param replacement
055: * the replacement string for all occurences of find
056: * @return the original StringBuffer where all the occurences of find are
057: * replaced by replacement
058: */
059: public static StringBuffer replaceAll(final StringBuffer buffer,
060: final String find, final String replacement) {
061: int bufidx = buffer.length() - 1;
062: int offset = find.length();
063: while (bufidx > -1) {
064: int findidx = offset - 1;
065: while (findidx > -1) {
066: if (bufidx == -1) {
067: // Done
068: return buffer;
069: }
070: if (buffer.charAt(bufidx) == find.charAt(findidx)) {
071: findidx--; // Look for next char
072: bufidx--;
073: } else {
074: findidx = offset - 1; // Start looking again
075: bufidx--;
076: if (bufidx == -1) {
077: // Done
078: return buffer;
079: }
080: continue;
081: }
082: }
083: buffer
084: .replace(bufidx + 1, bufidx + 1 + offset,
085: replacement);
086: // start looking again
087: }
088: // No more matches
089: return buffer;
090:
091: }
092:
093: /**
094: * convinient methode for converting. seperator will be ',' delimiter will
095: * be '"'.
096: *
097: * @param array
098: * The array of strings input.
099: * @return String A string containing tokens separated by seperator.
100: */
101: public static String arrayToCSVString(final String[] array) {
102: return arrayToCSVString(array, ',', '"');
103: }
104:
105: /**
106: * Takes an array of tokens and converts into separator-separated string.
107: *
108: * @param array
109: * The array of strings input.
110: * @param localseparators
111: * The separator char.
112: * @param localdelimiter
113: * The delimiter char.
114: * @return String A string containing tokens separated by seperator.
115: */
116: public static String arrayToCSVString(final String[] array,
117: final char localseparators, final char localdelimiter) {
118: String delimiter = Character.toString(localdelimiter);
119: String separators = Character.toString(localseparators);
120: StringBuffer sb = new StringBuffer("");
121: String empty = "";
122:
123: if ((array == null) || (array.length == 0)) {
124: return empty;
125: }
126:
127: if (delimiter == null) {
128: delimiter = "\"";
129: }
130:
131: if (separators == null) {
132: separators = ",";
133: }
134:
135: for (int ix = 0; ix < array.length; ix++) {
136: // if (array[ix] != null && !array[ix].equals("")) {
137: if (array[ix] != null) {
138: StringBuffer value = new StringBuffer(array[ix]);
139: if (value.indexOf(delimiter) >= 0) {
140: value = replaceAll(value, delimiter, delimiter
141: + delimiter);
142: }
143: if ((array[ix].indexOf(separators) >= 0)
144: || (array[ix].indexOf(delimiter) >= 0)) {
145: sb.append(delimiter);
146: sb.append(value);
147: sb.append(delimiter);
148: sb.append(separators);
149: } else {
150: sb.append(value);
151: sb.append(separators);
152: }
153: }
154: }
155: String str = sb.toString();
156: if (!str.equals("")) {
157: str = str
158: .substring(0, (str.length() - separators.length()));
159: }
160: return str;
161: }
162:
163: /**
164: * Converts a delimited string into an array of string tokens. Separator is
165: * ',', delimiter is '"'
166: *
167: * @param string
168: * The 'separator' separated string.
169: * @return String[] A string array of the original tokens.
170: */
171: public static String[] csvStringToArray(final String string) {
172: return csvStringToArray(string, ',', '"');
173: }
174:
175: /**
176: * Converts a delimited string into an array of string tokens.
177: *
178: * @param str
179: * The 'separator' separated string.
180: * @param localseparators
181: * The separator char.
182: * @param localdelimiter
183: * The delimiter char.
184: * @return String[] A string array of the original tokens.
185: */
186: public static String[] csvStringToArray(final String str,
187: final char localseparators, final char localdelimiter) {
188: /**
189: * Parse comma-separated values (CSV), a common Windows file format.
190: * Sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625
191: * <p>
192: * Inner logic adapted from a C++ original that was Copyright (C) 1999
193: * Lucent Technologies Excerpted from 'The Practice of Programming' by
194: * Brian W. Kernighan and Rob Pike.
195: * <p>
196: * Included by permission of the http://tpop.awl.com/ web site, which
197: * says: "You may use this code for any purpose, as long as you leave
198: * the copyright notice and book citation attached." I have done so.
199: *
200: * @author Brian W. Kernighan and Rob Pike (C++ original)
201: * @author Ian F. Darwin (translation into Java and removal of I/O)
202: * @author Ben Ballard (rewrote advQuoted to handle '""' and for
203: * readability)
204: */
205: class CSV {
206:
207: public static final char DEFAULT_SEP = ',';
208:
209: public static final char DEFAULT_DELIM = '\"';
210:
211: /** Construct a CSV parser, with the default separator (`,'). */
212: public CSV() {
213: this (DEFAULT_SEP, DEFAULT_DELIM);
214: }
215:
216: /**
217: * Construct a CSV parser with a given separator. Must be exactly
218: * the string that is the separator, not a list of separator
219: * characters!
220: *
221: * @param delim
222: * field delimiter
223: * @param sep
224: * field separator
225: */
226: public CSV(final char sep, final char delim) {
227: fieldSep = sep;
228: fieldDelim = delim;
229: }
230:
231: /** The fields in the current String */
232: ArrayList<String> list = new ArrayList<String>();
233:
234: /** the separator char for this parser */
235: private char fieldSep;
236:
237: /** the delimiter char for this parser */
238: private char fieldDelim;
239:
240: /**
241: * parse: break the input String into fields
242: *
243: * @param line
244: * the line to parse
245: * @return java.util.Iterator containing each field from the
246: * original as a String, in order.
247: */
248: public final Iterator parse(final String line) {
249: StringBuffer sb = new StringBuffer();
250: list.clear(); // discard previous, if any
251: int i = 0;
252:
253: if (line.length() == 0) {
254: // list.add(line);
255: return list.iterator();
256: }
257: do {
258: sb.setLength(0);
259: if (i < line.length()
260: && line.charAt(i) == fieldDelim) {
261: i = advQuoted(line, sb, ++i); // skip quote
262: } else {
263: i = advPlain(line, sb, i);
264: }
265: list.add(sb.toString());
266: // Debug.println("csv", sb.toString());
267: i++;
268: } while (i < line.length());
269: return list.iterator();
270: }
271:
272: /**
273: * advQuoted: quoted field; return index of next separator
274: *
275: * @param s
276: * String
277: * @param sb
278: * StringBuffer
279: * @param i
280: * int
281: * @return int
282: */
283: private int advQuoted(final String s,
284: final StringBuffer sb, final int i) {
285: int j;
286: int len = s.length();
287: for (j = i; j < len; j++) {
288: if (s.charAt(j) == fieldDelim && j + 1 < len) {
289: if (s.charAt(j + 1) == fieldDelim) {
290: j++; // skip escape char
291: } else if (s.charAt(j + 1) == fieldSep) { // next
292: // delimeter
293: j++; // skip end quotes
294: break;
295: }
296: } else if (s.charAt(j) == fieldDelim
297: && j + 1 == len) { // end
298: // quotes at end of line
299: break; // done
300: }
301: sb.append(s.charAt(j)); // regular character.
302: }
303: return j;
304: }
305:
306: /**
307: * advPlain: unquoted field; return index of next separator
308: *
309: * @param s
310: * String
311: * @param sb
312: * StringBuffer
313: * @param i
314: * int
315: * @return int
316: */
317: private int advPlain(final String s, final StringBuffer sb,
318: final int i) {
319: int j;
320:
321: j = s.indexOf(fieldSep, i); // look for separator
322: // Debug.println("csv", "i = " + i + ", j = " + j);
323: if (j == -1) { // none found
324: sb.append(s.substring(i));
325: return s.length();
326: } else {
327: sb.append(s.substring(i, j));
328: return j;
329: }
330: }
331: }
332: CSV csv = new CSV(localseparators, localdelimiter);
333: csv.parse(str);
334: return (String[]) csv.list.toArray(new String[0]);
335: }
336:
337: /**
338: * Remove a given set of characters from a String.
339: *
340: * @param data
341: * The input string to be cleansed of 'removeChars'.
342: * @param removeChars
343: * The characters to be removed.
344: * @return String The new string cleansed of 'removeChars'.
345: */
346: public static String removeChars(final String data,
347: final String removeChars) {
348: String temp = null;
349: StringBuffer out = new StringBuffer();
350: temp = data;
351:
352: StringTokenizer st = new StringTokenizer(temp, removeChars);
353: while (st.hasMoreTokens()) {
354: String element = (String) st.nextElement();
355: out.append(element);
356: }
357: return out.toString();
358: }
359:
360: /**
361: * Given a filename, strips the .extension.
362: *
363: * @param filename
364: * filename to strip
365: * @return String filename without .extension
366: */
367: public static String stripExtension(final String filename) {
368: int index = filename.lastIndexOf('.');
369: if (index > -1) {
370: return filename.substring(0, index);
371: }
372: return filename;
373: }
374:
375: /**
376: * Performs variable substitution for a string. String is scanned for
377: * ${variable_name} and if one is found, it is replaced with corresponding
378: * value from the vars hashtable.
379: *
380: * @param origString
381: * unmodified string
382: * @param vars
383: * Hashtable of replacement values
384: * @return modified string
385: * @exception Exception
386: */
387: public static String replaceVars(final String origString,
388: final Map vars) {
389:
390: StringBuffer finalString = new StringBuffer();
391: int index = 0;
392: int i = 0;
393: String key = null;
394: String value = null;
395: while ((index = origString.indexOf("${", i)) > -1) {
396: key = origString.substring(index + 2, origString.indexOf(
397: "}", index + 3));
398: value = (String) vars.get(key);
399: finalString.append(origString.substring(i, index));
400: if (value != null) {
401: finalString.append(value);
402: } else {
403: finalString.append("${" + key + "}");
404: }
405: i = index + 3 + key.length();
406: }
407: finalString.append(origString.substring(i));
408:
409: return finalString.toString();
410: }
411:
412: /**
413: * Check strSearchValue is in Array.
414: *
415: * @param fieldProps
416: * Array
417: * @param strSearchValue
418: * SearchString
419: * @return integer Value of Index in Array
420: */
421: public static int isInArray(final String[] fieldProps,
422: final String strSearchValue) {
423: for (int i = 0; i < fieldProps.length; i++) {
424: if (fieldProps[i].equals(strSearchValue)) {
425: return i;
426: }
427: }
428: return -1;
429: }
430:
431: /**
432: * Convert byte array to a mime coded string.
433: *
434: * @param array
435: * the array to convert
436: * @return mime coded String
437: * @throws IOException
438: * if something goes wrong
439: */
440: public static String byteArrayToMimeString(final byte[] array)
441: throws IOException {
442: return Base64.encodeBytes(array);
443: }
444:
445: /**
446: * Convert a mimecoded string to a array of byte.
447: *
448: * @param string
449: * the mime coded string
450: * @return an array of byte
451: * @throws Exception
452: * if something goes wrong
453: */
454: public static byte[] mimeStringTobyteArray(final String string)
455: throws Exception {
456: return Base64.decode(string);
457: }
458:
459: /**
460: * building the md5 hash of an String.
461: *
462: * @param s
463: * String
464: * @return String
465: */
466: public static String md5String(final String s) {
467: // Build MD5-hashcode
468: MessageDigest md;
469: try {
470: md = MessageDigest.getInstance("MD5");
471: md.update(s.getBytes());
472: byte[] digest = md.digest();
473:
474: return StringFormat.toHexString(digest);
475: } catch (NoSuchAlgorithmException e) {
476: e.printStackTrace();
477: }
478: return null;
479: }
480:
481: /**
482: * Method md5String.
483: *
484: * @param s
485: * String
486: * @return byte[[]
487: */
488: public static byte[] md5StringBytes(final String s) {
489: // Build MD5-hashcode
490: MessageDigest md;
491: try {
492: md = MessageDigest.getInstance("MD5");
493: md.update(s.getBytes());
494: byte[] digest = md.digest();
495:
496: return digest;
497: } catch (NoSuchAlgorithmException e) {
498: e.printStackTrace();
499: }
500: return null;
501: }
502:
503: /**
504: * xorArrays.
505: *
506: * @param arg0
507: * byte[]
508: * @param arg1
509: * byte[]
510: * @return byte[]
511: */
512: public static byte[] xorArrays(final byte[] arg0, final byte[] arg1) {
513: byte[] xor = new byte[arg0.length];
514: int keylength = arg1.length;
515: for (int i = 0; i < xor.length; i++) {
516: xor[i] = (byte) (arg0[i] ^ arg1[i % keylength]);
517: }
518: return xor;
519: }
520:
521: /**
522: * Getting the value formatted to the actual fieldsize.
523: *
524: * @param aValue
525: * value to format
526: * @param size
527: * array index of this field
528: * @return String
529: */
530: public static String formatFieldData(final String aValue,
531: final int size) {
532: StringBuffer value = new StringBuffer(aValue);
533: while (value.length() < size) {
534: value.append(SPACE);
535: }
536: if (value.length() > size) {
537: value = new StringBuffer(value.substring(0, size));
538: }
539: return value.toString();
540: }
541:
542: /**
543: * converts a string array into a list of strings.
544: *
545: * @param strings
546: * string array to convert to
547: * @return a list.
548: */
549: public static List<String> toList(final String[] strings) {
550: ArrayList<String> list = new ArrayList<String>(strings.length);
551: for (int i = 0; i < strings.length; i++) {
552: list.add(strings[i]);
553: }
554: return list;
555: }
556: }
|