Java Tutorial/Collections/Properties

Материал из Java эксперт
Перейти к: навигация, поиск

Содержание

An utility class to ease up using property-file resource bundles.

/* 
 * 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 
 *
 * @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()]);
     }
 }





A Properties file stored in a JAR can be loaded this way

import java.net.URL;
import java.util.Properties;
import javax.swing.JApplet;
public class Main extends JApplet {
  public static void main(String[] a) throws Exception {
    Properties p = new Properties();
    URL url = ClassLoader.getSystemResource("/com/jexp/config/system.props");
    if (url != null)
      p.load(url.openStream());
  }
}





Convert a Properties list into a map.

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Main {
  public static void main(String args[]) {
    Properties prop = new Properties();
    prop.setProperty("A", "t@h.ru");
    prop.setProperty("B", "k@h.ru");
    prop.setProperty("C", "R@h.ru");
    prop.setProperty("D", "S@h.ru");
    HashMap<String, String> propMap = new HashMap<String, String>((Map) prop);
    Set<Map.Entry<String, String>> propSet;
    propSet = propMap.entrySet();
    System.out.println("Contents of map: ");
    for (Map.Entry<String, String> me : propSet) {
      System.out.print(me.getKey() + ": ");
      System.out.println(me.getValue());
    }
  }
}





Copy a set of properties from one Property to another.

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
/*
   Derby - Class org.apache.derby.iapi.util.PropertyUtil
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to you under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

public class Main {

  /**
   * Copy a set of properties from one Property to another.
   * 
   *
   * @param src_prop  Source set of properties to copy from.
   * @param dest_prop Dest Properties to copy into.
   *
   **/
  public static void copyProperties(Properties src_prop, Properties dest_prop)
  {
      for (Enumeration propertyNames = src_prop.propertyNames();
           propertyNames.hasMoreElements(); )
      {
          Object key = propertyNames.nextElement();
          dest_prop.put(key, src_prop.get(key));
      }
  }
}





Create Properties from String array

/*
    JSPWiki - a JSP-based WikiWiki clone.
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at
       http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.    
 */
import java.security.SecureRandom;
import java.util.Properties;
import java.util.Random;
public class StringUtils
{

  /**
   *  Creates a Properties object based on an array which contains alternatively
   *  a key and a value.  It is useful for generating default mappings.
   *  For example:
   *  <pre>
   *     String[] properties = { "jspwiki.property1", "value1",
   *                             "jspwiki.property2", "value2 };
   *
   *     Properties props = TextUtil.createPropertes( values );
   *
   *     System.out.println( props.getProperty("jspwiki.property1") );
   *  </pre>
   *  would output "value1".
   *
   *  @param values Alternating key and value pairs.
   *  @return Property object
   *  @see java.util.Properties
   *  @throws IllegalArgumentException if the property array is missing
   *          a value for a key.
   *  @since 2.2.
   */
  public static Properties createProperties( String[] values )
      throws IllegalArgumentException
  {
      if( values.length % 2 != 0 )
          throw new IllegalArgumentException( "One value is missing.");
      Properties props = new Properties();
      for( int i = 0; i < values.length; i += 2 )
      {
          props.setProperty( values[i], values[i+1] );
      }
      return props;
  }
}





Gets strong-type-value property from a standard Properties

/*
    JSPWiki - a JSP-based WikiWiki clone.
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at
       http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.    
 */
import java.security.SecureRandom;
import java.util.Properties;
import java.util.Random;
public class StringUtils
{
  /**
   *  Gets an integer-valued property from a standard Properties
   *  list.  If the value does not exist, or is a non-integer, returns defVal.
   *
   *  @since 2.1.48.
   *  @param props The property set to look through
   *  @param key   The key to look for
   *  @param defVal If the property is not found or is a non-integer, returns this value.
   *  @return The property value as an integer (or defVal).
   */
  public static int getIntegerProperty( Properties props,
                                        String key,
                                        int defVal )
  {
      String val = props.getProperty( key );
      return parseIntParameter( val, defVal );
  }
  /**
   *  Gets a boolean property from a standard Properties list.
   *  Returns the default value, in case the key has not been set.
   *  
   *  The possible values for the property are "true"/"false", "yes"/"no", or
   *  "on"/"off".  Any value not recognized is always defined as "false".
   *
   *  @param props   A list of properties to search.
   *  @param key     The property key.
   *  @param defval  The default value to return.
   *
   *  @return True, if the property "key" was set to "true", "on", or "yes".
   *
   *  @since 2.0.11
   */
  public static boolean getBooleanProperty( Properties props,
                                            String key,
                                            boolean defval )
  {
      String val = props.getProperty( key );
      if( val == null ) return defval;
      return isPositive( val );
  }
  /**
   *  Fetches a String property from the set of Properties.  This differs from
   *  Properties.getProperty() in a couple of key respects: First, property value
   *  is trim()med (so no extra whitespace back and front), and well, that"s it.
   *
   *  @param props The Properties to search through
   *  @param key   The property key
   *  @param defval A default value to return, if the property does not exist.
   *  @return The property value.
   *  @since 2.1.151
   */
  public static String getStringProperty( Properties props,
                                          String key,
                                          String defval )
  {
      String val = props.getProperty( key );
      if( val == null ) return defval;
      return val.trim();
  }
  /**
   *  Returns true, if the string "val" denotes a positive string.  Allowed
   *  values are "yes", "on", and "true".  Comparison is case-insignificant.
   *  Null values are safe.
   *
   *  @param val Value to check.
   *  @return True, if val is "true", "on", or "yes"; otherwise false.
   *
   *  @since 2.0.26
   */
  public static boolean isPositive( String val )
  {
      if( val == null ) return false;
      val = val.trim();
      return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("on") ||
               val.equalsIgnoreCase("yes");
  }

