Java tutorial
/* * JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * --------------------- * ReadOnlyIterator.java * --------------------- * (C)opyright 2003-2008, by Thomas Morgner and Contributors. * * Original Author: Thomas Morgner; * Contributor(s): David Gilbert (for Object Refinery Limited); * * $Id: ResourceBundleSupport.java,v 1.12 2008/12/18 09:57:32 mungady Exp $ * * Changes * ------- * 18-Dec-2008 : Use ResourceBundleWrapper - see JFreeChart patch 1607918 by * Jess Thrysoee (DG); * */ import java.awt.Image; import java.awt.Toolkit; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; import java.net.URLClassLoader; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.TreeSet; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JMenu; import javax.swing.KeyStroke; import sun.rmi.runtime.Log; /** * An utility class to ease up using property-file resource bundles. * <p/> * The class support references within the resource bundle set to minimize the * occurence of duplicate keys. References are given in the format: * <pre> * a.key.name=@referenced.key * </pre> * <p/> * A lookup to a key in an other resource bundle should be written by * <pre> * a.key.name=@@resourcebundle_name@referenced.key * </pre> * * @author Thomas Morgner */ public class ResourceBundleSupport { /** * The resource bundle that will be used for local lookups. */ private ResourceBundle resources; /** * A cache for string values, as looking up the cache is faster than looking * up the value in the bundle. */ private TreeMap cache; /** * The current lookup path when performing non local lookups. This prevents * infinite loops during such lookups. */ private TreeSet lookupPath; /** * The name of the local resource bundle. */ private String resourceBase; /** * The locale for this bundle. */ private Locale locale; /** * Creates a new instance. * * @param locale the locale. * @param baseName the base name of the resource bundle, a fully qualified * class name */ public ResourceBundleSupport(final Locale locale, final String baseName) { this(locale, ResourceBundleWrapper.getBundle(baseName, locale), baseName); } /** * Creates a new instance. * * @param locale the locale for which this resource bundle is * created. * @param resourceBundle the resourcebundle * @param baseName the base name of the resource bundle, a fully * qualified class name */ protected ResourceBundleSupport(final Locale locale, final ResourceBundle resourceBundle, final String baseName) { if (locale == null) { throw new NullPointerException("Locale must not be null"); } if (resourceBundle == null) { throw new NullPointerException("Resources must not be null"); } if (baseName == null) { throw new NullPointerException("BaseName must not be null"); } this.locale = locale; this.resources = resourceBundle; this.resourceBase = baseName; this.cache = new TreeMap(); this.lookupPath = new TreeSet(); } /** * Creates a new instance. * * @param locale the locale for which the resource bundle is * created. * @param resourceBundle the resourcebundle */ public ResourceBundleSupport(final Locale locale, final ResourceBundle resourceBundle) { this(locale, resourceBundle, resourceBundle.toString()); } /** * Creates a new instance. * * @param baseName the base name of the resource bundle, a fully qualified * class name */ public ResourceBundleSupport(final String baseName) { this(Locale.getDefault(), ResourceBundleWrapper.getBundle(baseName), baseName); } /** * Creates a new instance. * * @param resourceBundle the resourcebundle * @param baseName the base name of the resource bundle, a fully * qualified class name */ protected ResourceBundleSupport(final ResourceBundle resourceBundle, final String baseName) { this(Locale.getDefault(), resourceBundle, baseName); } /** * Creates a new instance. * * @param resourceBundle the resourcebundle */ public ResourceBundleSupport(final ResourceBundle resourceBundle) { this(Locale.getDefault(), resourceBundle, resourceBundle.toString()); } /** * The base name of the resource bundle. * * @return the resource bundle's name. */ protected final String getResourceBase() { return this.resourceBase; } /** * Gets a string for the given key from this resource bundle or one of its * parents. If the key is a link, the link is resolved and the referenced * string is returned instead. * * @param key the key for the desired string * @return the string for the given key * @throws NullPointerException if <code>key</code> is <code>null</code> * @throws MissingResourceException if no object for the given key can be * found * @throws ClassCastException if the object found for the given key is * not a string */ public synchronized String getString(final String key) { final String retval = (String) this.cache.get(key); if (retval != null) { return retval; } this.lookupPath.clear(); return internalGetString(key); } /** * Performs the lookup for the given key. If the key points to a link the * link is resolved and that key is looked up instead. * * @param key the key for the string * @return the string for the given key */ protected String internalGetString(final String key) { if (this.lookupPath.contains(key)) { throw new MissingResourceException("InfiniteLoop in resource lookup", getResourceBase(), this.lookupPath.toString()); } final String fromResBundle = this.resources.getString(key); if (fromResBundle.startsWith("@@")) { // global forward ... final int idx = fromResBundle.indexOf('@', 2); if (idx == -1) { throw new MissingResourceException("Invalid format for global lookup key.", getResourceBase(), key); } try { final ResourceBundle res = ResourceBundleWrapper.getBundle(fromResBundle.substring(2, idx)); return res.getString(fromResBundle.substring(idx + 1)); } catch (Exception e) { System.out.println("Error during global lookup:" + e); throw new MissingResourceException("Error during global lookup", getResourceBase(), key); } } else if (fromResBundle.startsWith("@")) { // local forward ... final String newKey = fromResBundle.substring(1); this.lookupPath.add(key); final String retval = internalGetString(newKey); this.cache.put(key, retval); return retval; } else { this.cache.put(key, fromResBundle); return fromResBundle; } } /** * Returns an scaled icon suitable for buttons or menus. * * @param key the name of the resource bundle key * @param large true, if the image should be scaled to 24x24, or false for * 16x16 * @return the icon. */ public Icon getIcon(final String key, final boolean large) { final String name = getString(key); return createIcon(name, true, large); } /** * Returns an unscaled icon. * * @param key the name of the resource bundle key * @return the icon. */ public Icon getIcon(final String key) { final String name = getString(key); return createIcon(name, false, false); } /** * Returns the mnemonic stored at the given resourcebundle key. The mnemonic * should be either the symbolic name of one of the KeyEvent.VK_* constants * (without the 'VK_') or the character for that key. * <p/> * For the enter key, the resource bundle would therefore either contain * "ENTER" or "\n". * <pre> * a.resourcebundle.key=ENTER * an.other.resourcebundle.key=\n * </pre> * * @param key the resourcebundle key * @return the mnemonic */ public Integer getMnemonic(final String key) { final String name = getString(key); return createMnemonic(name); } /** * Returns an optional mnemonic. * * @param key the key. * * @return The mnemonic. */ public Integer getOptionalMnemonic(final String key) { final String name = getString(key); if (name != null && name.length() > 0) { return createMnemonic(name); } return null; } /** * Returns the keystroke stored at the given resourcebundle key. * <p/> * The keystroke will be composed of a simple key press and the plattform's * MenuKeyMask. * <p/> * The keystrokes character key should be either the symbolic name of one of * the KeyEvent.VK_* constants or the character for that key. * <p/> * For the 'A' key, the resource bundle would therefore either contain * "VK_A" or "a". * <pre> * a.resourcebundle.key=VK_A * an.other.resourcebundle.key=a * </pre> * * @param key the resourcebundle key * @return the mnemonic * @see Toolkit#getMenuShortcutKeyMask() */ public KeyStroke getKeyStroke(final String key) { return getKeyStroke(key, getMenuKeyMask()); } /** * Returns an optional key stroke. * * @param key the key. * * @return The key stroke. */ public KeyStroke getOptionalKeyStroke(final String key) { return getOptionalKeyStroke(key, getMenuKeyMask()); } /** * Returns the keystroke stored at the given resourcebundle key. * <p/> * The keystroke will be composed of a simple key press and the given * KeyMask. If the KeyMask is zero, a plain Keystroke is returned. * <p/> * The keystrokes character key should be either the symbolic name of one of * the KeyEvent.VK_* constants or the character for that key. * <p/> * For the 'A' key, the resource bundle would therefore either contain * "VK_A" or "a". * <pre> * a.resourcebundle.key=VK_A * an.other.resourcebundle.key=a * </pre> * * @param key the resourcebundle key. * @param mask the mask. * * @return the mnemonic * @see Toolkit#getMenuShortcutKeyMask() */ public KeyStroke getKeyStroke(final String key, final int mask) { final String name = getString(key); return KeyStroke.getKeyStroke(createMnemonic(name).intValue(), mask); } /** * Returns an optional key stroke. * * @param key the key. * @param mask the mask. * * @return The key stroke. */ public KeyStroke getOptionalKeyStroke(final String key, final int mask) { final String name = getString(key); if (name != null && name.length() > 0) { return KeyStroke.getKeyStroke(createMnemonic(name).intValue(), mask); } return null; } /** * Returns a JMenu created from a resource bundle definition. * <p/> * The menu definition consists of two keys, the name of the menu and the * mnemonic for that menu. Both keys share a common prefix, which is * extended by ".name" for the name of the menu and ".mnemonic" for the * mnemonic. * <p/> * <pre> * # define the file menu * menu.file.name=File * menu.file.mnemonic=F * </pre> * The menu definition above can be used to create the menu by calling * <code>createMenu ("menu.file")</code>. * * @param keyPrefix the common prefix for that menu * @return the created menu */ public JMenu createMenu(final String keyPrefix) { final JMenu retval = new JMenu(); retval.setText(getString(keyPrefix + ".name")); retval.setMnemonic(getMnemonic(keyPrefix + ".mnemonic").intValue()); return retval; } /** * Returns a URL pointing to a resource located in the classpath. The * resource is looked up using the given key. * <p/> * Example: The load a file named 'logo.gif' which is stored in a java * package named 'org.jfree.resources': * <pre> * mainmenu.logo=org/jfree/resources/logo.gif * </pre> * The URL for that file can be queried with: <code>getResource("mainmenu.logo");</code>. * * @param key the key for the resource * @return the resource URL */ public URL getResourceURL(final String key) { final String name = getString(key); final URL in = ObjectUtilities.getResource(name, ResourceBundleSupport.class); if (in == null) { System.out.println("Unable to find file in the class path: " + name + "; key=" + key); } return in; } /** * Attempts to load an image from classpath. If this fails, an empty image * icon is returned. * * @param resourceName the name of the image. The name should be a global * resource name. * @param scale true, if the image should be scaled, false otherwise * @param large true, if the image should be scaled to 24x24, or * false for 16x16 * @return the image icon. */ private ImageIcon createIcon(final String resourceName, final boolean scale, final boolean large) { final URL in = ObjectUtilities.getResource(resourceName, ResourceBundleSupport.class); ; if (in == null) { System.out.println("Unable to find file in the class path: " + resourceName); return new ImageIcon(createTransparentImage(1, 1)); } final Image img = Toolkit.getDefaultToolkit().createImage(in); if (img == null) { System.out.println("Unable to instantiate the image: " + resourceName); return new ImageIcon(createTransparentImage(1, 1)); } if (scale) { if (large) { return new ImageIcon(img.getScaledInstance(24, 24, Image.SCALE_SMOOTH)); } return new ImageIcon(img.getScaledInstance(16, 16, Image.SCALE_SMOOTH)); } return new ImageIcon(img); } /** * Creates the Mnemonic from the given String. The String consists of the * name of the VK constants of the class KeyEvent without VK_*. * * @param keyString the string * @return the mnemonic as integer */ private Integer createMnemonic(final String keyString) { if (keyString == null) { throw new NullPointerException("Key is null."); } if (keyString.length() == 0) { throw new IllegalArgumentException("Key is empty."); } int character = keyString.charAt(0); if (keyString.startsWith("VK_")) { try { final Field f = KeyEvent.class.getField(keyString); final Integer keyCode = (Integer) f.get(null); character = keyCode.intValue(); } catch (Exception nsfe) { // ignore the exception ... } } return new Integer(character); } /** * Returns the plattforms default menu shortcut keymask. * * @return the default key mask. */ private int getMenuKeyMask() { try { return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); } catch (UnsupportedOperationException he) { // headless exception extends UnsupportedOperation exception, // but the HeadlessException is not defined in older JDKs... return InputEvent.CTRL_MASK; } } /** * Creates a transparent image. These can be used for aligning menu items. * * @param width the width. * @param height the height. * @return the created transparent image. */ private BufferedImage createTransparentImage(final int width, final int height) { final BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); final int[] data = img.getRGB(0, 0, width, height, null, 0, width); Arrays.fill(data, 0x00000000); img.setRGB(0, 0, width, height, data, 0, width); return img; } /** * Creates a transparent icon. The Icon can be used for aligning menu * items. * * @param width the width of the new icon * @param height the height of the new icon * @return the created transparent icon. */ public Icon createTransparentIcon(final int width, final int height) { return new ImageIcon(createTransparentImage(width, height)); } /** * Formats the message stored in the resource bundle (using a * MessageFormat). * * @param key the resourcebundle key * @param parameter the parameter for the message * @return the formated string */ public String formatMessage(final String key, final Object parameter) { return formatMessage(key, new Object[] { parameter }); } /** * Formats the message stored in the resource bundle (using a * MessageFormat). * * @param key the resourcebundle key * @param par1 the first parameter for the message * @param par2 the second parameter for the message * @return the formated string */ public String formatMessage(final String key, final Object par1, final Object par2) { return formatMessage(key, new Object[] { par1, par2 }); } /** * Formats the message stored in the resource bundle (using a * MessageFormat). * * @param key the resourcebundle key * @param parameters the parameter collection for the message * @return the formated string */ public String formatMessage(final String key, final Object[] parameters) { final MessageFormat format = new MessageFormat(getString(key)); format.setLocale(getLocale()); return format.format(parameters); } /** * Returns the current locale for this resource bundle. * * @return the locale. */ public Locale getLocale() { return this.locale; } } /* * JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * -------------------------- * ResourceBundleWrapper.java * -------------------------- * (C)opyright 2008, by Jess Thrysoee and Contributors. * * Original Author: Jess Thrysoee; * Contributor(s): David Gilbert (for Object Refinery Limited); * * Changes * ------- * 18-Dec-2008 : Version 1 (JT); * */ /** * Wrapper of ResourceBundle.getBundle() methods. This wrapper is introduced to * avoid a dramatic performance penalty by superfluous resource (and classes * loaded by Class.forName) lookups on web server in applets. * * <pre> * public class AppletC extends javax.swing.JApplet { * public void init() { * ResourceBundleWrapper.removeCodeBase(getCodeBase(), * (URLClassLoader) getClass().getClassLoader()); * ... * </pre> * * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4243379"> * Bug ID: 4243379</a> * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4668479"> * Bug ID: 4668479</a> * * @since 1.0.15 */ class ResourceBundleWrapper { /** * A special class loader with no code base lookup. This field may be * <code>null</code> (the field is only initialised if removeCodeBase() is * called from an applet. */ private static URLClassLoader noCodeBaseClassLoader; /** * Private constructor. */ private ResourceBundleWrapper() { // all methods are static, no need to instantiate } /** * Instantiate a {@link URLClassLoader} for resource lookups where the * codeBase URL is removed. This method is typically called from an * applet's init() method. If this method is never called, the * <code>getBundle()</code> methods map to the standard * {@link ResourceBundle} lookup methods. * * @param codeBase the codeBase URL. * @param urlClassLoader the class loader. */ public static void removeCodeBase(URL codeBase, URLClassLoader urlClassLoader) { List urlsNoBase = new ArrayList(); URL[] urls = urlClassLoader.getURLs(); for (int i = 0; i < urls.length; i++) { if (!urls[i].sameFile(codeBase)) { urlsNoBase.add(urls[i]); } } // substitute the filtered URL list URL[] urlsNoBaseArray = (URL[]) urlsNoBase.toArray(new URL[0]); noCodeBaseClassLoader = URLClassLoader.newInstance(urlsNoBaseArray); } /** * Finds and returns the specified resource bundle. * * @param baseName the base name. * * @return The resource bundle. */ public static final ResourceBundle getBundle(String baseName) { // the noCodeBaseClassLoader is configured by a call to the // removeCodeBase() method, typically in the init() method of an // applet... if (noCodeBaseClassLoader != null) { return ResourceBundle.getBundle(baseName, Locale.getDefault(), noCodeBaseClassLoader); } else { // standard ResourceBundle behaviour return ResourceBundle.getBundle(baseName); } } /** * Finds and returns the specified resource bundle. * * @param baseName the base name. * @param locale the locale. * * @return The resource bundle. */ public static final ResourceBundle getBundle(String baseName, Locale locale) { // the noCodeBaseClassLoader is configured by a call to the // removeCodeBase() method, typically in the init() method of an // applet... if (noCodeBaseClassLoader != null) { return ResourceBundle.getBundle(baseName, locale, noCodeBaseClassLoader); } else { // standard ResourceBundle behaviour return ResourceBundle.getBundle(baseName, locale); } } /** * Maps directly to <code>ResourceBundle.getBundle(baseName, locale, * loader)</code>. * * @param baseName the base name. * @param locale the locale. * @param loader the class loader. * * @return The resource bundle. */ public static ResourceBundle getBundle(String baseName, Locale locale, ClassLoader loader) { return ResourceBundle.getBundle(baseName, locale, loader); } } /* * JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * --------------------- * ObjectUtilitiess.java * --------------------- * (C) Copyright 2003-2005, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * * $Id: ObjectUtilities.java,v 1.21 2008/09/10 09:24:41 mungady Exp $ * * Changes * ------- * 25-Mar-2003 : Version 1 (DG); * 15-Sep-2003 : Fixed bug in clone(List) method (DG); * 25-Nov-2004 : Modified clone(Object) method to fail with objects that * cannot be cloned, added new deepClone(Collection) method. * Renamed ObjectUtils --> ObjectUtilities (DG); * 11-Jan-2005 : Removed deprecated code in preparation for 1.0.0 release (DG); * 18-Aug-2005 : Added casts to suppress compiler warnings, as suggested in * patch 1260622 (DG); * */ /** * A collection of useful static utility methods for handling classes and object * instantiation. * * @author Thomas Morgner */ final class ObjectUtilities { /** * A constant for using the TheadContext as source for the classloader. */ public static final String THREAD_CONTEXT = "ThreadContext"; /** * A constant for using the ClassContext as source for the classloader. */ public static final String CLASS_CONTEXT = "ClassContext"; /** * By default use the thread context. */ private static String classLoaderSource = THREAD_CONTEXT; /** * The custom classloader to be used (if not null). */ private static ClassLoader classLoader; /** * Default constructor - private. */ private ObjectUtilities() { } /** * Returns the internal configuration entry, whether the classloader of * the thread context or the context classloader should be used. * * @return the classloader source, either THREAD_CONTEXT or CLASS_CONTEXT. */ public static String getClassLoaderSource() { return classLoaderSource; } /** * Defines the internal configuration entry, whether the classloader of * the thread context or the context classloader should be used. * <p/> * This setting can only be defined using the API, there is no safe way * to put this into an external configuration file. * * @param classLoaderSource the classloader source, * either THREAD_CONTEXT or CLASS_CONTEXT. */ public static void setClassLoaderSource(final String classLoaderSource) { ObjectUtilities.classLoaderSource = classLoaderSource; } /** * Returns <code>true</code> if the two objects are equal OR both * <code>null</code>. * * @param o1 object 1 (<code>null</code> permitted). * @param o2 object 2 (<code>null</code> permitted). * @return <code>true</code> or <code>false</code>. */ public static boolean equal(final Object o1, final Object o2) { if (o1 == o2) { return true; } if (o1 != null) { return o1.equals(o2); } else { return false; } } /** * Returns a hash code for an object, or zero if the object is * <code>null</code>. * * @param object the object (<code>null</code> permitted). * @return The object's hash code (or zero if the object is * <code>null</code>). */ public static int hashCode(final Object object) { int result = 0; if (object != null) { result = object.hashCode(); } return result; } /** * Returns a clone of the specified object, if it can be cloned, otherwise * throws a CloneNotSupportedException. * * @param object the object to clone (<code>null</code> not permitted). * @return A clone of the specified object. * @throws CloneNotSupportedException if the object cannot be cloned. */ public static Object clone(final Object object) throws CloneNotSupportedException { if (object == null) { throw new IllegalArgumentException("Null 'object' argument."); } try { final Method method = object.getClass().getMethod("clone", (Class[]) null); if (Modifier.isPublic(method.getModifiers())) { return method.invoke(object, (Object[]) null); } } catch (NoSuchMethodException e) { System.out.println("Object without clone() method is impossible."); } catch (IllegalAccessException e) { System.out.println("Object.clone(): unable to call method."); } catch (InvocationTargetException e) { System.out.println("Object without clone() method is impossible."); } throw new CloneNotSupportedException("Failed to clone."); } /** * Returns a new collection containing clones of all the items in the * specified collection. * * @param collection the collection (<code>null</code> not permitted). * @return A new collection containing clones of all the items in the * specified collection. * @throws CloneNotSupportedException if any of the items in the collection * cannot be cloned. */ public static Collection deepClone(final Collection collection) throws CloneNotSupportedException { if (collection == null) { throw new IllegalArgumentException("Null 'collection' argument."); } // all JDK-Collections are cloneable ... // and if the collection is not clonable, then we should throw // a CloneNotSupportedException anyway ... final Collection result = (Collection) ObjectUtilities.clone(collection); result.clear(); final Iterator iterator = collection.iterator(); while (iterator.hasNext()) { final Object item = iterator.next(); if (item != null) { result.add(clone(item)); } else { result.add(null); } } return result; } /** * Returns the classloader, which was responsible for loading the given * class. * * @param c the classloader, either an application class loader or the * boot loader. * @return the classloader, never null. * @throws SecurityException if the SecurityManager does not allow to grab * the context classloader. */ public static ClassLoader getClassLoader(final Class c) { final String localClassLoaderSource; synchronized (ObjectUtilities.class) { if (classLoader != null) { return classLoader; } localClassLoaderSource = classLoaderSource; } if ("ThreadContext".equals(localClassLoaderSource)) { final ClassLoader threadLoader = Thread.currentThread().getContextClassLoader(); if (threadLoader != null) { return threadLoader; } } // Context classloader - do not cache .. final ClassLoader applicationCL = c.getClassLoader(); if (applicationCL == null) { return ClassLoader.getSystemClassLoader(); } else { return applicationCL; } } /** * Returns the resource specified by the <strong>absolute</strong> name. * * @param name the name of the resource * @param c the source class * @return the url of the resource or null, if not found. */ public static URL getResource(final String name, final Class c) { final ClassLoader cl = getClassLoader(c); if (cl == null) { return null; } return cl.getResource(name); } /** * Returns the resource specified by the <strong>relative</strong> name. * * @param name the name of the resource relative to the given class * @param c the source class * @return the url of the resource or null, if not found. */ public static URL getResourceRelative(final String name, final Class c) { final ClassLoader cl = getClassLoader(c); final String cname = convertName(name, c); if (cl == null) { return null; } return cl.getResource(cname); } /** * Transform the class-relative resource name into a global name by * appending it to the classes package name. If the name is already a * global name (the name starts with a "/"), then the name is returned * unchanged. * * @param name the resource name * @param c the class which the resource is relative to * @return the tranformed name. */ private static String convertName(final String name, Class c) { if (name.startsWith("/")) { // strip leading slash.. return name.substring(1); } // we cant work on arrays, so remove them ... while (c.isArray()) { c = c.getComponentType(); } // extract the package ... final String baseName = c.getName(); final int index = baseName.lastIndexOf('.'); if (index == -1) { return name; } final String pkgName = baseName.substring(0, index); return pkgName.replace('.', '/') + "/" + name; } /** * Returns the inputstream for the resource specified by the * <strong>absolute</strong> name. * * @param name the name of the resource * @param context the source class * @return the url of the resource or null, if not found. */ public static InputStream getResourceAsStream(final String name, final Class context) { final URL url = getResource(name, context); if (url == null) { return null; } try { return url.openStream(); } catch (IOException e) { return null; } } /** * Returns the inputstream for the resource specified by the * <strong>relative</strong> name. * * @param name the name of the resource relative to the given class * @param context the source class * @return the url of the resource or null, if not found. */ public static InputStream getResourceRelativeAsStream(final String name, final Class context) { final URL url = getResourceRelative(name, context); if (url == null) { return null; } try { return url.openStream(); } catch (IOException e) { return null; } } /** * Tries to create a new instance of the given class. This is a short cut * for the common bean instantiation code. * * @param className the class name as String, never null. * @param source the source class, from where to get the classloader. * @return the instantiated object or null, if an error occured. */ public static Object loadAndInstantiate(final String className, final Class source) { try { final ClassLoader loader = getClassLoader(source); final Class c = loader.loadClass(className); return c.newInstance(); } catch (Exception e) { return null; } } /** * Tries to create a new instance of the given class. This is a short cut * for the common bean instantiation code. This method is a type-safe method * and will not instantiate the class unless it is an instance of the given * type. * * @param className the class name as String, never null. * @param source the source class, from where to get the classloader. * @param type the type. * @return the instantiated object or null, if an error occurred. */ public static Object loadAndInstantiate(final String className, final Class source, final Class type) { try { final ClassLoader loader = getClassLoader(source); final Class c = loader.loadClass(className); if (type.isAssignableFrom(c)) { return c.newInstance(); } } catch (Exception e) { return null; } return null; } /** * Returns <code>true</code> if this is version 1.4 or later of the * Java runtime. * * @return A boolean. */ public static boolean isJDK14() { return false; } private static String[] parseVersions(String version) { if (version == null) { return new String[0]; } final ArrayList versions = new ArrayList(); final StringTokenizer strtok = new StringTokenizer(version, "."); while (strtok.hasMoreTokens()) { versions.add(strtok.nextToken()); } return (String[]) versions.toArray(new String[versions.size()]); } }