KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > util > Util


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56 package org.objectstyle.cayenne.util;
57
58 import java.io.BufferedInputStream JavaDoc;
59 import java.io.BufferedOutputStream JavaDoc;
60 import java.io.BufferedReader JavaDoc;
61 import java.io.ByteArrayInputStream JavaDoc;
62 import java.io.ByteArrayOutputStream JavaDoc;
63 import java.io.File JavaDoc;
64 import java.io.FileInputStream JavaDoc;
65 import java.io.FileOutputStream JavaDoc;
66 import java.io.FileReader JavaDoc;
67 import java.io.IOException JavaDoc;
68 import java.io.InputStream JavaDoc;
69 import java.io.ObjectInputStream JavaDoc;
70 import java.io.ObjectOutputStream JavaDoc;
71 import java.io.OutputStream JavaDoc;
72 import java.io.Serializable JavaDoc;
73 import java.lang.reflect.InvocationTargetException JavaDoc;
74 import java.net.URL JavaDoc;
75 import java.sql.SQLException JavaDoc;
76 import java.util.ArrayList JavaDoc;
77 import java.util.Collection JavaDoc;
78 import java.util.Collections JavaDoc;
79 import java.util.Comparator JavaDoc;
80 import java.util.HashMap JavaDoc;
81 import java.util.Iterator JavaDoc;
82 import java.util.List JavaDoc;
83 import java.util.Map JavaDoc;
84
85 import javax.xml.parsers.ParserConfigurationException JavaDoc;
86 import javax.xml.parsers.SAXParser JavaDoc;
87 import javax.xml.parsers.SAXParserFactory JavaDoc;
88
89 import org.apache.commons.lang.builder.EqualsBuilder;
90 import org.apache.commons.lang.builder.HashCodeBuilder;
91 import org.apache.oro.text.perl.Perl5Util;
92 import org.objectstyle.cayenne.CayenneException;
93 import org.objectstyle.cayenne.CayenneRuntimeException;
94 import org.xml.sax.SAXException JavaDoc;
95 import org.xml.sax.XMLReader JavaDoc;
96
97 /**
98  * Contains various unorganized static utility methods used across Cayenne.
99  *
100  * @author Andrei Adamchik
101  */

102 public class Util {
103
104     private static final Perl5Util regexUtil = new Perl5Util();
105
106     /**
107      * Reads file contents, returning it as a String, using System default
108      * line separator.
109      */

110     public static String JavaDoc stringFromFile(File JavaDoc file) throws IOException JavaDoc {
111         return stringFromFile(file, System.getProperty("line.separator"));
112     }
113
114     /**
115      * Reads file contents, returning it as a String, joining lines with provided separator.
116      */

117     public static String JavaDoc stringFromFile(File JavaDoc file, String JavaDoc joinWith) throws IOException JavaDoc {
118         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
119         BufferedReader JavaDoc in = new BufferedReader JavaDoc(new FileReader JavaDoc(file));
120
121         try {
122             String JavaDoc line = null;
123             while ((line = in.readLine()) != null) {
124                 buf.append(line).append(joinWith);
125             }
126         }
127         finally {
128             in.close();
129         }
130         return buf.toString();
131     }
132
133     /**
134      * Copies file contents from source to destination.
135      * Makes up for the lack of file copying utilities in Java
136      */

137     public static boolean copy(File JavaDoc source, File JavaDoc destination) {
138         BufferedInputStream JavaDoc fin = null;
139         BufferedOutputStream JavaDoc fout = null;
140         try {
141             int bufSize = 8 * 1024;
142             fin = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(source), bufSize);
143             fout = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(destination), bufSize);
144             copyPipe(fin, fout, bufSize);
145         }
146         catch (IOException JavaDoc ioex) {
147             return false;
148         }
149         catch (SecurityException JavaDoc sx) {
150             return false;
151         }
152         finally {
153             if (fin != null) {
154                 try {
155                     fin.close();
156                 }
157                 catch (IOException JavaDoc cioex) {
158                 }
159             }
160             if (fout != null) {
161                 try {
162                     fout.close();
163                 }
164                 catch (IOException JavaDoc cioex) {
165                 }
166             }
167         }
168         return true;
169     }
170
171     /**
172      * Save URL contents to a file.
173      */