  /**
   *  Parses an integer parameter, returning a default value
   *  if the value is null or a non-number.
   *  
   *  @param value The value to parse
   *  @param defvalue A default value in case the value is not a number
   *  @return The parsed value (or defvalue).
   */
  public static int parseIntParameter( String value, int defvalue )
  {
      int val = defvalue;
      try
      {
          val = Integer.parseInt( value.trim() );
      }
      catch( Exception e ) {}
      return val;
  }
}





Getting a key List from Properties

propertyNames() method in Properties class combines the keys in the properties list with the keys in the defaults properties list passed into the constructor.



import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.Properties;
public class MainClass {
  public static void main(String args[]) throws Exception {
    Properties p = new Properties();
    p.load(new FileInputStream("test.txt"));
    Enumeration e = p.propertyNames();
    for (; e.hasMoreElements();) {
      System.out.println(e.nextElement());
    }
  }
}

//File: test.txt
/*
foo:bar
one
two
three=four
five  six seven eight
nine ten

*/



five
two
one
three
nine
foo


Getting and Setting Properties

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class Main {
  public static void main(String[] argv) throws Exception {
    Properties properties = new Properties();
    try {
      properties.load(new FileInputStream("filename.properties"));
    } catch (IOException e) {
    }
    String string = properties.getProperty("a.b");
    properties.setProperty("a.b", "new value");
  }
}





Getting property by String key value

public String getProperty(String key)
public String getProperty(String key, String defaultValue)





Have a multi-line value in a properties file

// add a slash \ to continue the value on the next line.
prop1=line1\
line2\
line3
import java.net.URL;
import java.util.Properties;
public class Main {
  public static void main(String args[]) throws Exception {
    Properties props = new Properties();
    URL url = ClassLoader.getSystemResource("props.properties");
    props.load(url.openStream());
    System.out.println("prop1 :\n " + props.get("prop1"));
    System.out.println("prop2 :\n " + props.get("prop2"));
  }
}





List Properties to a print stream or print writer

import java.io.FileInputStream;
import java.util.Properties;
public class MainClass {
  public static void main(String args[]) throws Exception {
    Properties p = new Properties();
    p.load(new FileInputStream("test.txt"));
    p.list(System.out);
  }
}

//File: colon.txt
/*
foo:bar
one
two
three=four
five  six seven eight
nine ten

*/





Load a properties file in the classpath

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.Properties;
public class Main {
  public static void main(String args[]) throws Exception {
    
    Properties props = new Properties();
    URL url = ClassLoader.getSystemResource("myprops.props");
    props.load(url.openStream());
    System.out.println(props);
  }
}





Load a properties file in the startup directory

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
public class Main {
  public static void main(String args[]) throws Exception {
    Properties props = new Properties();
    props = new java.util.Properties();
    String path = new Main().getClass().getProtectionDomain().getCodeSource().getLocation()
        .toString().substring(6);
    FileInputStream fis = new FileInputStream(new File(path + "\\myprops.props"));
    props.load(fis);
    System.out.println(props);
  }
}





Loading and Saving properties

import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.Properties;
public class MainClass {
  public static void main(String args[]) throws Exception {
    Properties p = new Properties();
    p.load(new FileInputStream("test.txt"));
    Enumeration e = p.propertyNames();
    for (; e.hasMoreElements();) {
      System.out.println(e.nextElement());
    }
  }
}
//File: test.txt
/*
foo:bar
one
two
three=four
five  six seven eight
nine ten
*/



five
two
one
three
nine
foo


