KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > util > ObjectUtilities


1 /* ========================================================================
2  * JCommon : a free general purpose class library for the Java(tm) platform
3  * ========================================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jcommon/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ---------------------
28  * ObjectUtilitiess.java
29  * ---------------------
30  * (C) Copyright 2003-2005, by Object Refinery Limited.
31  *
32  * Original Author: David Gilbert (for Object Refinery Limited);
33  * Contributor(s): -;
34  *
35  * $Id: ObjectUtilities.java,v 1.17 2006/12/03 15:33:33 taqua Exp $
36  *
37  * Changes
38  * -------
39  * 25-Mar-2003 : Version 1 (DG);
40  * 15-Sep-2003 : Fixed bug in clone(List) method (DG);
41  * 25-Nov-2004 : Modified clone(Object) method to fail with objects that
42  * cannot be cloned, added new deepClone(Collection) method.
43  * Renamed ObjectUtils --> ObjectUtilities (DG);
44  * 11-Jan-2005 : Removed deprecated code in preparation for 1.0.0 release (DG);
45  * 18-Aug-2005 : Added casts to suppress compiler warnings, as suggested in
46  * patch 1260622 (DG);
47  *
48  */

49
50 package org.jfree.util;
51
52 import java.io.IOException JavaDoc;
53 import java.io.InputStream JavaDoc;
54 import java.lang.reflect.InvocationTargetException JavaDoc;
55 import java.lang.reflect.Method JavaDoc;
56 import java.lang.reflect.Modifier JavaDoc;
57 import java.net.URL JavaDoc;
58 import java.util.Collection JavaDoc;
59 import java.util.Iterator JavaDoc;
60 import java.util.ArrayList JavaDoc;
61 import java.util.StringTokenizer JavaDoc;
62
63 /**
64  * A collection of useful static utility methods for handling classes and object
65  * instantiation.
66  *
67  * @author Thomas Morgner
68  */