174     public static boolean copy(URL JavaDoc from, File JavaDoc to) {
175         BufferedInputStream JavaDoc urlin = null;
176         BufferedOutputStream JavaDoc fout = null;
177         try {
178             int bufSize = 8 * 1024;
179             urlin =
180                 new BufferedInputStream JavaDoc(from.openConnection().getInputStream(), bufSize);
181             fout = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(to), bufSize);
182             copyPipe(urlin, fout, bufSize);
183         }
184         catch (IOException JavaDoc ioex) {
185             return false;
186         }
187         catch (SecurityException JavaDoc sx) {
188             return false;
189         }
190         finally {
191             if (urlin != null) {
192                 try {
193                     urlin.close();
194                 }
195                 catch (IOException JavaDoc cioex) {
196                 }
197             }
198             if (fout != null) {
199                 try {
200                     fout.close();
201                 }
202                 catch (IOException JavaDoc cioex) {
203                 }
204             }
205         }
206         return true;
207     }
208
209     /**
210      * Reads data from the input and writes it to the output,
211      * until the end of the input stream.
212      *
213      * @param in
214      * @param out
215      * @param bufSizeHint
216      * @throws IOException
217      */

218     public static void copyPipe(InputStream JavaDoc in, OutputStream JavaDoc out, int bufSizeHint)
219         throws IOException JavaDoc {
220         int read = -1;
221         byte[] buf = new byte[bufSizeHint];
222         while ((read = in.read(buf, 0, bufSizeHint)) >= 0) {
223             out.write(buf, 0, read);
224         }
225         out.flush();
226     }
227
228     /**
229      * Deletes a file or directory, allowing recursive directory
230      * deletion. This is an improved version of File.delete() method.
231      */

232     public static boolean delete(String JavaDoc filePath, boolean recursive) {
233         File JavaDoc file = new File JavaDoc(filePath);
234         if (!file.exists()) {
235             return true;
236         }
237
238         if (!recursive || !file.isDirectory())
239             return file.delete();
240
241         String JavaDoc[] list = file.list();
242         for (int i = 0; i < list.length; i++) {
243             if (!delete(filePath + File.separator + list[i], true))
244                 return false;
245         }
246
247         return file.delete();
248     }
249
250     /**
251      * Replaces all backslashes "\" with forward slashes "/". Convenience
252      * method to convert path Strings to URI format.
253      */

254     public static String JavaDoc substBackslashes(String JavaDoc string) {
255         if (string == null) {
256             return null;
257         }
258
259         return regexUtil.match("/\\\\/", string)
260             ? regexUtil.substitute("s/\\\\/\\//g", string)
261             : string;
262     }
263
264     /**
265      * Looks up and returns the root cause of an exception. If none is found,
266      * returns supplied Throwable object unchanged. If root is found,
267      * recursively "unwraps" it, and returns the result to the user.
268      */

269     public static Throwable JavaDoc unwindException(Throwable JavaDoc th) {
270         if (th instanceof CayenneException) {
271             CayenneException e = (CayenneException) th;
272             if (e.getCause() != null && e.getCause() != e) {
273                 return unwindException(e.getCause());
274             }
275         }
276         else if (th instanceof CayenneRuntimeException) {
277             CayenneRuntimeException e = (CayenneRuntimeException) th;
278             if (e.getCause() != null && e.getCause() != e) {
279                 return unwindException(e.getCause());
280             }
281         }
282         else if (th instanceof InvocationTargetException JavaDoc) {
283             InvocationTargetException JavaDoc e = (InvocationTargetException JavaDoc) th;
284             if (e.getTargetException() != null) {
285                 return unwindException(e.getTargetException());
286             }
287         }
288         else if (th instanceof SAXException JavaDoc) {
289             SAXException JavaDoc sax = (SAXException JavaDoc) th;
290             if (sax.getException() != null) {
291                 return unwindException(sax.getException());
292             }
293         }
294         else if (th instanceof SQLException JavaDoc) {
295             SQLException JavaDoc sql = (SQLException JavaDoc) th;
296             if (sql.getNextException() != null) {
297                 return unwindException(sql.getNextException());
298             }
299         }
300
301         return th;
302     }
303
304     /**
305      * Compares two objects similar to "Object.equals(Object)".
306      * Unlike Object.equals(..), this method doesn't throw an exception
307      * if any of the two objects is null.
308      */

