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.security.MessageDigest;
020: import java.security.NoSuchAlgorithmException;
021: import java.util.ArrayList;
022: import java.util.Collection;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Map;
027:
028: /**
029: * Implements missing String format functions as a function library.
030: *
031: * @version $Revision: 1.1 $
032: */
033: public final class StringFormat {
034:
035: /** Der MessageDigest. */
036: private static MessageDigest standardMd;
037: static {
038: try {
039: standardMd = MessageDigest.getInstance("MD5");
040: } catch (NoSuchAlgorithmException e) {
041: e.printStackTrace();
042: }
043: }
044:
045: /** i don't know. */
046: private static final String SPECIALSAVECHARS = "\\";
047:
048: /** Die hexadezimalen Ziffern. */
049: private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4',
050: '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
051:
052: /** und nochmal als ein String. */
053: private static final String HEX_STRING = "0123456789ABCDEF";
054:
055: /**
056: * Hide the Constructor.
057: */
058: private StringFormat() {
059: }
060:
061: /**
062: * Converts a byte to hex digit and writes to the supplied buffer.
063: *
064: * @param b
065: * byte to convert
066: * @param buf
067: * StringBuffer to append to
068: */
069: public static void byte2hex(final byte b, final StringBuffer buf) {
070: int high = ((b & 0xf0) >> 4);
071: int low = (b & 0x0f);
072: buf.append(HEX_CHARS[high]);
073: buf.append(HEX_CHARS[low]);
074: }
075:
076: /**
077: * Converts a byte array to hex string.
078: *
079: * @param block
080: * bytearray to convert
081: * @return String Hexstring representing the block, constisting only from
082: * uppercase letters [0-9A-F]*
083: */
084: public static String toHexString(final byte[] block) {
085: StringBuffer buf = new StringBuffer();
086:
087: int len = block.length;
088:
089: for (int i = 0; i < len; i++) {
090: byte2hex(block[i], buf);
091:
092: }
093: return buf.toString();
094: }
095:
096: /**
097: * Converts the given hex string to a byte array. The hex string is
098: * interpreted as a sequence of hex digit pairs in high, low order. For odd
099: * length strings the last digit is interpreted as low value.
100: *
101: * @param str
102: * The hex string to convert to a byte array.
103: * @return A byte array containing the byte values of the hex string. throws
104: * NumberFormatException if the given string isn't a hex string
105: */
106: public static byte[] fromHexString(final String str) {
107: String hexStr = str.toUpperCase();
108: final int len = hexStr.length();
109: final int l = len / 2;
110: byte[] bytes = new byte[l + (len % 2)];
111: int i, n;
112: for (i = 0, n = 0; i + 1 < len; i += 2, n++) {
113:
114: int low = HEX_STRING.indexOf(hexStr.charAt(i + 1));
115: int high = HEX_STRING.indexOf(hexStr.charAt(i));
116: if (-1 == low || -1 == high) {
117: throw new NumberFormatException(hexStr);
118: }
119: bytes[n] = (byte) ((high << 4) | low);
120: }
121: if (len % 2 > 0) {
122: int low = HEX_STRING.indexOf(hexStr.charAt(i));
123: if (-1 == low) {
124: throw new NumberFormatException(hexStr);
125: }
126: bytes[n] = (byte) low;
127: }
128: return bytes;
129: }
130:
131: /**
132: * Converts a string to its int equivalent.
133: *
134: * @param strNum
135: * The string that should be converted
136: * @return int The int version of the string value throws
137: * NumberFormatException if the given String isn't a textual
138: * representation of an int value.
139: */
140: public static int strToInt(final String strNum) {
141: return Integer.parseInt(strNum);
142: }
143:
144: /**
145: * Returns a each 2 characters separated PathString from a MD5 HexString The
146: * used separator is System.getProperty("file.separator").
147: *
148: * @param string
149: * der String der gewandelt werden soll
150: * @param directoryDepth
151: * Die Anzahl der Unterverzeichisse
152: * @return String
153: */
154: public static String getPathFromString(final String string,
155: final int directoryDepth) {
156: int maxdirectoryDepth = (string.length() / 2);
157: StringBuffer buf = new StringBuffer();
158: if ((directoryDepth <= maxdirectoryDepth)
159: && (directoryDepth >= 0)) {
160: String filedelim = System.getProperty("file.separator");
161: // Path
162: for (int i = 0; i < (directoryDepth * 2); i++) {
163: // File-Delimiter?
164: if ((i > 0) && ((i % 2) == 0)) {
165: buf.append(filedelim);
166: }
167: buf.append(string.charAt(i));
168: }
169: buf.append(filedelim);
170: }
171: return buf.toString();
172: }
173:
174: /**
175: * Format the String representation of the given long to the given length
176: * and fills up at the beginning with the given fill value. l=654, length=5,
177: * fill='0' will lead to '00654'. If the result of l is longer than length,
178: * the full length of l is return
179: *
180: * @param l
181: * the long to be converted
182: * @param length
183: * the length of the result
184: * @param fill
185: * the fill value of the result
186: * @return the formatted string
187: */
188: public static String formatLong(final long l, final int length,
189: final char fill) {
190: String x = String.valueOf(l);
191: if (x.length() < length) {
192: StringBuffer z = new StringBuffer();
193: for (int i = 0, s = length - x.length(); i < s; i++) {
194: z.append(fill);
195: }
196: z.append(x);
197: return z.toString();
198: } else {
199: return x;
200: }
201: }
202:
203: /**
204: * Format the String representation of the given long to the given length
205: * and fills up at the beginning with the given fill value. l=654, length=5,
206: * fill='0' will lead to '00654'. If the result of l is longer than length,
207: * the full length of l is return
208: *
209: * @param x
210: * the long to be converted
211: * @param length
212: * the length of the result
213: * @param fill
214: * the fill value of the result
215: * @return the formatted string
216: */
217: public static String formatStringLeading(final String x,
218: final int length, final char fill) {
219:
220: if (x.length() < length) {
221: StringBuffer z = new StringBuffer();
222: for (int i = 0, s = length - x.length(); i < s; i++) {
223: z.append(fill);
224: }
225: z.append(x);
226: return z.toString();
227: } else {
228: if (x.length() == length) {
229: return x;
230: } else {
231: return x.substring(0, length + 1);
232: }
233: }
234: }
235:
236: /**
237: * Format the String representation of the given long to the given length
238: * and fills up at the beginning with the given fill value. l=654, length=5,
239: * fill='0' will lead to '00654'. If the result of l is longer than length,
240: * the full length of l is return
241: *
242: * @param x
243: * the long to be converted
244: * @param length
245: * the length of the result
246: * @param fill
247: * the fill value of the result
248: * @return the formatted string
249: */
250: public static String formatString(final String x, final int length,
251: final char fill) {
252:
253: if (x.length() < length) {
254: StringBuffer z = new StringBuffer(x);
255: for (int i = 0, s = length - x.length(); i < s; i++) {
256: z.append(fill);
257: }
258: return z.toString();
259: } else {
260: if (x.length() == length) {
261: return x;
262: } else {
263: return x.substring(0, length + 1);
264: }
265: }
266: }
267:
268: /**
269: * Method md5String.
270: *
271: * @param s
272: * String
273: * @return String
274: */
275: public static String md5String(final String s) {
276: // Build MD5-hashcode
277: MessageDigest md;
278: try {
279: md = (MessageDigest) standardMd.clone();
280: md.update(s.getBytes());
281: byte[] digest = md.digest();
282:
283: return StringFormat.toHexString(digest);
284:
285: } catch (CloneNotSupportedException e) {
286: // ignore, because cloning works
287: e.printStackTrace();
288: }
289: return null;
290: }
291:
292: /**
293: * Creates a well formed XML string.
294: *
295: * @param g
296: * original string
297: * @return a well formed string
298: */
299: public static String wellForm(final String g) {
300: StringBuffer newString = new StringBuffer();
301: for (int i = 0, s = g.length(); i < s; i++) {
302: char t = g.charAt(i);
303: switch (t) {
304: case '&':
305: newString.append("&");
306: break;
307: case '>':
308: newString.append(">");
309: break;
310: case '<':
311: newString.append("<");
312: break;
313: case '"':
314: newString.append(""");
315: break;
316: case '\'':
317: newString.append("'");
318: break;
319: default:
320: newString.append(t);
321: }
322: }
323: return newString.toString();
324: }
325:
326: /**
327: * Creates a String that contains all element of the given collection,
328: * seperated by the given seperator.
329: *
330: * @param col
331: * a collection of objects
332: * @param sep
333: * the seperator
334: * @return result String
335: */
336: public static String getList(final Collection col, final char sep) {
337: StringBuffer buf = new StringBuffer();
338: boolean first = true;
339: for (Iterator iter = col.iterator(); iter.hasNext();) {
340: Object element = (Object) iter.next();
341: if (!first) {
342: buf.append(sep);
343: }
344: first = false;
345: if (element.toString().indexOf(sep) != -1) {
346: buf.append('"');
347: buf.append(element.toString());
348: buf.append('"');
349: } else {
350: buf.append(element.toString());
351: }
352:
353: }
354: return buf.toString();
355:
356: }
357:
358: /**
359: * Parses the given String and returns a collection of String elements. If
360: * the separator must be part of the String, the single string element must
361: * be included in '"'
362: *
363: * @param col
364: * a string with separated strings
365: * @param sep
366: * a seperator
367: * @return a collection of strings
368: */
369: public static List parseList(final String col, final char sep) {
370: ArrayList<String> q = new ArrayList<String>();
371: StringBuffer element = new StringBuffer();
372: boolean ignore = false;
373: for (int i = 0; i < col.length(); i++) {
374: char v = col.charAt(i);
375: if (v == sep) {
376: if (!ignore) {
377: q.add(element.toString());
378: element = new StringBuffer();
379: } else {
380: element.append(v);
381: }
382: } else {
383: if (v == '"') {
384: if (element.length() == 0) {
385: ignore = true;
386: } else {
387: if (ignore) {
388: ignore = false;
389: } else {
390: element.append(v);
391: }
392: }
393: } else {
394: element.append(v);
395: }
396: }
397: }
398: if (element.length() != 0) {
399: q.add(element.toString());
400: }
401:
402: return q;
403: }
404:
405: /**
406: * Reads a string and searches for every occurence of one of the characters
407: * in <code>chars</code>. If the character occurs in <code>chars</code>
408: * it will be added to the result. If none of the characters in
409: * <code>chars</code> occurs in <code>source</code>, the method will
410: * return <code>null</code>.
411: *
412: * @param source
413: * the source to check
414: * @param chars
415: * a string that contains every character to check for.
416: * @return the result of occurences of characters from <code>chars</code>
417: * in <code>source</code> or <code>null</code>.
418: */
419: public static String containsChars(final String source,
420: final String chars) {
421: StringBuffer errorChars = new StringBuffer();
422: for (int i = 0, length = source.length(); i < length; i++) {
423: char c = source.charAt(i);
424: if (chars.indexOf(c) != -1) {
425: if (errorChars.toString().indexOf(c) == -1) {
426: errorChars.append(c);
427: }
428: }
429: }
430: if (errorChars.length() > 0) {
431: return errorChars.toString();
432: } else {
433: return null;
434: }
435: }
436:
437: /**
438: * Anzahl derr zeichen zählen.
439: *
440: * @param searchString
441: * the string to count chars
442: * @param character
443: * the character to count
444: * @return the count of chars
445: */
446: public static int countsChars(final String searchString,
447: final char character) {
448: int count = 0;
449: for (int i = 0, s = searchString.length(); i < s; i++) {
450: if (searchString.charAt(i) == character) {
451: count++;
452: }
453: }
454: return count;
455: }
456:
457: /**
458: * @param r
459: * a colletion that contains strings
460: * @return a String array
461: */
462: public static String[] fromCollection(final Collection r) {
463: String[] values = new String[r.size()];
464: int i = 0;
465: for (Iterator iter = r.iterator(); iter.hasNext();) {
466: String element = iter.next().toString();
467: values[i++] = element;
468: }
469: return values;
470: }
471:
472: /**
473: * Removes white spaces (>=ascii 32) from a string and all spaces at the
474: * end.
475: *
476: * @param s
477: * the input string
478: * @return a string without whitespaces
479: */
480: public static String filterWhiteSpace(final String s) {
481: StringBuffer result = new StringBuffer();
482: String sResult = "";
483: for (int i = 0; i < s.length(); i++) {
484: char x = s.charAt(i);
485: if (x > 31) {
486: result.append(x);
487: } else {
488: result.append(' ');
489: }
490: }
491: sResult = result.toString();
492: while (sResult.endsWith(" ")) {
493: sResult = sResult.substring(0, sResult.length() - 1);
494: }
495: return sResult;
496: }
497:
498: /**
499: * Method replaceString.
500: *
501: * @param newString
502: * String
503: * @param source
504: * String
505: * @param searchStr
506: * String
507: * @return String
508: */
509: public static String replaceString(final String newString,
510: final String source, final String searchStr) {
511: int position;
512: String sResult = source;
513: while ((position = source.indexOf(searchStr)) != -1) {
514: String start;
515: String end;
516: if (position > 0) {
517: start = source.substring(0, position);
518: } else {
519: start = "";
520: }
521: if (position + searchStr.length() - 1 < source.length() - 1) {
522: end = source.substring(position + searchStr.length(),
523: source.length());
524: } else {
525: end = "";
526: }
527: sResult = start + newString + end;
528: }
529: return sResult;
530: }
531:
532: /**
533: * Returns the value of a property. The given collection should contain
534: * strings with "name=value" entries. The method looks for the name and
535: * returns the value, else returns the default value
536: *
537: * @param property
538: * ???
539: * @param defaultValue
540: * ???
541: * @param col
542: * ???
543: * @return the value of the property or the default
544: */
545: public static String getProperty(final String property,
546: final String defaultValue, final Collection col) {
547: String value = defaultValue;
548: for (Iterator iter = col.iterator(); iter.hasNext();) {
549: String element = (String) iter.next();
550: int i = element.indexOf('=');
551: if (i != -1) {
552: String prop = element.substring(0, i).trim();
553: if (prop.equalsIgnoreCase(property)) {
554: value = element.substring(i + 1).trim();
555: if (value.startsWith("\"") && value.endsWith("\"")) {
556: value = value.substring(1, value.length() - 1);
557: }
558: break;
559: }
560: }
561: }
562: return value;
563: }
564:
565: /**
566: * Gets a Map of properties from a collection that contains strings like
567: * "prop=value".
568: *
569: * @param col
570: * the properties
571: * @return a map
572: */
573: public static Map<String, String> getProperties(final Collection col) {
574: HashMap<String, String> props = new HashMap<String, String>();
575: for (Iterator iter = col.iterator(); iter.hasNext();) {
576: String element = (String) iter.next();
577: String prop;
578: String value;
579: int i = element.indexOf('=');
580: if (i != -1) {
581: prop = element.substring(0, i).trim();
582: value = element.substring(i + 1);
583: props.put(prop, value);
584: }
585: }
586: return props;
587: }
588:
589: /**
590: * Creates a property string ( a list of comma separated key=value items)
591: * from a HashMap.
592: *
593: * @param props
594: * the properties
595: * @return a string that contains the key=value list
596: */
597: public static String getPropertyString(final Map props) {
598: StringBuffer result = new StringBuffer();
599: for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
600: String element = (String) iter.next();
601: String value = (String) (element + "=" + props.get(element));
602: if (value.indexOf(",") != -1) {
603: value = '"' + value + '"';
604: }
605: if (result.length() > 0) {
606: result.append(',');
607: }
608: result.append(value);
609: }
610: return result.toString();
611: }
612:
613: /**
614: * Sets a property in a property string list.
615: *
616: * @param property
617: * the name of the property
618: * @param value
619: * the value
620: * @param propertyString
621: * the property string list
622: * @return the result
623: */
624: public static String setProperty(final String property,
625: final String value, final String propertyString) {
626: Map<String, String> m = getProperties(StringFormat.parseList(
627: propertyString, ','));
628: m.put(property, value);
629: return getPropertyString(m);
630: }
631:
632: /**
633: * Holt aus einer Stringliste (mit CRLF getrennt) eine Collection von
634: * Strings.
635: *
636: * @param input
637: * EingangsString
638: * @return Collection
639: */
640: public static Collection getMultiLineString(final String input) {
641: ArrayList<String> lines = new ArrayList<String>();
642: StringBuffer actual = new StringBuffer();
643: for (int i = 0, length = input.length(); i < length; i++) {
644:
645: char ch = input.charAt(i);
646: if (ch == 0x0a || ch == 0x0d) {
647: if (actual.length() != 0) {
648: lines.add(actual.toString());
649: }
650: actual = new StringBuffer();
651: } else {
652: actual.append(ch);
653: }
654: }
655: if (actual.length() != 0) {
656: lines.add(actual.toString());
657: }
658: return lines;
659: }
660:
661: /**
662: * filters a string from the given characters. Example: filterString
663: * ("{blabla}", " {", "}") returns blabla
664: *
665: * @param input
666: * input String
667: * @param left
668: * linke Begrenzung
669: * @param right
670: * rechte Begrenzung
671: * @return the_filtered_string
672: */
673: public static String filterString(final String input,
674: final char left, final char right) {
675: String sReturn = input;
676: int iLeft = input.indexOf(left);
677: if (iLeft > -1) {
678: sReturn = input.substring(iLeft + 1);
679: }
680: int iRight = sReturn.indexOf(right);
681: if (iRight > -1) {
682: sReturn = sReturn.substring(0, iRight);
683: }
684: return sReturn;
685: }
686:
687: /**
688: * filters a string from the given characters. Example: filterString
689: * ("'blabla'", " '") returns blabla
690: *
691: * @param input
692: * zu filternder String
693: * @param filterchar
694: * begrenzungszeichen
695: * @return the_filtered_string
696: */
697:
698: public static String filterString(final String input,
699: final char filterchar) {
700: String sReturn = input;
701:
702: while (sReturn.startsWith("" + filterchar)) {
703: sReturn = sReturn.substring(1);
704: }
705: while (sReturn.endsWith("" + filterchar)) {
706: sReturn = sReturn.substring(0, sReturn.length() - 1);
707: }
708: return sReturn;
709: }
710:
711: /**
712: * rightrim.
713: *
714: * @param s
715: * inputstring
716: * @return string
717: */
718: public static String rtrim(final String s) {
719: int firstx = 0;
720: for (int i = s.length() - 1; i >= 0; i--) {
721: if (s.charAt(i) > 32) {
722: break;
723: } else {
724: firstx = i;
725:
726: }
727: }
728: if (firstx == 0) {
729: return "";
730: } else {
731: return s.substring(0, firstx);
732: }
733: }
734:
735: /**
736: * Converts some special characters (tab, CR, LF, 0 etc) from java escape
737: * sequences to characters.
738: *
739: * @param s
740: * the string to convert.
741: * @return the converted string
742: */
743: public static String convertEscapes(final String s) {
744: StringBuffer r = new StringBuffer();
745: StringBuffer hexBuffer = null;
746: boolean code = false;
747: int hexCount = 0;
748: for (int i = 0, length = s.length(); i < length; i++) {
749: char c = s.charAt(i);
750: if (c == '\\') {
751: code = true;
752: } else {
753: if (code) {
754: switch (c) {
755: case '0':
756: hexBuffer = new StringBuffer();
757: hexCount = -1;
758: code = false;
759: break;
760: case 'r':
761: r.append('\r');
762: code = false;
763: break;
764: case 'f':
765: r.append('\f');
766: code = false;
767: break;
768: case 'n':
769: r.append('\n');
770: code = false;
771: break;
772: case 't':
773: r.append('\t');
774: code = false;
775: break;
776: case '\\':
777: r.append('\\');
778: code = false;
779: break;
780: default:
781: }
782: } else {
783: if (hexCount != 0) {
784: if (hexCount == -1) {
785: if (c == 'x') {
786: hexCount = 2;
787: } else if (c == 'u') {
788: hexCount = 4;
789: } else {
790: hexCount = 0;
791: }
792: } else {
793: hexBuffer.append(c);
794: hexCount--;
795: if (hexCount == 0) {
796: r.append((char) Integer.parseInt(
797: hexBuffer.toString(), 16));
798: }
799: }
800:
801: } else {
802: r.append(c);
803: }
804: }
805: }
806: }
807: return r.toString();
808:
809: }
810:
811: /**
812: * converting a string so that it can be saved into a human readable file.
813: *
814: * @param theString
815: * the string to convert
816: * @param escapeSpace
817: * spaces must be escaped.
818: * @return the converted String.
819: */
820: public static String saveConvert(final String theString,
821: final boolean escapeSpace) {
822: int len = theString.length();
823: StringBuffer outBuffer = new StringBuffer(len * 2);
824:
825: for (int x = 0; x < len; x++) {
826: char aChar = theString.charAt(x);
827: switch (aChar) {
828: case ' ':
829: if (x == 0 || escapeSpace) {
830: outBuffer.append('\\');
831: }
832:
833: outBuffer.append(' ');
834: break;
835: case '\\':
836: outBuffer.append('\\');
837: outBuffer.append('\\');
838: break;
839: case '\t':
840: outBuffer.append('\\');
841: outBuffer.append('t');
842: break;
843: case '\n':
844: outBuffer.append('\\');
845: outBuffer.append('n');
846: break;
847: case '\r':
848: outBuffer.append('\\');
849: outBuffer.append('r');
850: break;
851: case '\f':
852: outBuffer.append('\\');
853: outBuffer.append('f');
854: break;
855: default:
856: // if ((aChar < 0x0020) || (aChar > 0x007e)) {
857: // outBuffer.append('\\');
858: // outBuffer.append('u');
859: // outBuffer.append(toHex((aChar >> 12) & 0xF));
860: // outBuffer.append(toHex((aChar >> 8) & 0xF));
861: // outBuffer.append(toHex((aChar >> 4) & 0xF));
862: // outBuffer.append(toHex(aChar & 0xF));
863: // } else {
864: if (SPECIALSAVECHARS.indexOf(aChar) != -1) {
865: outBuffer.append('\\');
866: }
867: outBuffer.append(aChar);
868: // }
869: }
870: }
871: return outBuffer.toString();
872: }
873:
874: /**
875: * Convert a nibble to a hex character.
876: *
877: * @param nibble
878: * the nibble to convert.
879: * @return char
880: */
881: private static char toHex(final int nibble) {
882: return HEXDIGIT[(nibble & 0xF)];
883: }
884:
885: /** A table of hex digits. */
886: private static final char[] HEXDIGIT = { '0', '1', '2', '3', '4',
887: '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
888:
889: /**
890: * getting a stack trace as a string like in exception.printStackTrace.
891: *
892: * @param cause
893: * the exception to convert.
894: * @return String
895: */
896: public static String getStackTrace(final Throwable cause) {
897: StackTraceElement[] elements = cause.getStackTrace();
898: StringBuffer buffer = new StringBuffer(1024);
899: buffer.append(cause);
900: for (int i = 0; i < elements.length; i++) {
901: StackTraceElement element = elements[i];
902: buffer.append("\r\n\tat ");
903: buffer.append(element.toString());
904: }
905: return buffer.toString();
906: }
907:
908: public static String left(final String string, final int pos) {
909: return string.substring(0, pos);
910: }
911:
912: public static String right(final String string, final int pos) {
913: return string.substring(pos);
914: }
915:
916: public static String[] splitFirst(final String string,
917: final String search) {
918: String[] result = new String[2];
919: int pos = string.indexOf(search);
920: if (pos == -1) {
921: result[0] = string;
922: } else {
923: result[0] = left(string, pos + search.length() - 1);
924: if (pos < string.length()) {
925: result[1] = right(string, pos + search.length());
926: }
927: }
928: return result;
929: }
930: }
|