Merge Properties Into Map

import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Miscellaneous collection utility methods.
 * Mainly for internal use within the framework.
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @since 1.1.3
 */
abstract class CollectionUtils {
  /**
   * Merge the given Properties instance into the given Map,
   * copying all properties (key-value pairs) over.
   * Uses <code>Properties.propertyNames()</code> to even catch
   * default properties linked into the original Properties instance.
   * @param props the Properties instance to merge (may be <code>null</code>)
   * @param map the target Map to merge the properties into
   */
  public static void mergePropertiesIntoMap(Properties props, Map map) {
    if (map == null) {
      throw new IllegalArgumentException("Map must not be null");
    }
    if (props != null) {
      for (Enumeration en = props.propertyNames(); en.hasMoreElements();) {
        String key = (String) en.nextElement();
        map.put(key, props.getProperty(key));
      }
    }
  }
  /**
   * Return <code>true</code> if the supplied Collection is <code>null</code>
   * or empty. Otherwise, return <code>false</code>.
   * @param collection the Collection to check
   * @return whether the given Collection is empty
   */
  public static boolean isEmpty(Collection collection) {
    return (collection == null || collection.isEmpty());
  }
  /**
   * Return <code>true</code> if the supplied Map is <code>null</code>
   * or empty. Otherwise, return <code>false</code>.
   * @param map the Map to check
   * @return whether the given Map is empty
   */
  public static boolean isEmpty(Map map) {
    return (map == null || map.isEmpty());
  }


  /**
   * Check whether the given Collection contains the given element instance.
   * Enforces the given instance to be present, rather than returning
   * <code>true</code> for an equal element as well.
   * @param collection the Collection to check
   * @param element the element to look for
   * @return <code>true</code> if found, <code>false</code> else
   */
  public static boolean containsInstance(Collection collection, Object element) {
    if (collection != null) {
      for (Iterator it = collection.iterator(); it.hasNext();) {
        Object candidate = it.next();
        if (candidate == element) {
          return true;
        }
      }
    }
    return false;
  }
  /**
   * Return <code>true</code> if any element in "<code>candidates</code>" is
   * contained in "<code>source</code>"; otherwise returns <code>false</code>.
   * @param source the source Collection
   * @param candidates the candidates to search for
   * @return whether any of the candidates has been found
   */
  public static boolean containsAny(Collection source, Collection candidates) {
    if (isEmpty(source) || isEmpty(candidates)) {
      return false;
    }
    for (Iterator it = candidates.iterator(); it.hasNext();) {
      if (source.contains(it.next())) {
        return true;
      }
    }
    return false;
  }
  /**
   * Return the first element in "<code>candidates</code>" that is contained in
   * "<code>source</code>". If no element in "<code>candidates</code>" is present in
   * "<code>source</code>" returns <code>null</code>. Iteration order is
   * {@link Collection} implementation specific.
   * @param source the source Collection
   * @param candidates the candidates to search for
   * @return the first present object, or <code>null</code> if not found
   */
  public static Object findFirstMatch(Collection source, Collection candidates) {
    if (isEmpty(source) || isEmpty(candidates)) {
      return null;
    }
    for (Iterator it = candidates.iterator(); it.hasNext();) {
      Object candidate = it.next();
      if (source.contains(candidate)) {
        return candidate;
      }
    }
    return null;
  }
  /**
   * Find a value of the given type in the given Collection.
   * @param collection the Collection to search
   * @param type the type to look for
   * @return a value of the given type found, or <code>null</code> if none
   * @throws IllegalArgumentException if more than one value of the given type found
   */
  public static Object findValueOfType(Collection collection, Class type) throws IllegalArgumentException {
    if (isEmpty(collection)) {
      return null;
    }
    Class typeToUse = (type != null ? type : Object.class);
    Object value = null;
    for (Iterator it = collection.iterator(); it.hasNext();) {
      Object obj = it.next();
      if (typeToUse.isInstance(obj)) {
        if (value != null) {
          throw new IllegalArgumentException("More than one value of type [" + typeToUse.getName() + "] found");
        }
        value = obj;
      }
    }
    return value;
  }
  /**
   * Determine whether the given Collection only contains a single unique object.
   * @param collection the Collection to check
   * @return <code>true</code> if the collection contains a single reference or
   * multiple references to the same instance, <code>false</code> else
   */
  public static boolean hasUniqueObject(Collection collection) {
    if (isEmpty(collection)) {
      return false;
    }
    boolean hasCandidate = false;
    Object candidate = null;
    for (Iterator it = collection.iterator(); it.hasNext();) {
      Object elem = it.next();
      if (!hasCandidate) {
        hasCandidate = true;
        candidate = elem;
      }
      else if (candidate != elem) {
        return false;
      }
    }
    return true;
  }
}





