home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / sybase / starbuck / java.z / Properties.java < prev    next >
Text File  |  1996-05-03  |  7KB  |  269 lines

  1. /*
  2.  * @(#)Properties.java    1.21 95/12/15 Arthur van Hoff
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package java.util;
  21.  
  22. import java.io.IOException;
  23. import java.io.PrintStream;
  24. import java.io.InputStream;
  25. import java.io.OutputStream;
  26. import java.util.Hashtable;
  27.  
  28. /**
  29.  * Persistent properties class. This class is basically a hashtable 
  30.  * that can be saved/loaded from a stream. If a property is not found,
  31.  * a property list containing defaults is searched. This allows
  32.  * arbitrary nesting.
  33.  *
  34.  * @author Arthur van Hoff
  35.  * @version     1.21, 15 Dec 1995
  36.  */
  37. public
  38. class Properties extends Hashtable {
  39.     protected Properties defaults;
  40.  
  41.     /**
  42.      * Creates an empty property list.
  43.      */
  44.     public Properties() {
  45.     this(null);
  46.     }
  47.  
  48.     /**
  49.      * Creates an empty property list with specified defaults.
  50.      * @param defaults the defaults
  51.      */
  52.     public Properties(Properties defaults) {
  53.     this.defaults = defaults;
  54.     }
  55.  
  56.     /**
  57.      * Loads properties from an InputStream.
  58.      * @param in the input stream
  59.      * @exception IOException Error when reading from input stream.
  60.      */
  61.     public synchronized void load(InputStream in) throws IOException {
  62.     in = Runtime.getRuntime().getLocalizedInputStream(in);
  63.  
  64.     int ch = in.read();
  65.     while (true) {
  66.         switch (ch) {
  67.           case -1:
  68.         return;
  69.  
  70.           case '#':
  71.           case '!':
  72.         do {
  73.             ch = in.read();
  74.         } while ((ch >= 0) && (ch != '\n') && (ch != '\r'));
  75.         continue;
  76.  
  77.           case '\n':
  78.           case '\r':
  79.           case ' ':
  80.           case '\t':
  81.         ch = in.read();
  82.         continue;
  83.         }
  84.  
  85.         // Read the key
  86.         StringBuffer key = new StringBuffer();
  87.         while ((ch >= 0) && (ch != '=') && (ch != ':') && 
  88.            (ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r')) {
  89.         key.append((char)ch);
  90.         ch = in.read();
  91.         }
  92.         while ((ch == ' ') && (ch == '\t')) {
  93.         ch = in.read();
  94.         }
  95.         if ((ch == '=') || (ch == ':')) {
  96.         ch = in.read();
  97.         }
  98.         while ((ch == ' ') && (ch == '\t')) {
  99.         ch = in.read();
  100.         }
  101.  
  102.         // Read the value
  103.         StringBuffer val = new StringBuffer();
  104.         while ((ch >= 0) && (ch != '\n') && (ch != '\r')) {
  105.         if (ch == '\\') {
  106.             switch (ch = in.read()) {
  107.               case '\r':
  108.             if (((ch = in.read()) == '\n') ||
  109.                 (ch == ' ') || (ch == '\t')) {
  110.               // fall thru to '\n' case
  111.             } else continue;
  112.               case '\n': 
  113.             while (((ch = in.read()) == ' ') || (ch == '\t'));
  114.             continue;
  115.               case 't': ch = '\t'; break;
  116.               case 'n': ch = '\n'; break;
  117.               case 'r': ch = '\r'; break;
  118.               case 'u': {
  119.             while ((ch = in.read()) == 'u');
  120.             int d = 0;
  121.               loop:
  122.             for (int i = 0 ; i < 4 ; i++, ch = in.read()) {
  123.                 switch (ch) {
  124.                   case '0': case '1': case '2': case '3': case '4':
  125.                   case '5': case '6': case '7': case '8': case '9':
  126.                 d = (d << 4) + ch - '0';
  127.                 break;
  128.                   case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  129.                 d = (d << 4) + 10 + ch - 'a';
  130.                 break;
  131.                   case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  132.                 d = (d << 4) + 10 + ch - 'A';
  133.                 break;
  134.                   default:
  135.                 break loop;
  136.                 }    
  137.             }
  138.             ch = d;
  139.               }
  140.             }
  141.         }
  142.         val.append((char)ch);
  143.         ch = in.read();
  144.         }
  145.  
  146.         //System.out.println(key + " = '" + val + "'");
  147.         put(key.toString(), val.toString());
  148.     }
  149.     }
  150.  
  151.     /**
  152.      * Save properties to an OutputStream. Use the header as
  153.      * a comment at the top of the file.
  154.      */
  155.     public synchronized void save(OutputStream out, String header) {
  156.     OutputStream localOut = Runtime.getRuntime().getLocalizedOutputStream(out);
  157.     PrintStream prnt = new PrintStream(localOut, false);
  158.     boolean localize = localOut != out;
  159.  
  160.     if (header != null) {
  161.         prnt.write('#');
  162.         prnt.println(header);
  163.     }
  164.     prnt.write('#');
  165.     prnt.println(new Date());
  166.  
  167.     for (Enumeration e = keys() ; e.hasMoreElements() ;) {
  168.         String key = (String)e.nextElement();
  169.         prnt.print(key);
  170.         prnt.write('=');
  171.  
  172.         String val = (String)get(key);
  173.         int len = val.length();
  174.         boolean empty = false;
  175.  
  176.         for (int i = 0 ; i < len ; i++) {
  177.         int ch = val.charAt(i);
  178.  
  179.         switch (ch) {
  180.           case '\\': prnt.write('\\'); prnt.write('\\'); break;
  181.           case '\t': prnt.write('\\'); prnt.write('t'); break;
  182.           case '\n': prnt.write('\\'); prnt.write('n'); break;
  183.           case '\r': prnt.write('\\'); prnt.write('r'); break;
  184.  
  185.           default:
  186.             if ((ch < ' ') || (ch >= 127) || (empty && (ch == ' '))) {
  187.             if ((ch > 255) && localize) {
  188.                 prnt.write(ch);
  189.             } else {
  190.                 prnt.write('\\');
  191.                 prnt.write('u');
  192.                 prnt.write((ch >> 12) & 0xF);
  193.                 prnt.write((ch >>  8) & 0xF);
  194.                 prnt.write((ch >>  4) & 0xF);
  195.                 prnt.write((ch >>  0) & 0xF);
  196.             }
  197.             } else {
  198.             prnt.write(ch);
  199.             }
  200.         }
  201.         empty = false;
  202.         }
  203.         prnt.write('\n');
  204.     }
  205.     }
  206.  
  207.     /**
  208.      * Gets a property with the specified key. If the key is not 
  209.      * found in this property list, tries the defaults. This method 
  210.      * returns null if the property is not found.
  211.      * @param key the hashtable key
  212.      */
  213.     public String getProperty(String key) {
  214.     String val = (String)super.get(key);
  215.     return ((val == null) && (defaults != null)) ? defaults.getProperty(key) : val;
  216.     }
  217.  
  218.     /**
  219.      * Gets a property with the specified key and default. If the 
  220.      * key is not found in this property list, tries the defaults. 
  221.      * This method returns defaultValue if the property is not found.
  222.      */
  223.     public String getProperty(String key, String defaultValue) {
  224.     String val = getProperty(key);
  225.     return (val == null) ? defaultValue : val;
  226.     }
  227.  
  228.     /**
  229.      * Enumerates all the keys.
  230.      */
  231.     public Enumeration propertyNames() {
  232.     Hashtable h = new Hashtable();
  233.     enumerate(h);
  234.     return h.keys();
  235.     }
  236.  
  237.     /**
  238.      * List properties, for debugging
  239.      */
  240.     public void list(PrintStream out) {
  241.     out.println("-- listing properties --");
  242.     Hashtable h = new Hashtable();
  243.     enumerate(h);
  244.     for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
  245.         String key = (String)e.nextElement();
  246.         String val = (String)h.get(key);
  247.         if (val.length() > 40) {
  248.         val = val.substring(0, 37) + "...";
  249.         }
  250.         out.println(key + "=" + val);
  251.     }
  252.     
  253.     }
  254.     
  255.     /**
  256.      * Enumerates all key/value pairs in the specified hastable.
  257.      * @param h the hashtable
  258.      */
  259.     private synchronized void enumerate(Hashtable h) {
  260.     if (defaults != null) {
  261.         defaults.enumerate(h);
  262.     }
  263.     for (Enumeration e = keys() ; e.hasMoreElements() ;) {
  264.         String key = (String)e.nextElement();
  265.         h.put(key, get(key));
  266.     }
  267.     }
  268. }
  269.