You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/06/07 14:06:53 UTC

svn commit: r412383 - in /incubator/harmony/enhanced/classlib/trunk/modules/luni/src: main/java/java/util/InvalidPropertiesFormatException.java main/java/java/util/Properties.java test/java/tests/api/java/util/PropertiesTest.java

Author: tellison
Date: Wed Jun  7 05:06:52 2006
New Revision: 412383

URL: http://svn.apache.org/viewvc?rev=412383&view=rev
Log:
Apply patch HARMONY-563 (Java 5 Enhancement: java.util.Properties should implement methods loadFromXML, storeToXML)

Added:
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/InvalidPropertiesFormatException.java   (with props)
Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Properties.java
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/PropertiesTest.java

Added: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/InvalidPropertiesFormatException.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/InvalidPropertiesFormatException.java?rev=412383&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/InvalidPropertiesFormatException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/InvalidPropertiesFormatException.java Wed Jun  7 05:06:52 2006
@@ -0,0 +1,43 @@
+/* Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package java.util;
+
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
+
+public class InvalidPropertiesFormatException extends IOException {
+    
+    public InvalidPropertiesFormatException(String m) {
+        super(m);
+    }
+
+    public InvalidPropertiesFormatException(Throwable c) {
+        initCause(c);
+    }
+    
+    private void writeObject(ObjectOutputStream out) 
+            throws NotSerializableException{
+        throw new NotSerializableException();        
+    }
+    
+    private void readObject(ObjectInputStream in) 
+            throws NotSerializableException{
+        throw new NotSerializableException();        
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/InvalidPropertiesFormatException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Properties.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Properties.java?rev=412383&r1=412382&r2=412383&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Properties.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Properties.java Wed Jun  7 05:06:52 2006
@@ -22,8 +22,23 @@
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
 import java.io.PrintWriter;
+import java.io.StringReader;
 import java.security.AccessController;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
 import org.apache.harmony.luni.util.PriviAction;
 
 /**
@@ -38,6 +53,19 @@
 	
 	private static final long serialVersionUID = 4112578634029874840L;
 
+    private DocumentBuilder builder = null;
+
+    private static final String PROP_DTD_NAME 
+            = "http://java.sun.com/dtd/properties.dtd";
+
+    private static final String PROP_DTD 
+            = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "    <!ELEMENT properties (comment?, entry*) >"
+            + "    <!ATTLIST properties version CDATA #FIXED \"1.0\" >"
+            + "    <!ELEMENT comment (#PCDATA) >"
+            + "    <!ELEMENT entry (#PCDATA) >"
+            + "    <!ATTLIST entry key CDATA #REQUIRED >";
+	
 	/**
 	 * The default values for this Properties.
 	 */
@@ -463,4 +491,160 @@
 		writer.flush();
 	}
 