309     public static boolean nullSafeEquals(Object JavaDoc obj1, Object JavaDoc obj2) {
310         if (obj1 == null && obj2 == null) {
311             return true;
312         }
313         else if (obj1 != null)
314         {
315           // Arrays must be handled differently since equals() only does
316
// an "==" for an array and ignores equivalence. If an array, use
317
// the Jakarta Commons Language component EqualsBuilder to determine
318
// the types contained in the array and do individual comparisons.
319
if (obj1.getClass().isArray()) {
320             EqualsBuilder builder = new EqualsBuilder();
321             builder.append(obj1, obj2);
322             return builder.isEquals();
323           }
324           else { // It is NOT an array, so use regular equals()
325
return obj1.equals(obj2);
326           }
327         }
328         else {
329             return false;
330         }
331     }
332
333     /**
334      * Compares two objects similar to "Comparable.compareTo(Object)".
335      * Unlike Comparable.compareTo(..), this method doesn't throw an exception
336      * if any of the two objects is null.
337      *
338      * @since 1.1
339      */

340     public static int nullSafeCompare(boolean nullsFirst, Comparable JavaDoc o1, Object JavaDoc o2) {
341         if (o1 == null && o2 == null) {
342             return 0;
343         }
344         else if (o1 == null) {
345             return nullsFirst ? -1 : 1;
346         }
347         else if (o2 == null) {
348             return nullsFirst ? 1 : -1;
349         }
350         else {
351             return o1.compareTo(o2);
352         }
353     }
354
355     /**
356      * Returns true, if the String is null or an empty string.
357      */

358     public static boolean isEmptyString(String JavaDoc string) {
359         return string == null || string.length() == 0;
360     }
361
362     /**
363      * Creates Serializable object copy using serialization/deserialization.
364      */

365     public static Object JavaDoc cloneViaSerialization(Serializable JavaDoc obj) throws Exception JavaDoc {
366         ByteArrayOutputStream JavaDoc bytes = new ByteArrayOutputStream JavaDoc();
367         ObjectOutputStream JavaDoc out = new ObjectOutputStream JavaDoc(bytes);
368         out.writeObject(obj);
369         out.close();
370
371         byte[] data = bytes.toByteArray();
372
373         ObjectInputStream JavaDoc in = new ObjectInputStream JavaDoc(new ByteArrayInputStream JavaDoc(data));
374         Object JavaDoc objCopy = in.readObject();
375         in.close();
376         return objCopy;
377     }
378
379     /**
380      * Creates an XMLReader with default feature set. Note that all Cayenne
381      * internal XML parsers should probably use XMLReader obtained via this
382      * method for consistency sake, and can customize feature sets as needed.
383      */

384     public static XMLReader JavaDoc createXmlReader()
385         throws SAXException JavaDoc, ParserConfigurationException JavaDoc {
386         SAXParserFactory JavaDoc spf = SAXParserFactory.newInstance();
387
388         // Create a JAXP SAXParser
389
SAXParser JavaDoc saxParser = spf.newSAXParser();
390
391         // Get the encapsulated SAX XMLReader
392
XMLReader JavaDoc reader = saxParser.getXMLReader();
393
394         // set default features
395
reader.setFeature("http://xml.org/sax/features/namespaces", true);
396
397         return reader;
398     }
399
400     /**
401      * Returns package name for the Java class as a path separated with forward slash ("/").
402      * Method is used to lookup resources that are located in package subdirectories.
403      * For example, a String "a/b/c" will be returned for class name "a.b.c.ClassName".
404      */

