/[classpath]/classpath/java/util/Properties.java
ViewVC logotype

Diff of /classpath/java/util/Properties.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.26.2.3 by gnu_andrew, Tue Aug 2 20:12:30 2005 UTC revision 1.26.2.4 by gnu_andrew, Wed Nov 2 00:43:37 2005 UTC
# Line 47  import java.io.OutputStreamWriter; Line 47  import java.io.OutputStreamWriter;
47  import java.io.PrintStream;  import java.io.PrintStream;
48  import java.io.PrintWriter;  import java.io.PrintWriter;
49    
50    import javax.xml.parsers.ParserConfigurationException;
51    import javax.xml.parsers.SAXParser;
52    import javax.xml.parsers.SAXParserFactory;
53    
54    import org.xml.sax.Attributes;
55    import org.xml.sax.InputSource;
56    import org.xml.sax.SAXException;
57    import org.xml.sax.XMLReader;
58    import org.xml.sax.ext.DefaultHandler2;
59    
60    import org.w3c.dom.Document;
61    import org.w3c.dom.DocumentType;
62    import org.w3c.dom.DOMImplementation;
63    import org.w3c.dom.Element;
64    import org.w3c.dom.bootstrap.DOMImplementationRegistry;
65    import org.w3c.dom.ls.DOMImplementationLS;
66    import org.w3c.dom.ls.LSOutput;
67    import org.w3c.dom.ls.LSSerializer;
68    
69  /**  /**
70   * A set of persistent properties, which can be saved or loaded from a stream.   * A set of persistent properties, which can be saved or loaded from a stream.
71   * A property list may also contain defaults, searched if the main list   * A property list may also contain defaults, searched if the main list
# Line 579  label   = Name:\\u0020</pre> Line 598  label   = Name:\\u0020</pre>
598            head = key;            head = key;
599        }        }
600    }    }
601    
602      /**
603       * <p>
604       * Encodes the properties as an XML file using the UTF-8 encoding.
605       * The format of the XML file matches the DTD
606       * <a href="http://java.sun.com/dtd/properties.dtd">
607       * http://java.sun.com/dtd/properties.dtd</a>.
608       * </p>
609       * <p>
610       * Invoking this method provides the same behaviour as invoking
611       * <code>storeToXML(os, comment, "UTF-8")</code>.
612       * </p>
613       *
614       * @param os the stream to output to.
615       * @param comment a comment to include at the top of the XML file, or
616       *                <code>null</code> if one is not required.
617       * @throws IOException if the serialization fails.
618       * @throws NullPointerException if <code>os</code> is null.
619       * @since 1.5
620       */
621      public void storeToXML(OutputStream os, String comment)
622        throws IOException
623      {
624        storeToXML(os, comment, "UTF-8");
625      }
626    
627      /**
628       * <p>
629       * Encodes the properties as an XML file using the supplied encoding.
630       * The format of the XML file matches the DTD
631       * <a href="http://java.sun.com/dtd/properties.dtd">
632       * http://java.sun.com/dtd/properties.dtd</a>.
633       * </p>
634       *
635       * @param os the stream to output to.
636       * @param comment a comment to include at the top of the XML file, or
637       *                <code>null</code> if one is not required.
638       * @param encoding the encoding to use for the XML output.
639       * @throws IOException if the serialization fails.
640       * @throws NullPointerException if <code>os</code> or <code>encoding</code>
641       *                              is null.
642       * @since 1.5
643       */
644      public void storeToXML(OutputStream os, String comment, String encoding)
645        throws IOException
646      {
647        if (os == null)
648          throw new NullPointerException("Null output stream supplied.");
649        if (encoding == null)
650          throw new NullPointerException("Null encoding supplied.");
651        try
652          {
653            DOMImplementationRegistry registry =
654              DOMImplementationRegistry.newInstance();
655            DOMImplementation domImpl = registry.getDOMImplementation("LS 3.0");
656            DocumentType doctype =
657              domImpl.createDocumentType("properties", null,
658                                         "http://java.sun.com/dtd/properties.dtd");
659            Document doc = domImpl.createDocument(null, "properties", doctype);
660            Element root = doc.getDocumentElement();
661            if (comment != null)
662              {
663                Element commentElement = doc.createElement("comment");
664                commentElement.appendChild(doc.createTextNode(comment));
665                root.appendChild(commentElement);
666              }
667            Iterator iterator = entrySet().iterator();
668            while (iterator.hasNext())
669              {
670                Map.Entry entry = (Map.Entry) iterator.next();
671                Element entryElement = doc.createElement("entry");
672                entryElement.setAttribute("key", (String) entry.getKey());
673                entryElement.appendChild(doc.createTextNode((String)
674                                                            entry.getValue()));
675                root.appendChild(entryElement);
676              }
677            DOMImplementationLS loadAndSave = (DOMImplementationLS) domImpl;
678            LSSerializer serializer = loadAndSave.createLSSerializer();
679            LSOutput output = loadAndSave.createLSOutput();
680            output.setByteStream(os);
681            output.setEncoding(encoding);
682            serializer.write(doc, output);
683          }
684        catch (ClassNotFoundException e)
685          {
686            throw (IOException)
687              new IOException("The XML classes could not be found.").initCause(e);
688          }
689        catch (InstantiationException e)
690          {
691            throw (IOException)
692              new IOException("The XML classes could not be instantiated.")
693              .initCause(e);
694          }
695        catch (IllegalAccessException e)
696          {
697            throw (IOException)
698              new IOException("The XML classes could not be accessed.")
699              .initCause(e);
700          }
701      }
702    
703      /**
704       * <p>
705       * Decodes the contents of the supplied <code>InputStream</code> as
706       * an XML file, which represents a set of properties.  The format of
707       * the XML file must match the DTD
708       * <a href="http://java.sun.com/dtd/properties.dtd">
709       * http://java.sun.com/dtd/properties.dtd</a>.
710       * </p>
711       *
712       * @param in the input stream from which to receive the XML data.
713       * @throws IOException if an I/O error occurs in reading the input data.
714       * @throws InvalidPropertiesFormatException if the input data does not
715       *                                          constitute an XML properties
716       *                                          file.
717       * @throws NullPointerException if <code>in</code> is null.
718       * @since 1.5
719       */
720      public void loadFromXML(InputStream in)
721        throws IOException, InvalidPropertiesFormatException
722      {
723        if (in == null)
724          throw new NullPointerException("Null input stream supplied.");
725        try
726          {
727            SAXParserFactory factory = SAXParserFactory.newInstance();
728            factory.setValidating(false); /* Don't use the URI */
729            XMLReader parser = factory.newSAXParser().getXMLReader();
730            PropertiesHandler handler = new PropertiesHandler();
731            parser.setContentHandler(handler);
732            parser.setProperty("http://xml.org/sax/properties/lexical-handler",
733                               handler);
734            parser.parse(new InputSource(in));
735          }
736        catch (SAXException e)
737          {
738            throw (InvalidPropertiesFormatException)
739              new InvalidPropertiesFormatException("Error in parsing XML.").
740              initCause(e);
741          }
742        catch (ParserConfigurationException e)
743          {
744            throw (IOException)
745              new IOException("An XML parser could not be found.").
746              initCause(e);
747          }
748      }
749    
750      /**
751       * This class deals with the parsing of XML using
752       * <a href="http://java.sun.com/dtd/properties.dtd">
753       * http://java.sun.com/dtd/properties.dtd</a>.
754       *  
755       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
756       * @since 1.5
757       */
758      private class PropertiesHandler
759        extends DefaultHandler2
760      {
761        
762        /**
763         * The current key.
764         */
765        private String key;
766        
767        /**
768         * The current value.
769         */
770        private String value;
771    
772        /**
773         * A flag to check whether a valid DTD declaration has been seen.
774         */
775        private boolean dtdDeclSeen;
776    
777        /**
778         * Constructs a new Properties handler.
779         */
780        public PropertiesHandler()
781        {
782          key = null;
783          value = null;
784          dtdDeclSeen = false;
785        }
786    
787        /**
788         * <p>
789         * Captures the start of the DTD declarations, if they exist.
790         * A valid properties file must declare the following doctype:
791         * </p>
792         * <p>
793         * <code>!DOCTYPE properties SYSTEM
794         * "http://java.sun.com/dtd/properties.dtd"</code>
795         * </p>
796         *
797         * @param name the name of the document type.
798         * @param publicId the public identifier that was declared, or
799         *                 null if there wasn't one.
800         * @param systemId the system identifier that was declared, or
801         *                 null if there wasn't one.
802         * @throws SAXException if some error occurs in parsing.
803         */
804        public void startDTD(String name, String publicId, String systemId)
805          throws SAXException
806        {
807          if (name.equals("properties") &&
808              publicId == null &&
809              systemId.equals("http://java.sun.com/dtd/properties.dtd"))
810            {
811              dtdDeclSeen = true;
812            }
813          else
814            throw new SAXException("Invalid DTD declaration: " + name);
815        }
816    
817        /**
818         * Captures the start of an XML element.
819         *
820         * @param uri the namespace URI.
821         * @param localName the local name of the element inside the namespace.
822         * @param qName the local name qualified with the namespace URI.
823         * @param attributes the attributes of this element.
824         * @throws SAXException if some error occurs in parsing.
825         */
826        public void startElement(String uri, String localName,
827                                 String qName, Attributes attributes)
828          throws SAXException
829        {
830          if (qName.equals("entry"))
831            {
832              int index = attributes.getIndex("key");
833              if (index != -1)
834                key = attributes.getValue(index);
835            }
836          else if (qName.equals("comment") || qName.equals("properties"))
837            {
838              /* Ignore it */
839            }
840          else
841            throw new SAXException("Invalid tag: " + qName);
842        }
843        
844        /**
845         * Captures characters within an XML element.
846         *
847         * @param ch the array of characters.
848         * @param start the start index of the characters to use.
849         * @param length the number of characters to use from the start index on.
850         * @throws SAXException if some error occurs in parsing.
851         */
852        public void characters(char[] ch, int start, int length)
853          throws SAXException
854        {
855          if (key != null)
856            value = new String(ch,start,length);
857        }
858        
859        /**
860         * Captures the end of an XML element.
861         *
862         * @param uri the namespace URI.
863         * @param localName the local name of the element inside the namespace.
864         * @param qName the local name qualified with the namespace URI.
865         * @throws SAXException if some error occurs in parsing.
866         */
867        public void endElement(String uri, String localName,
868                               String qName)
869          throws SAXException
870        {
871          if (qName.equals("entry"))
872            {
873              if (value == null)
874                value = "";
875              setProperty(key, value);
876              key = null;
877              value = null;
878            }
879        }
880    
881        /**
882         * Captures the end of the XML document.  If a DTD declaration has
883         * not been seen, the document is erroneous and an exception is thrown.
884         *
885         * @throws SAXException if the correct DTD declaration didn't appear.
886         */
887        public void endDocument()
888          throws SAXException
889        {
890          if (!dtdDeclSeen)
891            throw new SAXException("No appropriate DTD declaration was seen.");
892        }
893    
894      } // class PropertiesHandler
895    
896  } // class Properties  } // class Properties

Legend:
Removed from v.1.26.2.3  
changed lines
  Added in v.1.26.2.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26