+    public synchronized void loadFromXML(InputStream in) 
+            throws IOException, InvalidPropertiesFormatException {
+        if (in == null) {
+            throw new NullPointerException();
+        }
+        
+        if (builder == null) {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            factory.setValidating(true);
+            
+            try {
+                builder = factory.newDocumentBuilder();
+            } catch (ParserConfigurationException e) {
+                throw new Error(e);
+            }
+            
+            builder.setErrorHandler(new ErrorHandler() {
+                public void warning(SAXParseException e) throws SAXException {
+                    throw e;
+                }
+
+                public void error(SAXParseException e) throws SAXException {
+                    throw e;
+                }
+
+                public void fatalError(SAXParseException e) throws SAXException {
+                    throw e;
+                }
+            });
+            
+            builder.setEntityResolver(new EntityResolver() {
+                public InputSource resolveEntity(String publicId, String systemId)
+                        throws SAXException, IOException {
+                    if (systemId.equals(PROP_DTD_NAME)) {
+                        InputSource result = new InputSource(new StringReader(
+                                PROP_DTD));
+                        result.setSystemId(PROP_DTD_NAME);
+                        return result;
+                    }
+                    throw new SAXException(
+                            "Invalid DOCTYPE declaration: " + systemId);
+                }
+            });
+        }
+        
+        try {
+            Document doc = builder.parse(in);
+            NodeList entries = doc.getElementsByTagName("entry"); 
+            if (entries == null) {
+                return;
+            }
+            int entriesListLength = entries.getLength();
+            
+            for (int i = 0; i < entriesListLength; i++) {
+                Element entry = (Element) entries.item(i);
+                String key = entry.getAttribute("key");
+                String value = entry.getTextContent();
+                
+                /*
+                 * key != null & value != null
+                 * but key or(and) value can be empty String
+                 */
+                put(key, value);
+            }
+        } catch (IOException e) {
+            throw e;
+        } catch (SAXException e) {
+            throw new InvalidPropertiesFormatException(e);
+        }
+    }
+    
+    public void storeToXML(OutputStream os, String comment) 
+            throws IOException {
+        storeToXML(os, comment, "UTF-8");
+    }
+    
+    public synchronized void storeToXML(OutputStream os, String comment,
+             String encoding) throws IOException {
+        String encodingCanonicalName; 
+
+        if (os == null || encoding == null) {
+            throw new NullPointerException();
+        }
+        
+        if (lineSeparator == null) {
+            lineSeparator = (String) AccessController
+                    .doPrivileged(new PriviAction("line.separator"));
+        }
+        
+        /*
+         * Uncomment following code when java.nio.charset.Charset class will
+         * be implemented. We can write to XML file using encoding parameter 
+         * but note that some aliases for encodings are not supported 
+         * by the XML parser. Thus we have to know canonical name for encoding
+         * used to store data in XML since the XML parser must recognize 
+         * encoding name used to store data.
+         */
+        
+        //try {
+        //    encodingCanonicalName = Charset.forName(encoding).name();
+        //} catch (IllegalCharsetNameException e) {
+        //    System.out.println("Warning: encoding name " + encoding +" is illegal, " 
+        //            + "using UTF-8 as default encoding");
+        //    encodingCanonicalName = "UTF-8";
+        //} catch (UnsupportedCharsetException e) {
+        //    System.out.println("Warning: encoding " + encoding +" is not supported, " 
+        //            + "using UTF-8 as default encoding");
+        //    encodingCanonicalName = "UTF-8";
+        //}
+        
+        /*
+         * We use UTF-8 as default encoding. Delete the line of code that 
+         * follows this comment when java.nio.charset.Charset class will be 
+         * implemented.
+         */
+        encodingCanonicalName = "UTF-8";
+        
+        OutputStreamWriter osw = new OutputStreamWriter(os,
+                encodingCanonicalName);
+        StringBuffer buf = new StringBuffer(200);
+        buf.append("<?xml version=\"1.0\" encoding=\"" + encodingCanonicalName 
+                + "\"?>" + lineSeparator);
+        buf.append("<!DOCTYPE properties SYSTEM \"" + PROP_DTD_NAME 
+                + "\">" + lineSeparator);
+        buf.append("<properties>" + lineSeparator);
+        if (comment != null) {
+            buf.append("<comment>" + substitutePredefinedEntries(comment) 
+                    + "</comment>" + lineSeparator);
+        }
+        Iterator iter = entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry entry = (Map.Entry) iter.next();
+            String keyValue = (String) entry.getKey();
+            String entryValue = (String) entry.getValue();
+            buf.append("<entry key=\"" + substitutePredefinedEntries(keyValue) 
+                    + "\">" + substitutePredefinedEntries(entryValue) 
+                    + "</entry>" + lineSeparator);            
+        }
+        buf.append("</properties>" + lineSeparator);
+    
+        osw.write(buf.toString());
+        osw.flush();
+    }
+    
+    private String substitutePredefinedEntries(String s) {
+        
+        /*
+         * substitution for predefined character entities
+         * to use them safely in XML
+         */
+        return s.replaceAll("&", "&amp;")
+            .replaceAll("<", "&lt;")
+            .replaceAll(">", "&gt;")
+            .replaceAll("\u0027", "&apos;")
+            .replaceAll("\"", "&quot;");
+    }	
 }

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/PropertiesTest.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/PropertiesTest.java?rev=412383&r1=412382&r2=412383&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/PropertiesTest.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/PropertiesTest.java Wed Jun  7 05:06:52 2006
@@ -23,6 +23,7 @@
 import java.io.PrintWriter;
 import java.util.Enumeration;
 import java.util.Properties;
+import java.util.InvalidPropertiesFormatException;
 
 import tests.support.resource.Support_Resources;
 