405     public static String JavaDoc getPackagePath(String JavaDoc className) {
406         if (regexUtil.match("/\\./", className)) {
407             String JavaDoc path = regexUtil.substitute("s/\\./\\//g", className);
408             return path.substring(0, path.lastIndexOf("/"));
409         }
410         else {
411             return "";
412         }
413     }
414     
415     /**
416      * Creates a mutable map out of two arrays with keys and values.
417      *
418      * @since 1.2
419      */

420     public static Map JavaDoc toMap(Object JavaDoc[] keys, Object JavaDoc[] values) {
421         int keysSize = (keys != null) ? keys.length : 0;
422         int valuesSize = (values != null) ? values.length : 0;
423
424         if (keysSize == 0 && valuesSize == 0) {
425             // return mutable map
426
return new HashMap JavaDoc();
427         }
428
429         if (keysSize != valuesSize) {
430             throw new IllegalArgumentException JavaDoc(
431                     "The number of keys doesn't match the number of values.");
432         }
433
434         Map JavaDoc map = new HashMap JavaDoc();
435         for (int i = 0; i < keysSize; i++) {
436             map.put(keys[i], values[i]);
437         }
438
439         return map;
440     }
441
442     /**
443      * Extracts extension from the file name. Dot is not included in the returned string.
444      */

445     public static String JavaDoc extractFileExtension(String JavaDoc fileName) {
446         int dotInd = fileName.lastIndexOf('.');
447
448         // if dot is in the first position,
449
// we are dealing with a hidden file rather than an extension
450
return (dotInd > 0 && dotInd < fileName.length())
451             ? fileName.substring(dotInd + 1)
452             : null;
453     }
454
455     /**
456      * Strips extension from the file name.
457      */

458     public static String JavaDoc stripFileExtension(String JavaDoc fileName) {
459         int dotInd = fileName.lastIndexOf('.');
460
461         // if dot is in the first position,
462
// we are dealing with a hidden file rather than an extension
463
return (dotInd > 0) ? fileName.substring(0, dotInd) : fileName;
464     }
465     
466     /**
467      * Strips "\n", "\r\n", "\r" from the argument string.
468      *
469      * @since 1.2
470      */

471     public static String JavaDoc stripLineBreaks(String JavaDoc string, String JavaDoc replaceWith) {
472         if (isEmptyString(string)) {
473             return string;
474         }
475
476         int len = string.length();
477         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(len);
478         for (int i = 0; i < len; i++) {
479             char c = string.charAt(i);
480             
481             // skip \n, \r, \r\n
482
switch (c) {
483                 case '\n':
484                 case '\r': // do lookahead
485
if (i + 1 < len && string.charAt(i + 1) == '\n') {
486                         i++;
487                     }
488
489                     buffer.append(replaceWith);
490                     break;
491                 default:
492                     buffer.append(c);
493             }
494         }
495
496         return buffer.toString();
497     }
498
499     /**
500      * Encodes a string so that it can be used as an attribute value in an XML document.
501      * Will do conversion of the greater/less signs, quotes and ampersands.
502      */

503     public static String JavaDoc encodeXmlAttribute(String JavaDoc str) {
504         if (str == null)
505             return null;
506
507         int len = str.length();
508         if (len == 0)
509             return str;
510
511         StringBuffer JavaDoc encoded = new StringBuffer JavaDoc();
512         for (int i = 0; i < len; i++) {
513             char c = str.charAt(i);
514             if (c == '<')
515                 encoded.append("&lt;");
516             else if (c == '\"')
517                 encoded.append("&quot;");
518             else if (c == '>')
519                 encoded.append("&gt;");
520             else if (c == '\'')
521                 encoded.append("&apos;");
522             else if (c == '&')
523                 encoded.append("&amp;");
524             else
525                 encoded.append(c);
526         }
527
528         return encoded.toString();
529     }
530
531     /**
532      * Trims long strings substituting middle part with "...".
533      *
534      * @param str String to trim.
535      * @param maxLength maximum allowable length. Must be at least 5,
536      * or an IllegalArgumentException is thrown.
537      *
538      * @return String
539      */