Property access utility methods

/*
 * Copyright 2004, 2005, 2006 Odysseus Software GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * Property access utility methods.
 *
 * @author Christoph Beck
 */
public class PropertyUtils {
  private static HashMap descriptorCache = new HashMap();
  /**
   * Get map with property descriptors for the specified bean class
   */
  private static Map getPropertyDescriptors(Class clazz) {
    HashMap map = (HashMap)descriptorCache.get(clazz);
    if (map == null) {
      BeanInfo beanInfo = null;
      try {
        beanInfo = Introspector.getBeanInfo(clazz);
      } catch (IntrospectionException e) {
        return Collections.EMPTY_MAP;
      }
      PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
      if (descriptors == null)
         descriptors = new PropertyDescriptor[0];
      map = new HashMap(descriptors.length);
      for (int i = 0; i < descriptors.length; i++)
        map.put(descriptors[i].getName(), descriptors[i]);
      descriptorCache.put(clazz, map);
    }
    return map;
  }
  /**
   * Get property names of the specified bean class
   */
  public static Iterator getPropertyNames(Class clazz) {
    return getPropertyDescriptors(clazz).keySet().iterator();
  }
  /**
   * Get specified property descriptor
   */
  public static PropertyDescriptor getPropertyDescriptor(Class clazz, String property) {
    return (PropertyDescriptor)getPropertyDescriptors(clazz).get(property);
  }
  /**
   * Get specified property value
   */
  public static Object getProperty(Object bean, String property) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(), property);
    if (descriptor == null)
      throw new NoSuchMethodException("Cannot find property " + bean.getClass().getName() + "." + property);
    Method method = descriptor.getReadMethod();
    if (method == null)
      throw new NoSuchMethodException("Cannot find getter for " + bean.getClass().getName() + "." + property);
    return method.invoke(bean, null);
  }
  /**
   * Get specified nested property value
   */
  public static Object getNestedProperty(Object bean, String property) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    if (property.indexOf(".") > 0) {
      String[] path = property.split("\\.");
      for (int i = 0; i < path.length && bean != null; i++) {
        bean = getProperty(bean, path[i]);
      }
      return bean;
    } else {
      return getProperty(bean, property);
    }
  }
  /**
   * Set specified property value
   */
  public static void setProperty(Object bean, String property, Object value) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(), property);
    if (descriptor == null)
      throw new NoSuchMethodException("Cannot find property " + bean.getClass().getName() + "." + property);
    Method method = descriptor.getWriteMethod();
    if (method == null)
      throw new NoSuchMethodException("Cannot find setter for " + bean.getClass().getName() + "." + property);
    method.invoke(bean, new Object[]{ value });
  }
  /**
   * Set nested property given by property path, starting at specified
   * index. Dynamically create beans if necessary. Take care not to
   * leave the bean changed if an exception occurs.
   */
  private static void setNestedPropertyWithCreate(Object bean, String[] path, int start, Object value) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    for (int i = start; i < path.length - 1; i++) {
      Object object = getProperty(bean, path[i]);
      if (object == null) {
        PropertyDescriptor descr =
          getPropertyDescriptor(bean.getClass(), path[i]);
        object = descr.getPropertyType().newInstance();
        setNestedPropertyWithCreate(object, path, i + 1, value);
        setProperty(bean, path[i], object);
        return;
      }
      bean = object;
    }
    setProperty(bean, path[path.length - 1], value);      
  }
  /**
   * Set specified nested property value
   */
  public static void setNestedProperty(Object bean, String property, Object value) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    int lastDot = property.lastIndexOf(".");
    if (lastDot > 0) {
      setNestedPropertyWithCreate(bean, property.split("\\."), 0, value);
    } else {
      setProperty(bean, property, value);     
    }
  }

}





Property Loader

import java.io.InputStream;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;
public class PropertyLoader {
  public static Properties loadProperties(String name, ClassLoader loader) throws Exception {
    if (name.startsWith("/"))
      name = name.substring(1);
    if (name.endsWith(SUFFIX))
      name = name.substring(0, name.length() - SUFFIX.length());
    Properties result = new Properties();
    InputStream in = null;
    if (loader == null)
      loader = ClassLoader.getSystemClassLoader();
    if (LOAD_AS_RESOURCE_BUNDLE) {
      name = name.replace("/", ".");
      ResourceBundle rb = ResourceBundle.getBundle(name, Locale.getDefault(), loader);
      for (Enumeration keys = rb.getKeys(); keys.hasMoreElements();) {
        result.put((String) keys.nextElement(), rb.getString((String) keys.nextElement()));
      }
    } else {
      name = name.replace(".", "/");
      if (!name.endsWith(SUFFIX))
        name = name.concat(SUFFIX);
      in = loader.getResourceAsStream(name);
      if (in != null) {
        result = new Properties();
        result.load(in); // can throw IOException
      }
    }
    in.close();
    return result;
  }
  public static Properties loadProperties(final String name) throws Exception {
    return loadProperties(name, Thread.currentThread().getContextClassLoader());
  }
  private static final boolean LOAD_AS_RESOURCE_BUNDLE = false;
  private static final String SUFFIX = ".properties";
}





