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; |
import org.w3c.dom.Document; |
61 |
import org.w3c.dom.DocumentType; |
import org.w3c.dom.DocumentType; |
62 |
import org.w3c.dom.DOMImplementation; |
import org.w3c.dom.DOMImplementation; |
614 |
* @param comment a comment to include at the top of the XML file, or |
* @param comment a comment to include at the top of the XML file, or |
615 |
* <code>null</code> if one is not required. |
* <code>null</code> if one is not required. |
616 |
* @throws IOException if the serialization fails. |
* @throws IOException if the serialization fails. |
617 |
|
* @throws NullPointerException if <code>os</code> is null. |
618 |
* @since 1.5 |
* @since 1.5 |
619 |
*/ |
*/ |
620 |
public void storeToXML(OutputStream os, String comment) |
public void storeToXML(OutputStream os, String comment) |
636 |
* <code>null</code> if one is not required. |
* <code>null</code> if one is not required. |
637 |
* @param encoding the encoding to use for the XML output. |
* @param encoding the encoding to use for the XML output. |
638 |
* @throws IOException if the serialization fails. |
* @throws IOException if the serialization fails. |
639 |
|
* @throws NullPointerException if <code>os</code> or <code>encoding</code> |
640 |
|
* is null. |
641 |
* @since 1.5 |
* @since 1.5 |
642 |
*/ |
*/ |
643 |
public void storeToXML(OutputStream os, String comment, String encoding) |
public void storeToXML(OutputStream os, String comment, String encoding) |
644 |
throws IOException |
throws IOException |
645 |
{ |
{ |
646 |
|
if (os == null) |
647 |
|
throw new NullPointerException("Null output stream supplied."); |
648 |
|
if (encoding == null) |
649 |
|
throw new NullPointerException("Null encoding supplied."); |
650 |
try |
try |
651 |
{ |
{ |
652 |
DOMImplementationRegistry registry = |
DOMImplementationRegistry registry = |
699 |
} |
} |
700 |
} |
} |
701 |
|
|
702 |
|
/** |
703 |
|
* <p> |
704 |
|
* Decodes the contents of the supplied <code>InputStream</code> as |
705 |
|
* an XML file, which represents a set of properties. The format of |
706 |
|
* the XML file must match the DTD |
707 |
|
* <a href="http://java.sun.com/dtd/properties.dtd"> |
708 |
|
* http://java.sun.com/dtd/properties.dtd</a>. |
709 |
|
* </p> |
710 |
|
* |
711 |
|
* @param in the input stream from which to receive the XML data. |
712 |
|
* @throws IOException if an I/O error occurs in reading the input data. |
713 |
|
* @throws InvalidPropertiesFormatException if the input data does not |
714 |
|
* constitute an XML properties |
715 |
|
* file. |
716 |
|
* @throws NullPointerException if <code>in</code> is null. |
717 |
|
* @since 1.5 |
718 |
|
*/ |
719 |
|
public void loadFromXML(InputStream in) |
720 |
|
throws IOException, InvalidPropertiesFormatException |
721 |
|
{ |
722 |
|
if (in == null) |
723 |
|
throw new NullPointerException("Null input stream supplied."); |
724 |
|
try |
725 |
|
{ |
726 |
|
SAXParserFactory factory = SAXParserFactory.newInstance(); |
727 |
|
factory.setValidating(false); /* Don't use the URI */ |
728 |
|
XMLReader parser = factory.newSAXParser().getXMLReader(); |
729 |
|
PropertiesHandler handler = new PropertiesHandler(); |
730 |
|
parser.setContentHandler(handler); |
731 |
|
parser.setProperty("http://xml.org/sax/properties/lexical-handler", |
732 |
|
handler); |
733 |
|
parser.parse(new InputSource(in)); |
734 |
|
} |
735 |
|
catch (SAXException e) |
736 |
|
{ |
737 |
|
throw (InvalidPropertiesFormatException) |
738 |
|
new InvalidPropertiesFormatException("Error in parsing XML."). |
739 |
|
initCause(e); |
740 |
|
} |
741 |
|
catch (ParserConfigurationException e) |
742 |
|
{ |
743 |
|
throw (IOException) |
744 |
|
new IOException("An XML parser could not be found."). |
745 |
|
initCause(e); |
746 |
|
} |
747 |
|
} |
748 |
|
|
749 |
|
/** |
750 |
|
* This class deals with the parsing of XML using |
751 |
|
* <a href="http://java.sun.com/dtd/properties.dtd"> |
752 |
|
* http://java.sun.com/dtd/properties.dtd</a>. |
753 |
|
* |
754 |
|
* @author Andrew John Hughes (gnu_andrew@member.fsf.org) |
755 |
|
* @since 1.5 |
756 |
|
*/ |
757 |
|
private class PropertiesHandler |
758 |
|
extends DefaultHandler2 |
759 |
|
{ |
760 |
|
|
761 |
|
/** |
762 |
|
* The current key. |
763 |
|
*/ |
764 |
|
private String key; |
765 |
|
|
766 |
|
/** |
767 |
|
* The current value. |
768 |
|
*/ |
769 |
|
private String value; |
770 |
|
|
771 |
|
/** |
772 |
|
* A flag to check whether a valid DTD declaration has been seen. |
773 |
|
*/ |
774 |
|
private boolean dtdDeclSeen; |
775 |
|
|
776 |
|
/** |
777 |
|
* Constructs a new Properties handler. |
778 |
|
*/ |
779 |
|
public PropertiesHandler() |
780 |
|
{ |
781 |
|
key = null; |
782 |
|
value = null; |
783 |
|
dtdDeclSeen = false; |
784 |
|
} |
785 |
|
|
786 |
|
/** |
787 |
|
* <p> |
788 |
|
* Captures the start of the DTD declarations, if they exist. |
789 |
|
* A valid properties file must declare the following doctype: |
790 |
|
* </p> |
791 |
|
* <p> |
792 |
|
* <code>!DOCTYPE properties SYSTEM |
793 |
|
* "http://java.sun.com/dtd/properties.dtd"</code> |
794 |
|
* </p> |
795 |
|
* |
796 |
|
* @param name the name of the document type. |
797 |
|
* @param publicId the public identifier that was declared, or |
798 |
|
* null if there wasn't one. |
799 |
|
* @param systemId the system identifier that was declared, or |
800 |
|
* null if there wasn't one. |
801 |
|
* @throws SAXException if some error occurs in parsing. |
802 |
|
*/ |
803 |
|
public void startDTD(String name, String publicId, String systemId) |
804 |
|
throws SAXException |
805 |
|
{ |
806 |
|
if (name.equals("properties") && |
807 |
|
publicId == null && |
808 |
|
systemId.equals("http://java.sun.com/dtd/properties.dtd")) |
809 |
|
{ |
810 |
|
dtdDeclSeen = true; |
811 |
|
} |
812 |
|
else |
813 |
|
throw new SAXException("Invalid DTD declaration: " + name); |
814 |
|
} |
815 |
|
|
816 |
|
/** |
817 |
|
* Captures the start of an XML element. |
818 |
|
* |
819 |
|
* @param uri the namespace URI. |
820 |
|
* @param localName the local name of the element inside the namespace. |
821 |
|
* @param qName the local name qualified with the namespace URI. |
822 |
|
* @param attributes the attributes of this element. |
823 |
|
* @throws SAXException if some error occurs in parsing. |
824 |
|
*/ |
825 |
|
public void startElement(String uri, String localName, |
826 |
|
String qName, Attributes attributes) |
827 |
|
throws SAXException |
828 |
|
{ |
829 |
|
if (qName.equals("entry")) |
830 |
|
{ |
831 |
|
int index = attributes.getIndex("key"); |
832 |
|
if (index != -1) |
833 |
|
key = attributes.getValue(index); |
834 |
|
} |
835 |
|
else if (qName.equals("comment") || qName.equals("properties")) |
836 |
|
{ |
837 |
|
/* Ignore it */ |
838 |
|
} |
839 |
|
else |
840 |
|
throw new SAXException("Invalid tag: " + qName); |
841 |
|
} |
842 |
|
|
843 |
|
/** |
844 |
|
* Captures characters within an XML element. |
845 |
|
* |
846 |
|
* @param ch the array of characters. |
847 |
|
* @param start the start index of the characters to use. |
848 |
|
* @param length the number of characters to use from the start index on. |
849 |
|
* @throws SAXException if some error occurs in parsing. |
850 |
|
*/ |
851 |
|
public void characters(char[] ch, int start, int length) |
852 |
|
throws SAXException |
853 |
|
{ |
854 |
|
if (key != null) |
855 |
|
value = new String(ch,start,length); |
856 |
|
} |
857 |
|
|
858 |
|
/** |
859 |
|
* Captures the end of an XML element. |
860 |
|
* |
861 |
|
* @param uri the namespace URI. |
862 |
|
* @param localName the local name of the element inside the namespace. |
863 |
|
* @param qName the local name qualified with the namespace URI. |
864 |
|
* @throws SAXException if some error occurs in parsing. |
865 |
|
*/ |
866 |
|
public void endElement(String uri, String localName, |
867 |
|
String qName) |
868 |
|
throws SAXException |
869 |
|
{ |
870 |
|
if (qName.equals("entry")) |
871 |
|
{ |
872 |
|
if (value == null) |
873 |
|
value = ""; |
874 |
|
setProperty(key, value); |
875 |
|
key = null; |
876 |
|
value = null; |
877 |
|
} |
878 |
|
} |
879 |
|
|
880 |
|
/** |
881 |
|
* Captures the end of the XML document. If a DTD declaration has |
882 |
|
* not been seen, the document is erroneous and an exception is thrown. |
883 |
|
* |
884 |
|
* @throws SAXException if the correct DTD declaration didn't appear. |
885 |
|
*/ |
886 |
|
public void endDocument() |
887 |
|
throws SAXException |
888 |
|
{ |
889 |
|
if (!dtdDeclSeen) |
890 |
|
throw new SAXException("No appropriate DTD declaration was seen."); |
891 |
|
} |
892 |
|
|
893 |
|
} // class PropertiesHandler |
894 |
|
|
895 |
} // class Properties |
} // class Properties |