540     public static String JavaDoc prettyTrim(String JavaDoc str, int maxLength) {
541         if (maxLength < 5) {
542             throw new IllegalArgumentException JavaDoc(
543                 "Algorithm for 'prettyTrim' works only with length >= 5. "
544                     + "Supplied length is "
545                     + maxLength);
546         }
547
548         if (str == null || str.length() <= maxLength) {
549             return str;
550         }
551
552         // find a section to cut off
553
int len = maxLength - 3;
554         int startLen = len / 2;
555         int endLen = len - startLen;
556
557         return str.substring(0, startLen) + "..." + str.substring(str.length() - endLen);
558     }
559
560     /**
561      * Returns a sorted iterator from an unsorted one.
562      * Use this method as a last resort, since it is
563      * much less efficient then just sorting a collection
564      * that backs the original iterator.
565      */

566     public static Iterator JavaDoc sortedIterator(Iterator JavaDoc it, Comparator JavaDoc comparator) {
567         List JavaDoc list = new ArrayList JavaDoc();
568         while (it.hasNext()) {
569             list.add(it.next());
570         }
571
572         Collections.sort(list, comparator);
573         return list.iterator();
574     }
575
576     /**
577      * Builds a hashCode of Collection.
578      */

579     public static int hashCode(Collection JavaDoc c) {
580         HashCodeBuilder builder = new HashCodeBuilder();
581         for (Iterator JavaDoc i = c.iterator(); i.hasNext();)
582             builder.append(i.next());
583         return builder.toHashCode();
584     }
585
586     /**
587      * Converts a SQL-style pattern to a valid Perl regular expression. E.g.:
588      *
589      * <p>
590      * <code>"billing_%"</code> will become <code>/^billing_.*$/</code>
591      * <p>
592      * <code>"user?"</code> will become <code>/^user.?$/</code>
593      *
594      * @since 1.0.6
595      */

596     public static String JavaDoc sqlPatternToRegex(String JavaDoc pattern, boolean ignoreCase) {
597         if (pattern == null) {
598             throw new NullPointerException JavaDoc("Null pattern.");
599         }
600
601         if (pattern.length() == 0) {
602             throw new IllegalArgumentException JavaDoc("Empty pattern.");
603         }
604
605         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
606
607         // convert * into regex syntax
608
// e.g. abc*x becomes /^abc.*x$/
609
// or abc?x becomes /^abc.?x$/
610
buffer.append("/^");
611         for (int j = 0; j < pattern.length(); j++) {
612             char nextChar = pattern.charAt(j);
613             if (nextChar == '%') {
614                 nextChar = '*';
615             }
616
617             if (nextChar == '*' || nextChar == '?') {
618                 buffer.append('.');
619             }
620             // escape special chars
621
else if (
622                 nextChar == '.'
623                     || nextChar == '/'
624                     || nextChar == '$'
625                     || nextChar == '^') {
626                 buffer.append('\\');
627             }
628
629             buffer.append(nextChar);
630         }
631
632         buffer.append("$/");
633
634         if (ignoreCase) {
635             buffer.append('i');
636         }
637
638         String JavaDoc finalPattern = buffer.toString();
639
640         // test the pattern
641
try {
642             regexUtil.match(finalPattern, "abc_123");
643         }
644         catch (Exception JavaDoc e) {
645             throw new IllegalArgumentException JavaDoc(
646                 "Error converting pattern: " + e.getLocalizedMessage());
647         }
648
649         return finalPattern;
650     }
651 }
652
Popular Tags