Put value to a Property list.

import java.util.Properties;
import java.util.Set;
class PropDemo {
  public static void main(String args[]) {
    Properties capitals = new Properties();
    capitals.put("Illinois", "Springfield");
    capitals.put("Missouri", "Jefferson City");
    capitals.put("Washington", "Olympia");
    capitals.put("California", "Sacramento");
    capitals.put("Indiana", "Indianapolis");
    Set states = capitals.keySet();
    for (Object name : states)
      System.out.println(name + " / " + capitals.getProperty((String) name));
    String str = capitals.getProperty("Florida", "Not Found");
    System.out.println("The capital of Florida is " + str + ".");
  }
}





Read a set of properties from the received input stream, strip off any excess white space that exists in those property values,

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
/*
   Derby - Class org.apache.derby.iapi.util.PropertyUtil
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to you under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

public class Main {
  /** 
   * Read a set of properties from the received input stream, strip
   * off any excess white space that exists in those property values,
   * and then add those newly-read properties to the received
   * Properties object; not explicitly removing the whitespace here can
   * lead to problems.
   *
   * This method exists because of the manner in which the jvm reads
   * properties from file--extra spaces are ignored after a _key_, but
   * if they exist at the _end_ of a property decl line (i.e. as part
   * of a _value_), they are preserved, as outlined in the Java API:
   *
   * "Any whitespace after the key is skipped; if the first non-
   * whitespace character after the key is = or :, then it is ignored
   * and any whitespace characters after it are also skipped. All
   * remaining characters on the line become part of the associated
   * element string."
   *
   * @param iStr An input stream from which the new properties are to be
   *  loaded (should already be initialized).
   * @param prop A set of properties to which the properties from
   *  iStr will be added (should already be initialized).
   * properties loaded from "iStr" (with the extra whitespace (if any)
   *  removed from all values), will be returned via the parameter.
   *
   **/
  public static void loadWithTrimmedValues(InputStream iStr,
    Properties prop) throws IOException {
    if ((iStr == null) || (prop == null)) {
    // shouldn"t happen; just ignore this call and return.
      return;
    }
    // Else, load the properties from the received input stream.
    Properties p = new Properties();
    p.load(iStr);
    // Now, trim off any excess whitespace, if any, and then
    // add the properties from file to the received Properties
    // set.
    for (Enumeration propKeys = p.propertyNames();
      propKeys.hasMoreElements();) {
    // get the value, trim off the whitespace, then store it
    // in the received properties object.
      String tmpKey = (String)propKeys.nextElement();
      String tmpValue = p.getProperty(tmpKey);
      tmpValue = tmpValue.trim();
      prop.put(tmpKey, tmpValue);
    }
    return;
  }
}





Read system property as an integer

public class Main {
  public static void main(String[] args) {
    System.setProperty("app.major.version", "1");
    System.setProperty("app.minor.version", "19");
    Integer major = Integer.getInteger("app.major.version");
    Integer minor = Integer.getInteger("app.minor.version");
    System.out.println("App version = " + major + "." + minor);
  }
}





Returns a Properties object matching the given node

/**
 * EasyBeans
 * Copyright (C) 2006 Bull S.A.S.
 * Contact: easybeans@ow2.org
 *
 * 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id: XMLUtils.java 2049 2007-11-20 14:32:56Z benoitf $
 * --------------------------------------------------------------------------
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
 * Class with some useful methods on XML document.
 */