69 public final class ObjectUtilities {
70
71     /**
72      * A constant for using the TheadContext as source for the classloader.
73      */

74     public static final String JavaDoc THREAD_CONTEXT = "ThreadContext";
75     /**
76      * A constant for using the ClassContext as source for the classloader.
77      */

78     public static final String JavaDoc CLASS_CONTEXT = "ClassContext";
79
80     /**
81      * By default use the thread context.
82      */

83     private static String JavaDoc classLoaderSource = THREAD_CONTEXT;
84     /**
85      * The custom classloader to be used (if not null).
86      */

87     private static ClassLoader JavaDoc classLoader;
88
89     /**
90      * Default constructor - private.
91      */

92     private ObjectUtilities() {
93     }
94
95     /**
96      * Returns the internal configuration entry, whether the classloader of
97      * the thread context or the context classloader should be used.
98      *
99      * @return the classloader source, either THREAD_CONTEXT or CLASS_CONTEXT.
100      */

101     public static String JavaDoc getClassLoaderSource() {
102         return classLoaderSource;
103     }
104
105     /**
106      * Defines the internal configuration entry, whether the classloader of
107      * the thread context or the context classloader should be used.
108      * <p/>
109      * This setting can only be defined using the API, there is no safe way
110      * to put this into an external configuration file.
111      *
112      * @param classLoaderSource the classloader source,
113      * either THREAD_CONTEXT or CLASS_CONTEXT.
114      */

115     public static void setClassLoaderSource(final String JavaDoc classLoaderSource) {
116         ObjectUtilities.classLoaderSource = classLoaderSource;
117     }
118
119     /**
120      * Returns <code>true</code> if the two objects are equal OR both
121      * <code>null</code>.
122      *
123      * @param o1 object 1 (<code>null</code> permitted).
124      * @param o2 object 2 (<code>null</code> permitted).
125      * @return <code>true</code> or <code>false</code>.
126      */

127     public static boolean equal(final Object JavaDoc o1, final Object JavaDoc o2) {
128         if (o1 == o2) {
129             return true;
130         }
131         if (o1 != null) {
132             return o1.equals(o2);
133         }
134         else {
135             return false;
136         }
137     }
138
139     /**
140      * Returns a hash code for an object, or zero if the object is
141      * <code>null</code>.
142      *
143      * @param object the object (<code>null</code> permitted).
144      * @return The object's hash code (or zero if the object is
145      * <code>null</code>).
146      */

147     public static int hashCode(final Object JavaDoc object) {
148         int result = 0;
149         if (object != null) {
150             result = object.hashCode();
151         }
152         return result;
153     }
154
155     /**
156      * Returns a clone of the specified object, if it can be cloned, otherwise
157      * throws a CloneNotSupportedException.
158      *
159      * @param object the object to clone (<code>null</code> not permitted).
160      * @return A clone of the specified object.
161      * @throws CloneNotSupportedException if the object cannot be cloned.
162      */

163     public static Object JavaDoc clone(final Object JavaDoc object)
164         throws CloneNotSupportedException JavaDoc {
165         if (object == null) {
166             throw new IllegalArgumentException JavaDoc("Null 'object' argument.");
167         }
168         if (object instanceof PublicCloneable) {
169             final PublicCloneable pc = (PublicCloneable) object;
170             return pc.clone();
171         }
172         else {
173             try {
174                 final Method JavaDoc method = object.getClass().getMethod("clone",
175                         (Class JavaDoc[]) null);
176                 if (Modifier.isPublic(method.getModifiers())) {
177                     return method.invoke(object, (Object JavaDoc[]) null);
178                 }
179             }
180             catch (NoSuchMethodException JavaDoc e) {
181                 Log.warn("Object without clone() method is impossible.");
182             }
183             catch (IllegalAccessException JavaDoc e) {
184                 Log.warn("Object.clone(): unable to call method.");
185             }
186             catch (InvocationTargetException JavaDoc e) {
187                 Log.warn("Object without clone() method is impossible.");
188             }
189         }
190         throw new CloneNotSupportedException JavaDoc("Failed to clone.");
191     }
192
193     /**
194      * Returns a new collection containing clones of all the items in the
195      * specified collection.
196      *
197      * @param collection the collection (<code>null</code> not permitted).
198      * @return A new collection containing clones of all the items in the
199      * specified collection.
200      * @throws CloneNotSupportedException if any of the items in the collection
201      * cannot be cloned.
202      */

203     public static Collection JavaDoc deepClone(final Collection JavaDoc collection)
204         throws CloneNotSupportedException JavaDoc {
205
206         if (collection == null) {
207             throw new IllegalArgumentException JavaDoc("Null 'collection' argument.");
208         }
209         // all JDK-Collections are cloneable ...
210
// and if the collection is not clonable, then we should throw
211
// a CloneNotSupportedException anyway ...
212
final Collection JavaDoc result
213             = (Collection JavaDoc) ObjectUtilities.clone(collection);
214         result.clear();
215         final Iterator JavaDoc iterator = collection.iterator();
216         while (iterator.hasNext()) {
217             final Object JavaDoc item = iterator.next();
218             if (item != null) {
219                 result.add(clone(item));
220             }
221             else {
222                 result.add(null);
223             }
224         }
225         return result;
226     }
227
228     /**
229      * Redefines the custom classloader.
230      *
231      * @param classLoader the new classloader or null to use the default.
232      */

233     public synchronized static void setClassLoader(
234             final ClassLoader JavaDoc classLoader) {
235         ObjectUtilities.classLoader = classLoader;
236     }
237
238     /**
239      * Returns the custom classloader or null, if no custom classloader is defined.
240      *
241      * @return the custom classloader or null to use the default.
242      */

243     public static ClassLoader JavaDoc getClassLoader() {
244       return classLoader;
245     }
246
247     /**
248      * Returns the classloader, which was responsible for loading the given
249      * class.
250      *
251      * @param c the classloader, either an application class loader or the
252      * boot loader.
253      * @return the classloader, never null.
254      * @throws SecurityException if the SecurityManager does not allow to grab
255      * the context classloader.
256      */

257     public synchronized static ClassLoader JavaDoc getClassLoader(final Class JavaDoc c) {
258         if (classLoader != null) {
259             return classLoader;
260         }
261         if ("ThreadContext".equals(classLoaderSource)) {
262             final ClassLoader JavaDoc threadLoader
263                 = Thread.currentThread().getContextClassLoader();
264             if (threadLoader != null) {
265                 return threadLoader;
266             }
267         }
268
269         // Context classloader - do not cache ..
270
final ClassLoader JavaDoc applicationCL = c.getClassLoader();
271         if (applicationCL == null) {
272             return ClassLoader.getSystemClassLoader();
273         }
274         else {
275             return applicationCL;
276         }
277     }
278
279
280     /**
281      * Returns the resource specified by the <strong>absolute</strong> name.
282      *
283      * @param name the name of the resource
284      * @param c the source class
285      * @return the url of the resource or null, if not found.
286      */

287     public static URL JavaDoc getResource(final String JavaDoc name, final Class JavaDoc c) {
288         final ClassLoader JavaDoc cl = getClassLoader(c);
289         if (cl == null) {
290             return null;
291         }
292         return cl.getResource(name);
293     }
294
295     /**
296      * Returns the resource specified by the <strong>relative</strong> name.
297      *
298      * @param name the name of the resource relative to the given class
299      * @param c the source class
300      * @return the url of the resource or null, if not found.
301      */

302     public static URL JavaDoc getResourceRelative(final String JavaDoc name, final Class JavaDoc c) {
303         final ClassLoader JavaDoc cl = getClassLoader(c);
304         final String JavaDoc cname = convertName(name, c);
305         if (cl == null) {
306             return null;
307         }
308         return cl.getResource(cname);
309     }
310
311     /**
312      * Transform the class-relative resource name into a global name by
313      * appending it to the classes package name. If the name is already a
314      * global name (the name starts with a "/"), then the name is returned
315      * unchanged.
316      *
317      * @param name the resource name
318      * @param c the class which the resource is relative to
319      * @return the tranformed name.
320      */

321     private static String JavaDoc convertName(final String JavaDoc name, Class JavaDoc c) {
322         if (name.startsWith("/")) {
323             // strip leading slash..
324
return name.substring(1);
325         }
326
327         // we cant work on arrays, so remove them ...
328
while (c.isArray()) {
329             c = c.getComponentType();
330         }
331         // extract the package ...
332
final String JavaDoc baseName = c.getName();
333         final int index = baseName.lastIndexOf('.');
334         if (index == -1) {
335             return name;
336         }
337
338         final String JavaDoc pkgName = baseName.substring(0, index);
339         return pkgName.replace('.', '/') + "/" + name;
340     }
341
342     /**
343      * Returns the inputstream for the resource specified by the
344      * <strong>absolute</strong> name.
345      *
346      * @param name the name of the resource
347      * @param context the source class
348      * @return the url of the resource or null, if not found.
349      */

350     public static InputStream JavaDoc getResourceAsStream(final String JavaDoc name,
351                                                   final Class JavaDoc context) {
352         final URL JavaDoc url = getResource(name, context);
353         if (url == null) {
354             return null;
355         }
356
357         try {
358             return url.openStream();
359         }
360         catch (IOException JavaDoc e) {
361             return null;
362         }
363     }
364
365     /**
366      * Returns the inputstream for the resource specified by the
367      * <strong>relative</strong> name.
368      *
369      * @param name the name of the resource relative to the given class
370      * @param context the source class
371      * @return the url of the resource or null, if not found.
372      */

373     public static InputStream JavaDoc getResourceRelativeAsStream
374         (final String JavaDoc name, final Class JavaDoc context) {
375         final URL JavaDoc url = getResourceRelative(name, context);
376         if (url == null) {
377             return null;
378         }
379
380         try {
381             return url.openStream();
382         }
383         catch (IOException JavaDoc e) {
384             return null;
385         }
386     }
387
388     /**
389      * Tries to create a new instance of the given class. This is a short cut
390      * for the common bean instantiation code.
391      *
392      * @param className the class name as String, never null.
393      * @param source the source class, from where to get the classloader.
394      * @return the instantiated object or null, if an error occured.
395      */

396     public static Object JavaDoc loadAndInstantiate(final String JavaDoc className,
397                                             final Class JavaDoc source) {
398         try {
399             final ClassLoader JavaDoc loader = getClassLoader(source);
400             final Class JavaDoc c = loader.loadClass(className);
401             return c.newInstance();
402         }
403         catch (Exception JavaDoc e) {
404             return null;
405         }
406     }
407
408     /**
409      * Tries to create a new instance of the given class. This is a short cut
410      * for the common bean instantiation code. This method is a type-safe method
411      * and will not instantiate the class unless it is an instance of the given
412      * type.
413      *
414      * @param className the class name as String, never null.
415      * @param source the source class, from where to get the classloader.
416      * @return the instantiated object or null, if an error occured.
417      */

418     public static Object JavaDoc loadAndInstantiate(final String JavaDoc className,
419                                             final Class JavaDoc source,
420                                             final Class JavaDoc type) {
421         try {
422             final ClassLoader JavaDoc loader = getClassLoader(source);
423             final Class JavaDoc c = loader.loadClass(className);
424             if (type.isAssignableFrom(c)) {
425                 return c.newInstance();
426             }
427         }
428         catch (Exception JavaDoc e) {
429             return null;
430         }
431         return null;
432     }
433
434
435     public static boolean isJDK14() {
436         final ClassLoader JavaDoc loader = getClassLoader(ObjectUtilities.class);
437         if (loader != null) {
438             try {
439               loader.loadClass("java.util.RandomAccess");
440               return true;
441             }
442             catch (ClassNotFoundException JavaDoc e) {
443               return false;
444             }
445             catch(Exception JavaDoc e) {
446               // do nothing, but do not crash ...
447
}
448         }
449         // OK, the quick and dirty, but secure way failed. Lets try it
450
// using the standard way.
451
try {
452             final String JavaDoc version = System.getProperty
453                     ("java.vm.specification.version");
454             // parse the beast...
455
if (version == null) {
456                 return false;
457             }
458
459             String JavaDoc[] versions = parseVersions(version);
460             String JavaDoc[] target = new String JavaDoc[]{ "1", "4" };
461             return (ArrayUtilities.compareVersionArrays(versions, target) >= 0);
462         }
463         catch(Exception JavaDoc e) {
464             return false;
465         }
466     }
467
468     private static String JavaDoc[] parseVersions (String JavaDoc version)
469     {
470       if (version == null)
471       {
472         return new String JavaDoc[0];
473       }
474
475       final ArrayList JavaDoc versions = new ArrayList JavaDoc();
476       StringTokenizer JavaDoc strtok = new StringTokenizer JavaDoc(version, ".");
477       while (strtok.hasMoreTokens())
478       {
479         versions.add (strtok.nextToken());
480       }
481       return (String JavaDoc[]) versions.toArray(new String JavaDoc[versions.size()]);
482     }
483 }
484
Popular Tags