@@ -327,6 +328,116 @@
 	}
 
 	/**
+     * @tests java.util.Properties#loadFromXML(java.io.InputStream)
+     */
+    public void test_loadFromXMLLjava_io_InputStream() {
+        // Test for method void java.util.Properties.loadFromXML(java.io.InputStream)
+        Properties prop = null;
+        try {
+            InputStream is;
+            prop = new Properties();
+            prop.loadFromXML(is = new ByteArrayInputStream(writePropertiesXMLUTF_8()));
+            is.close();
+        } catch (Exception e) {
+            fail("Exception during load test : " + e.getMessage());
+        }
+        assertEquals("Failed to load correct properties", "value3", prop.getProperty(
+        "key3"));
+        assertEquals("Failed to load correct properties", "value1", prop.getProperty(
+        "key1"));
+                
+        try {
+            InputStream is;
+            prop = new Properties();
+            prop.loadFromXML(is = new ByteArrayInputStream(writePropertiesXMLISO_8859_1()));
+            is.close();
+        } catch (Exception e) {
+            fail("Exception during load test : " + e.getMessage());
+        }
+        assertEquals("Failed to load correct properties", "value2", prop.getProperty(
+        "key2"));
+        assertEquals("Failed to load correct properties", "value1", prop.getProperty(
+        "key1"));
+    }
+    
+    /**
+     * @tests java.util.Properties#storeToXML(java.io.OutputStream, java.lang.String, java.lang.String)
+     */
+    public void test_storeToXMLLjava_io_OutputStreamLjava_lang_StringLjava_lang_String() {
+        // Test for method void java.util.Properties.storeToXML(java.io.OutputStream,
+        // java.lang.String, java.lang.String)
+        Properties myProps = new Properties();
+        Properties myProps2 = new Properties();
+        Enumeration e;
+        String nextKey;
+
+        myProps.setProperty("key1", "value1");
+        myProps.setProperty("key2", "value2");
+        myProps.setProperty("key3", "value3");
+        myProps.setProperty("<a>key4</a>", "\"value4");
+        myProps.setProperty("key5   ", "<h>value5</h>");
+        myProps.setProperty("<a>key6</a>", "   <h>value6</h>   ");
+        myProps.setProperty("<comment>key7</comment>", "value7");
+        myProps.setProperty("  key8   ", "<comment>value8</comment>");
+        myProps.setProperty("&lt;key9&gt;", "\u0027value9");
+        myProps.setProperty("key10\"", "&lt;value10&gt;");
+        myProps.setProperty("&amp;key11&amp;", "value11");
+        myProps.setProperty("key12", "&amp;value12&amp;");
+        myProps.setProperty("<a>&amp;key13&lt;</a>", "&amp;&value13<b>&amp;</b>");
+        
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            
+            //store in UTF-8 encoding
+            myProps.storeToXML(out, "comment");
+            out.close();
+            ByteArrayInputStream in = new ByteArrayInputStream(out
+                    .toByteArray());
+            myProps2.loadFromXML(in);
+            in.close();
+        } catch (InvalidPropertiesFormatException ipfe) {
+            fail("InvalidPropertiesFormatException occurred reading file: "
+                    + ipfe.getMessage());
+        } catch (IOException ioe) {
+            fail("IOException occurred reading/writing file : "
+                    + ioe.getMessage());
+        }
+
+        e = myProps.propertyNames();
+        while (e.hasMoreElements()) {
+            nextKey = (String) e.nextElement();
+            assertTrue("Stored property list not equal to original", myProps2
+                    .getProperty(nextKey).equals(myProps.getProperty(nextKey)));
+        }
+
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            
+            //store in ISO-8859-1 encoding
+            myProps.storeToXML(out, "comment", "ISO-8859-1");
+            out.close();
+            ByteArrayInputStream in = new ByteArrayInputStream(out
+                    .toByteArray());
+            myProps2 = new Properties();
+            myProps2.loadFromXML(in);
+            in.close();
+        } catch (InvalidPropertiesFormatException ipfe) {
+            fail("InvalidPropertiesFormatException occurred reading file: "
+                    + ipfe.getMessage());
+        } catch (IOException ioe) {
+            fail("IOException occurred reading/writing file : "
+                    + ioe.getMessage());
+        }
+
+        e = myProps.propertyNames();
+        while (e.hasMoreElements()) {
+            nextKey = (String) e.nextElement();
+            assertTrue("Stored property list not equal to original", myProps2
+                    .getProperty(nextKey).equals(myProps.getProperty(nextKey)));
+        }        
+    }
+    
+    /**
 	 * Sets up the fixture, for example, open a network connection. This method
 	 * is called before a test is executed.
 	 */
@@ -358,4 +469,38 @@
 		ps.close();
 		return bout.toByteArray();
 	}
+    
+    protected byte[] writePropertiesXMLUTF_8() throws IOException {
+        PrintStream ps = null;
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        ps = new PrintStream(bout, true, "UTF-8");
+        ps.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+        ps.println("<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">");
+        ps.println("<properties>");
+        ps.println("<comment>comment</comment>");
+        ps.println("<entry key=\"key4\">value4</entry>");
+        ps.println("<entry key=\"key3\">value3</entry>");
+        ps.println("<entry key=\"key2\">value2</entry>");
+        ps.println("<entry key=\"key1\"><!-- xml comment -->value1</entry>");
+        ps.println("</properties>");
+        ps.close();
+        return bout.toByteArray();
+    }
+    
+    protected byte[] writePropertiesXMLISO_8859_1() throws IOException {
+        PrintStream ps = null;
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        ps = new PrintStream(bout, true, "ISO-8859-1");
+        ps.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
+        ps.println("<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">");
+        ps.println("<properties>");
+        ps.println("<comment>comment</comment>");
+        ps.println("<entry key=\"key4\">value4</entry>");
+        ps.println("<entry key=\"key3\">value3</entry>");
+        ps.println("<entry key=\"key2\">value2</entry>");
+        ps.println("<entry key=\"key1\"><!-- xml comment -->value1</entry>");
+        ps.println("</properties>");
+        ps.close();
+        return bout.toByteArray();
+    }
 }