public final class XMLUtils {
  /**
   * Returns a Properties object matching the given node.
   * @param ns the namespace.
   * @param base the element from where to search.
   * @param name of the element to get.
   * @return the value of this element.
   */
  public static Properties getPropertiesValueElement(final String ns, final Element base, final String name) {
      Properties returnedProperties = new Properties();
      // Get element
      NodeList list = base.getElementsByTagNameNS(ns, name);
      if (list.getLength() == 1) {
          Element element = (Element) list.item(0);
          // Get property element
          NodeList properties = element.getElementsByTagNameNS(ns, "property");
          // If properties is present, analyze them and add them
          if (properties.getLength() > 0) {
              for (int i = 0; i < properties.getLength(); i++) {
                  Element elemProperty = (Element) properties.item(i);
                  String pName = getAttributeValue(elemProperty, "name");
                  String pValue = getAttributeValue(elemProperty, "value");
                  if (pName != null && pValue != null) {
                      returnedProperties.setProperty(pName, pValue);
                  }
              }
          }
      } else if (list.getLength() > 1) {
          throw new IllegalStateException("Element "" + name + "" on "" + base + "" should be unique but there are ""
                  + list.getLength() + "" elements");
      }
      return returnedProperties;
  }
  /**
   * Returns the value of the attribute of the given element.
   * @param base the element from where to search.
   * @param name of the attribute to get.
   * @return the value of this element.
   */
  public static String getAttributeValue(final Element base, final String name) {
      // get attribute of this element...
      NamedNodeMap mapAttributes = base.getAttributes();
      Node node = mapAttributes.getNamedItem(name);
      if (node != null) {
          return node.getNodeValue();
      }
      return null;
  }
}





Setting and Getting Elements

setProperty() method in the Properties class ensures both the key and the value are strings.



public Object setProperty(String key, String value)





Sort Properties when saving

import java.io.FileOutputStream;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
public class Main{
  public static void main(String[] args) throws Exception {
    SortedProperties sp = new SortedProperties();
    sp.put("B", "value B");
    sp.put("C", "value C");
    sp.put("A", "value A");
    sp.put("D", "value D");
    FileOutputStream fos = new FileOutputStream("sp.props");
    sp.store(fos, "sorted props");
  }
}
class SortedProperties extends Properties {
  public Enumeration keys() {
     Enumeration keysEnum = super.keys();
     Vector<String> keyList = new Vector<String>();
     while(keysEnum.hasMoreElements()){
       keyList.add((String)keysEnum.nextElement());
     }
     Collections.sort(keyList);
     return keyList.elements();
  }
  
}





Sorts a property list and turns the sorted list into a string.

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
/*
   Derby - Class org.apache.derby.iapi.util.PropertyUtil
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to you under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

public class Main {
  /**
   * Sorts a property list and turns the sorted list into a string.
   *
   * @param  list  property list to sort
   *
   * @return a string version of the sorted list
   */
 public  static  String  sortProperties( Properties list )
 {
   // stringify them with no indentation
   return sortProperties(list, null);
 }
  /**
   * Sorts property list and print out each key=value pair prepended with 
   * specific indentation.  If indent is null, do not prepend with
   * indentation. 
   *
   * The output string shows up in two styles, style 1 looks like
   * { key1=value1, key2=value2, key3=value3 }
   *
   * style 2 looks like
   *    key1=value1
   *    key2=value2
   *    key3=value3
   * where indent goes between the new line and the keys
   *
   * To get style 1, pass in a null indent
   * To get sytle 2, pass in non-null indent (whatever you want to go before
   * the key value)
   */
  public  static  String  sortProperties( Properties list, String indent )
  {
    int       size = list == null ? 0 : list.size();
    int       count = 0;
    String[]    array = new String[size];
    String      key;
    String      value;
    StringBuffer  buffer;
    // Calculate the number of properties in the property list and
    // build an array of all the property names.
    // We need to go thru the enumeration because Properties has a
    // recursive list of defaults.
    if (list != null)
    {
      for (Enumeration propertyNames = list.propertyNames();
         propertyNames.hasMoreElements(); )
      {
        if (count == size)
        {
          // need to expand the array
          size = size*2;
          String[] expandedArray = new String[size];
          System.arraycopy(array, 0, expandedArray, 0, count);
          array = expandedArray;
        }
        key = (String) propertyNames.nextElement();
        array[ count++ ] = key;
      }
      // now sort the array
      java.util.Arrays.sort(array, 0, count);
    }
    // now stringify the array
    buffer = new StringBuffer();
    if (indent == null)
      buffer.append( "{ " );
    for ( int ictr = 0; ictr < count; ictr++ )
    {
      if ( ictr > 0 && indent == null)
        buffer.append( ", " );
      key = array[ ictr ];
      if (indent != null)
        buffer.append( indent );
      buffer.append( key ); buffer.append( "=" );
      value = list.getProperty( key, "MISSING_VALUE" );
      buffer.append( value );
      if (indent != null)
        buffer.append( "\n" );
    }
    if (indent == null)
      buffer.append( " }" );
    return  buffer.toString();
  }
}





