Mega Code Archive

 
Categories / Java / Development Class
 

XML Properties

// XMLProperties.java // $Id: XMLProperties.java,v 1.5 2000/08/16 21:37:58 ylafon Exp $ // (c) COPYRIGHT MIT, INRIA and Keio, 1999. // Please first read the full copyright statement in file COPYRIGHT.html import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Enumeration; import java.util.Properties; import org.xml.sax.AttributeList; import org.xml.sax.DocumentHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.Parser; import org.xml.sax.SAXException; /**  * The <code>Properties</code> class represents a persistent set of  * properties. The <code>Properties</code> can be saved to a stream or loaded  * from a stream. Each key and its corresponding value in the property list is a  * string.  * <p>  * A property list can contain another property list as its "defaults"; this  * second property list is searched if the property key is not found in the  * original property list. Because Properties inherits from Hashtable, the put  * and putAll methods can be applied to a Properties object. Their use is  * strongly discouraged as they allow the caller to insert entries whose keys or  * values are not Strings. The setProperty method should be used instead. If the  * store or save method is called on a "compromised" Properties object that  * contains a non-String key or value, the call will fail.  * <p>  * This is a special implementation for XML :  *   * <pre>  *    &lt;properties&gt;  *       &lt;key name=&quot;My_key1&quot;&gt;My_Value1&lt;/key&gt;  *       &lt;key name=&quot;My_key2&quot;&gt;My_Value2&lt;/key&gt;  *    &lt;/properties&gt;  * </pre>  *   * @version $Revision: 1.5 $  * @author Philippe Le Hégaret (plh@w3.org)  * @author Benoît Mahé (bmahe@w3.org)  */ public class XMLProperties extends Properties {   public static final String PARSER_P = "com.jclark.xml.sax.Driver";   public boolean debug = false;   class XMLParser implements DocumentHandler {     final int IN_NOTHING = 0;     final int IN_DOCUMENT = 1;     final int IN_KEY = 2;     int state = IN_NOTHING;     String key;     StringBuffer value;     Parser parser;     XMLParser(InputStream in) throws IOException, SAXException {       state = IN_NOTHING;       value = new StringBuffer();       try {         parser = getParser();         parser.setDocumentHandler(this);       } catch (Exception e) {         e.printStackTrace();         throw new SAXException("can't create parser ");       }       parser.parse(new InputSource(in));     }     public void startElement(String name, AttributeList atts) throws SAXException {       if (state == IN_NOTHING) {         if (name.equals("properties")) {           state = IN_DOCUMENT;         } else {           throw new SAXException("attempt to find root properties");         }       } else if (state == IN_DOCUMENT) {         if (name.equals("key")) {           state = IN_KEY;           key = atts.getValue("name");           if (key == null) {             throw new SAXException("no name for key " + atts);           }         } else {           throw new SAXException("attempt to find keys");         }       } else {         throw new SAXException("invalid element " + name);       }     }     public void endElement(String name) throws SAXException {       if (state == IN_KEY) {         setProperty(key, value.toString());         if (debug) {           System.out.print("<key name=\"" + key + "\">");           System.out.println(value.toString() + "</key>\n");         }         state = IN_DOCUMENT;         name = null;         value = new StringBuffer();       } else if (state == IN_DOCUMENT) {         state = IN_NOTHING;       }     }     public void characters(char ch[], int start, int length) throws SAXException {       if (state == IN_KEY) {         compute(ch, start, length);       }     }     public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {       // nothing to do     }     public void startDocument() throws SAXException {       // nothing to do     }     public void endDocument() throws SAXException {       // nothing to do     }     public void processingInstruction(String target, String data) throws SAXException {       // nothing to do     }     public void setDocumentLocator(Locator locator) {       // nothing to do     }     private void compute(char[] ch, int start, int length) {       int st = start;       int len = length - 1;       while (st < length           && ((ch[st] == '\n') || (ch[st] == '\t') || (ch[st] == ' ') || (ch[st] == '\r'))) {         st++;       }       while (len > 0           && ((ch[len] == '\n') || (ch[len] == '\t') || (ch[len] == ' ') || (ch[len] == '\r'))) {         len--;       }       while (st <= len) {         value.append(ch[st]);         st++;       }     }   } // XMLParser   private Class parser_class = null;   /**    * Reads a property list from an input stream.    *     * @param in    *          the input stream.    * @exception IOException    *              if an error occurred when reading from the input stream.    * @since JDK1.0    */   public synchronized void load(InputStream in) throws IOException {     XMLParser p = null;     try {       p = new XMLParser(in);     } catch (SAXException e) {       throw new IOException(e.getMessage());     }   }   /**    * Reads a property list from an input stream. This method try to load    * properties with super.load() if the XMLParser failed. Use this method to    * translate an Property set to an XML Property set.    *     * @param file    *          the properties file.    * @exception IOException    *              if an error occurred when reading from the input stream.    * @since JDK1.0    */   public synchronized void load(File file) throws IOException {     InputStream in = new BufferedInputStream(new FileInputStream(file));     XMLParser p = null;     try {       p = new XMLParser(in);     } catch (SAXException e) {       try {         in = new BufferedInputStream(new FileInputStream(file));         super.load(in);         in.close();       } catch (IOException ex) {         throw new IOException(e.getMessage());       }     }   }   /**    * Calls the <code>store(OutputStream out, String header)</code> method and    * suppresses IOExceptions that were thrown.    *     * @deprecated This method does not throw an IOException if an I/O error    *             occurs while saving the property list. As of JDK 1.2, the    *             preferred way to save a properties list is via the    *             <code>store(OutputStream out,    * String header)</code> method.    *     * @param out    *          an output stream.    * @param header    *          a description of the property list.    * @exception ClassCastException    *              if this <code>Properties</code> object contains any keys or    *              values that are not <code>Strings</code>.    */   public synchronized void save(OutputStream out, String header) {     try {       store(out, header);     } catch (IOException ex) {       ex.printStackTrace();     }   }   /**    * Writes this property list (key and element pairs) in this    * <code>Properties</code> table to the output stream in a format suitable    * for loading into a <code>Properties</code> table using the    * <code>load</code> method.    * <p>    * After the entries have been written, the output stream is flushed. The    * output stream remains open after this method returns.    *     * @param out    *          an output stream.    * @param header    *          a description of the property list.    * @exception ClassCastException    *              if this <code>Properties</code> object contains any keys or    *              values that are not <code>Strings</code>.    */   public synchronized void store(OutputStream out, String header) throws IOException {     PrintWriter wout = new PrintWriter(out);     wout.println("<?xml version='1.0'?>");     if (header != null) {       wout.println("<!--" + header + "-->");     }     wout.print("<properties>");     for (Enumeration e = keys(); e.hasMoreElements();) {       String key = (String) e.nextElement();       String val = (String) get(key);       wout.print("\n <key name=\"" + key + "\">");       wout.print(encode(val));       wout.print("</key>");     }     wout.print("\n</properties>");     wout.flush();   }   protected StringBuffer encode(String string) {     int len = string.length();     StringBuffer buffer = new StringBuffer(len);     char c;     for (int i = 0; i < len; i++) {       switch (c = string.charAt(i)) {       case '&':         buffer.append("&amp;");         break;       case '<':         buffer.append("&lt;");         break;       case '>':         buffer.append("&gt;");         break;       default:         buffer.append(c);       }     }     return buffer;   }   private Class getParserClass() throws ClassNotFoundException {     if (parser_class == null)       parser_class = Class.forName(PARSER_P);     return parser_class;   }   private Parser getParser() {     try {       return (Parser) getParserClass().newInstance();     } catch (Exception ex) {       throw new RuntimeException("Unable to intantiate : " + PARSER_P);     }   }   /**    * Creates an empty property list with no default values.    */   public XMLProperties() {     super();   }   /**    * Creates an empty property list with the specified defaults.    *     * @param defaults    *          the defaults.    */   public XMLProperties(Properties defaults) {     super(defaults);   }   /**    * Creates an empty property list with the specified defaults.    *     * @param parser    *          the XML Parser classname (default is PARSER_P)    * @param defaults    *          the defaults.    */   public XMLProperties(String parser, Properties defaults) {     super(defaults);     try {       parser_class = Class.forName(parser);     } catch (ClassNotFoundException ex) {       System.err.println("Unable to instanciate parser class: " + parser);       System.err.println("Using default parser.");     }   }   public void setDebug(boolean debug) {     this.debug = debug;   } }