home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / Properties.java < prev    next >
Text File  |  1997-05-20  |  11KB  |  364 lines

  1. /*
  2.  * @(#)Properties.java    1.29 97/01/28
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  * 
  21.  */
  22.  
  23. package java.util;
  24.  
  25. import java.io.IOException;
  26. import java.io.PrintStream;
  27. import java.io.PrintWriter;
  28. import java.io.InputStream;
  29. import java.io.OutputStream;
  30. import java.util.Hashtable;
  31.  
  32. /**
  33.  * The <code>Properties</code> class represents a persistent set of 
  34.  * properties. The <code>Properties</code> can be saved to a stream 
  35.  * or loaded from a stream. Each key and its corresponding value in 
  36.  * the property list is a string. 
  37.  * <p>
  38.  * A property list can contain another property list as its 
  39.  * "defaults"; this second property list is searched if 
  40.  * the property key is not found in the original property list. 
  41.  *
  42.  * @author  Arthur van Hoff
  43.  * @version 1.29, 01/28/97
  44.  * @since   JDK1.0
  45.  */
  46. public
  47. class Properties extends Hashtable {
  48.     /**
  49.      * A property list that contains default values for any keys not 
  50.      * found in this property list. 
  51.      *
  52.      * @since   JDK1.0
  53.      */
  54.     protected Properties defaults;
  55.  
  56.     /**
  57.      * Creates an empty property list with no default values. 
  58.      *
  59.      * @since   JDK1.0
  60.      */
  61.     public Properties() {
  62.     this(null);
  63.     }
  64.  
  65.     /**
  66.      * Creates an empty property list with the specified defaults. 
  67.      *
  68.      * @param   defaults   the defaults.
  69.      * @since   JDK1.0
  70.      */
  71.     public Properties(Properties defaults) {
  72.     this.defaults = defaults;
  73.     }
  74.  
  75.     /**
  76.      * Reads a property list from an input stream. 
  77.      *
  78.      * @param      in   the input stream.
  79.      * @exception  IOException  if an error occurred when reading from the
  80.      *               input stream.
  81.      * @since   JDK1.0
  82.      */
  83.     public synchronized void load(InputStream in) throws IOException {
  84.     in = Runtime.getRuntime().getLocalizedInputStream(in);
  85.  
  86.     int ch = in.read();
  87.     while (true) {
  88.         switch (ch) {
  89.           case -1:
  90.         return;
  91.  
  92.           case '#':
  93.           case '!':
  94.         do {
  95.             ch = in.read();
  96.         } while ((ch >= 0) && (ch != '\n') && (ch != '\r'));
  97.         continue;
  98.  
  99.           case '\n':
  100.           case '\r':
  101.           case ' ':
  102.           case '\t':
  103.         ch = in.read();
  104.         continue;
  105.         }
  106.  
  107.         // Read the key
  108.         StringBuffer key = new StringBuffer();
  109.         while ((ch >= 0) && (ch != '=') && (ch != ':') && 
  110.            (ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r')) {
  111.         key.append((char)ch);
  112.         ch = in.read();
  113.         }
  114.         while ((ch == ' ') || (ch == '\t')) {
  115.         ch = in.read();
  116.         }
  117.         if ((ch == '=') || (ch == ':')) {
  118.         ch = in.read();
  119.         }
  120.         while ((ch == ' ') || (ch == '\t')) {
  121.         ch = in.read();
  122.         }
  123.  
  124.         // Read the value
  125.         StringBuffer val = new StringBuffer();
  126.         while ((ch >= 0) && (ch != '\n') && (ch != '\r')) {
  127.         int next = 0;
  128.         if (ch == '\\') {
  129.             switch (ch = in.read()) {
  130.               case '\r':
  131.             if (((ch = in.read()) == '\n') ||
  132.                 (ch == ' ') || (ch == '\t')) {
  133.               // fall thru to '\n' case
  134.             } else continue;
  135.               case '\n': 
  136.             while (((ch = in.read()) == ' ') || (ch == '\t'));
  137.             continue;
  138.               case 't': ch = '\t'; next = in.read(); break;
  139.               case 'n': ch = '\n'; next = in.read(); break;
  140.               case 'r': ch = '\r'; next = in.read(); break;
  141.               case 'u': {
  142.             while ((ch = in.read()) == 'u');
  143.             int d = 0;
  144.               loop:
  145.             for (int i = 0 ; i < 4 ; i++) {
  146.                 next = in.read();
  147.                 switch (ch) {
  148.                   case '0': case '1': case '2': case '3': case '4':
  149.                   case '5': case '6': case '7': case '8': case '9':
  150.                 d = (d << 4) + ch - '0';
  151.                 break;
  152.                   case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  153.                 d = (d << 4) + 10 + ch - 'a';
  154.                 break;
  155.                   case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  156.                 d = (d << 4) + 10 + ch - 'A';
  157.                 break;
  158.                   default:
  159.                 break loop;
  160.                 }    
  161.                 ch = next;
  162.             }
  163.             ch = d;
  164.             break;
  165.               }
  166.               default: next = in.read(); break;
  167.             }
  168.         } else {
  169.             next = in.read();
  170.         }
  171.         val.append((char)ch);
  172.         ch = next;
  173.         }
  174.  
  175.         //System.out.println(key + " = '" + val + "'");
  176.         put(key.toString(), val.toString());
  177.     }
  178.     }
  179.  
  180.     /**
  181.      * Stores this property list to the specified output stream. The 
  182.      * string header is printed as a comment at the beginning of the stream.
  183.      *
  184.      * @param   out      an output stream.
  185.      * @param   header   a description of the property list.
  186.      * @since   JDK1.0
  187.      */
  188.     public synchronized void save(OutputStream out, String header) {
  189.     OutputStream localOut = Runtime.getRuntime().getLocalizedOutputStream(out);
  190.     PrintStream prnt = new PrintStream(localOut, false);
  191.     boolean localize = localOut != out;
  192.  
  193.     if (header != null) {
  194.         prnt.write('#');
  195.         prnt.println(header);
  196.     }
  197.     prnt.write('#');
  198.     prnt.println(new Date());
  199.  
  200.     for (Enumeration e = keys() ; e.hasMoreElements() ;) {
  201.         String key = (String)e.nextElement();
  202.         prnt.print(key);
  203.         prnt.write('=');
  204.  
  205.         String val = (String)get(key);
  206.         int len = val.length();
  207.         boolean empty = false;
  208.  
  209.         for (int i = 0 ; i < len ; i++) {
  210.         int ch = val.charAt(i);
  211.  
  212.         switch (ch) {
  213.           case '\\': prnt.write('\\'); prnt.write('\\'); break;
  214.           case '\t': prnt.write('\\'); prnt.write('t'); break;
  215.           case '\n': prnt.write('\\'); prnt.write('n'); break;
  216.           case '\r': prnt.write('\\'); prnt.write('r'); break;
  217.  
  218.           default:
  219.             if ((ch < ' ') || (ch >= 127) || (empty && (ch == ' '))) {
  220.             if ((ch > 255) && localize) {
  221.                 prnt.write(ch);
  222.             } else {
  223.                 prnt.write('\\');
  224.                 prnt.write('u');
  225.                 prnt.write(toHex((ch >> 12) & 0xF));
  226.                 prnt.write(toHex((ch >>  8) & 0xF));
  227.                 prnt.write(toHex((ch >>  4) & 0xF));
  228.                 prnt.write(toHex((ch >>  0) & 0xF));
  229.             }
  230.             } else {
  231.             prnt.write(ch);
  232.             }
  233.         }
  234.         empty = false;
  235.         }
  236.         prnt.write('\n');
  237.     }
  238.     }
  239.  
  240.     /**
  241.      * Searches for the property with the specified key in this property list.
  242.      * If the key is not found in this property list, the default property list,
  243.      * and its defaults, recursively, are then checked. The method returns
  244.      * <code>null</code> if the property is not found.
  245.      *
  246.      * @param   key   the property key.
  247.      * @return  the value in this property list with the specified key value.
  248.      * @see     java.util.Properties#defaults
  249.      * @since   JDK1.0
  250.      */
  251.     public String getProperty(String key) {
  252.     String val = (String)super.get(key);
  253.     return ((val == null) && (defaults != null)) ? defaults.getProperty(key) : val;
  254.     }
  255.  
  256.     /**
  257.      * Searches for the property with the specified key in this property list.
  258.      * If the key is not found in this property list, the default property list,
  259.      * and its defaults, recursively, are then checked. The method returns the
  260.      * default value argument if the property is not found.
  261.      *
  262.      * @param   key            the hashtable key.
  263.      * @param   defaultValue   a default value.
  264.      *
  265.      * @return  the value in this property list with the specified key value.
  266.      * @see     java.util.Properties#defaults
  267.      * @since   JDK1.0
  268.      */
  269.     public String getProperty(String key, String defaultValue) {
  270.     String val = getProperty(key);
  271.     return (val == null) ? defaultValue : val;
  272.     }
  273.  
  274.     /**
  275.      * Returns an enumeration of all the keys in this property list, including
  276.      * the keys in the default property list.
  277.      *
  278.      * @return  an enumeration of all the keys in this property list, including
  279.      *          the keys in the default property list.
  280.      * @see     java.util.Enumeration
  281.      * @see     java.util.Properties#defaults
  282.      * @since   JDK1.0
  283.      */
  284.     public Enumeration propertyNames() {
  285.     Hashtable h = new Hashtable();
  286.     enumerate(h);
  287.     return h.keys();
  288.     }
  289.  
  290.     /**
  291.      * Prints this property list out to the specified output stream. 
  292.      * This method is useful for debugging. 
  293.      *
  294.      * @param   out   an output stream.
  295.      * @since   JDK1.0
  296.      */
  297.     public void list(PrintStream out) {
  298.     out.println("-- listing properties --");
  299.     Hashtable h = new Hashtable();
  300.     enumerate(h);
  301.     for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
  302.         String key = (String)e.nextElement();
  303.         String val = (String)h.get(key);
  304.         if (val.length() > 40) {
  305.         val = val.substring(0, 37) + "...";
  306.         }
  307.         out.println(key + "=" + val);
  308.     }
  309.     }
  310.  
  311.     /**
  312.      * Prints this property list out to the specified output stream. 
  313.      * This method is useful for debugging. 
  314.      *
  315.      * @param   out   an output stream.
  316.      * @since   JDK1.1
  317.      */
  318.     /*
  319.      * Rather than use an anonymous inner class to share common code, this
  320.      * method is duplicated in order to ensure that a non-1.1 compiler can
  321.      * compile this file.
  322.      */
  323.     public void list(PrintWriter out) {
  324.     out.println("-- listing properties --");
  325.     Hashtable h = new Hashtable();
  326.     enumerate(h);
  327.     for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
  328.         String key = (String)e.nextElement();
  329.         String val = (String)h.get(key);
  330.         if (val.length() > 40) {
  331.         val = val.substring(0, 37) + "...";
  332.         }
  333.         out.println(key + "=" + val);
  334.     }
  335.     }
  336.  
  337.     /**
  338.      * Enumerates all key/value pairs in the specified hastable.
  339.      * @param h the hashtable
  340.      */
  341.     private synchronized void enumerate(Hashtable h) {
  342.     if (defaults != null) {
  343.         defaults.enumerate(h);
  344.     }
  345.     for (Enumeration e = keys() ; e.hasMoreElements() ;) {
  346.         String key = (String)e.nextElement();
  347.         h.put(key, get(key));
  348.     }
  349.     }
  350.  
  351.     /**
  352.      * Convert a nibble to a hex character
  353.      * @param    nibble    the nibble to convert.
  354.      */
  355.     private static char toHex(int nibble) {
  356.     return hexDigit[(nibble & 0xF)];
  357.     }
  358.  
  359.     /** A table of hex digits */
  360.     private static char[] hexDigit = {
  361.     '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
  362.     };
  363. }
  364.