Sorts property list and print out each key=value pair prepended with specific indentation.

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
/*
   Derby - Class org.apache.derby.iapi.util.PropertyUtil
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to you under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

public class Main {

  /**
   * Sorts property list and print out each key=value pair prepended with 
   * specific indentation.  If indent is null, do not prepend with
   * indentation. 
   *
   * The output string shows up in two styles, style 1 looks like
   * { key1=value1, key2=value2, key3=value3 }
   *
   * style 2 looks like
   *    key1=value1
   *    key2=value2
   *    key3=value3
   * where indent goes between the new line and the keys
   *
   * To get style 1, pass in a null indent
   * To get sytle 2, pass in non-null indent (whatever you want to go before
   * the key value)
   */
  public  static  String  sortProperties( Properties list, String indent )
  {
    int       size = list == null ? 0 : list.size();
    int       count = 0;
    String[]    array = new String[size];
    String      key;
    String      value;
    StringBuffer  buffer;
    // Calculate the number of properties in the property list and
    // build an array of all the property names.
    // We need to go thru the enumeration because Properties has a
    // recursive list of defaults.
    if (list != null)
    {
      for (Enumeration propertyNames = list.propertyNames();
         propertyNames.hasMoreElements(); )
      {
        if (count == size)
        {
          // need to expand the array
          size = size*2;
          String[] expandedArray = new String[size];
          System.arraycopy(array, 0, expandedArray, 0, count);
          array = expandedArray;
        }
        key = (String) propertyNames.nextElement();
        array[ count++ ] = key;
      }
      // now sort the array
      java.util.Arrays.sort(array, 0, count);
    }
    // now stringify the array
    buffer = new StringBuffer();
    if (indent == null)
      buffer.append( "{ " );
    for ( int ictr = 0; ictr < count; ictr++ )
    {
      if ( ictr > 0 && indent == null)
        buffer.append( ", " );
      key = array[ ictr ];
      if (indent != null)
        buffer.append( indent );
      buffer.append( key ); buffer.append( "=" );
      value = list.getProperty( key, "MISSING_VALUE" );
      buffer.append( value );
      if (indent != null)
        buffer.append( "\n" );
    }
    if (indent == null)
      buffer.append( " }" );
    return  buffer.toString();
  }
}





Store properties as XML file

import java.io.FileOutputStream;
import java.util.Properties;
public class Main {
  public static void main(String[] args) throws Exception {
    Properties properties = new Properties();
    properties.setProperty("database.type", "mysql");
    properties.setProperty("database.url", "jdbc:mysql://localhost/mydb");
    properties.setProperty("database.username", "root");
    properties.setProperty("database.password", "root");
    FileOutputStream fos = new FileOutputStream("database-configuration.xml");
    properties.storeToXML(fos, "Database Configuration", "UTF-8");
  }
}
 
 
The saved XML file will look like the properties file below:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.ru/dtd/properties.dtd">
  <properties>
    <comment>Database Configuration</comment>
    <entry key="database.password">root</entry>
    <entry key="database.url">jdbc:mysql://localhost/mydb</entry>
    <entry key="database.type">mysql</entry>
    <entry key="database.username">root</entry>
  </properties





The properties iterator iterates over a set of enumerated properties.

/**
 * 
 * JFreeReport : a free Java reporting library
 * 
 *
 * Project Info:  http://reporting.pentaho.org/
 *
 * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
 *
 * 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., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * ------------
 * PropertiesIterator.java
 * ------------
 * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
 */
import java.util.Iterator;
import java.util.Properties;
/**
 * The properties iterator iterates over a set of enumerated properties. The
 * properties are named by an optional prefix plus a number, which is counted up
 * on each iteration: <p/>
 * <ul>
 * <li>prefix_0 </li>
 * <li>prefix_1 </li>
 * <li>prefix_2 </li>
 * <li>... </li>
 * </ul>
 * <p/> The iterator iterates over all subsequent numbered proprties until the
 * number-sequence is finished.
 * 
 * @author Thomas Morgner
 * 
 */
public class PropertiesIterator implements Iterator {
  /**
   * The underlying properties collection.
   */
  private Properties properties;
  /**
   * The property name prefix.
   */
  private String prefix;
  /**
   * An incremental counter.
   */
  private int count;
  /**
   * Creates a new properties iterator without an prefix.
   * 
   * @param properties
   *          the underlying properties collection.
   */
  public PropertiesIterator(final Properties properties) {
    this(properties, null);
  }
  /**
   * Creates a new properties iterator with the given prefix.
   * 
   * @param properties
   *          the underlying properties collection.
   * @param prefix
   *          a prefix for generating property names (null permitted).
   */
  public PropertiesIterator(final Properties properties, final String prefix) {
    if (properties == null) {
      throw new NullPointerException();
    }
    this.properties = properties;
    this.prefix = prefix;
    this.count = 0;
  }
  /**
   * Returns true if there is a property in the underlying collection with a
   * name that matches the name returned by the getNextKey() method.
   * 
   * @return true if there is another property with a name in the correct form.
   */
  public boolean hasNext() {
    return properties.containsKey(getNextKey());
  }
  /**
   * Generates a property name in the form <prefix>
   * &lt;count&gt;.
   * 
   *  The &lt;count&gt; begins at 0,
   *  and is automatically incremented with each call to the next() method.
   * 
   *  @return the next key in the sequence
   * 
   */
  private String getNextKey() {
    if (prefix == null) {
      return String.valueOf(count);
    }
    return prefix + String.valueOf(count);
  }
  /**
   * Returns the property with a name the same as the name generated by the
   * getNextKey() method, or null if there is no such property (that is, then
   * end of the sequence has been reached).
   * 
   * @return the property or null.
   */
  public Object next() {
    final String value = properties.getProperty(getNextKey());
    count++;
    return value;
  }
  /**
   * Always throws UnsupportedOperationException as remove is not implemented
   * for this iterator.
   * 
   * @throws UnsupportedOperationException
   *           as remove is not supported.
   */
  public void remove() {
    throw new UnsupportedOperationException();
  }
}





To read a Properties file via an Applet

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import javax.swing.JApplet;
public class Main extends JApplet{
  public void init(){
    Properties p = new Properties();
    try {
      p.load((new URL(getCodeBase(), "user.props")).openStream());
    } catch (MalformedURLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}





Use a default property list.

import java.util.Properties;
import java.util.Set;
class PropDemoDef {
  public static void main(String args[]) {
    Properties defList = new Properties();
    defList.put("Florida", "Tallahassee");
    defList.put("Wisconsin", "Madison");
    Properties capitals = new Properties(defList);
    capitals.put("Illinois", "Springfield");
    capitals.put("Missouri", "Jefferson City");
    capitals.put("Washington", "Olympia");
    capitals.put("California", "Sacramento");
    capitals.put("Indiana", "Indianapolis");
    Set states = capitals.keySet();
    for (Object name : states)
      System.out.println(name + " / " + capitals.getProperty((String) name));
    String str = capitals.getProperty("Florida");
    System.out.println("The capital of Florida is " + str + ".");
  }
}





Use store() to save the properties

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;
public class MainClass {
  public static void main(String args[]) throws Exception {
    Properties p = new Properties();
    p.load(new FileInputStream("test.txt"));
    p.store(new FileOutputStream("t.txt"),"no comments");
  }
}
//File: test.txt
/*
foo:bar
one
two
three=four
five  six seven eight
nine ten
*/



foo=bar
one=
two=
three=four
five=six seven eight
nine=ten


Use XML with Properties

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.Properties;
public class Main {
  public static void main(String args[]) throws Exception {
    Properties p = new Properties();
    p.put("today", new Date().toString());
    p.put("user", "A");
    FileOutputStream out = new FileOutputStream("user.props");
    p.storeToXML(out, "updated");
    FileInputStream in = new FileInputStream("user.props");
    p.loadFromXML(in);
    p.list(System.out);
  }
}
/*
The XML looks like
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.ru/dtd/properties.dtd">
<properties>
    <comment>your wordings</comment>
    <entry key="user">A</entry>
    <entry key="today">12/12/2009</entry>
</properties>
*/





Using Enumeration to loop through Properties

import java.util.Enumeration;
import java.util.Properties;
public class MainClass {
  public static void main(String[] a) {
    Properties props = System.getProperties();
    Enumeration e = props.propertyNames();
    while (e.hasMoreElements()) {
      String key = (String) e.nextElement();
      System.out.println(key + " -- " + props.getProperty(key));
    }
  }
}



java.runtime.name -- Java(TM) 2 Runtime Environment, Standard Edition
sun.boot.library.path -- C:\Java_Dev\sdk\jdk\jre\bin
java.vm.version -- 1.5.0-b64
java.vm.vendor -- Sun Microsystems Inc.
java.vendor.url -- http://java.sun.ru/


using properties

import java.io.FileInputStream;
import java.util.Properties;
public class PropView {
  public static void main(String args[]) throws Exception {
    Properties properties = System.getProperties();
    properties.list(System.out);
    FileInputStream in = null;
    in = new FileInputStream(args[0]);
    properties.load(in);
    System.getProperties().list(System.out);
    System.out.println("\nValue of local.animal.defined is "
        + Boolean.getBoolean("local.animal.defined"));
    System.out.println("\nValue of local.animal.legcount is "
        + Integer.getInteger("local.animal.legcount"));
  }
}