8005281: (props) loadFromXML/storeToXML with small parser is not thread safe
authoralanb
Thu, 20 Dec 2012 20:40:04 +0000
changeset 14918 5e247ff7e351
parent 14917 bf08557604f8
child 14919 cd751b98ef69
8005281: (props) loadFromXML/storeToXML with small parser is not thread safe Reviewed-by: mchung
jdk/src/share/classes/jdk/internal/util/xml/BasicXmlPropertiesProvider.java
jdk/test/java/util/Properties/ConcurrentLoadAndStoreXML.java
--- a/jdk/src/share/classes/jdk/internal/util/xml/BasicXmlPropertiesProvider.java	Thu Dec 20 20:29:59 2012 +0000
+++ b/jdk/src/share/classes/jdk/internal/util/xml/BasicXmlPropertiesProvider.java	Thu Dec 20 20:40:04 2012 +0000
@@ -38,14 +38,13 @@
 
 public class BasicXmlPropertiesProvider extends XmlPropertiesProvider {
 
-    private final PropertiesDefaultHandler handler = new PropertiesDefaultHandler();
-
     public BasicXmlPropertiesProvider() { }
 
     @Override
     public void load(Properties props, InputStream in)
         throws IOException, InvalidPropertiesFormatException
     {
+        PropertiesDefaultHandler handler = new PropertiesDefaultHandler();
         handler.load(props, in);
     }
 
@@ -54,6 +53,7 @@
                       String encoding)
         throws IOException
     {
+        PropertiesDefaultHandler handler = new PropertiesDefaultHandler();
         handler.store(props, os, comment, encoding);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Properties/ConcurrentLoadAndStoreXML.java	Thu Dec 20 20:40:04 2012 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8005281
+ * @summary Test that the Properties storeToXML and loadFromXML methods are
+ *   thread safe
+ * @run main ConcurrentLoadAndStoreXML
+ * @run main/othervm -Dsun.util.spi.XmlPropertiesProvider=jdk.internal.util.xml.BasicXmlPropertiesProvider ConcurrentLoadAndStoreXML
+
+ */
+
+import java.io.*;
+import java.util.Properties;
+import java.util.Random;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+public class ConcurrentLoadAndStoreXML {
+
+    static final Random RAND = new Random();
+
+    static volatile boolean done;
+
+    /**
+     * Simple task that bashes on storeToXML and loadFromXML until the "done"
+     * flag is set.
+     */
+    static class Basher implements Callable<Void> {
+        final Properties props;
+
+        Basher(Properties props) {
+            this.props = props;
+        }
+
+        public Void call() throws IOException {
+            while (!done) {
+
+                // store as XML format
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                props.storeToXML(out, null, "UTF-8");
+
+                // load from XML format
+                Properties p = new Properties();
+                ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+                p.loadFromXML(in);
+
+                // check that the properties are as expected
+                if (!p.equals(props))
+                    throw new RuntimeException("Properties not equal");
+            }
+            return null;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        final int NTASKS = 4 + RAND.nextInt(4);
+
+        // create Bashers with Properties of random keys and values
+        Basher[] basher = new Basher[NTASKS];
+        for (int i=0; i<NTASKS; i++) {
+            Properties props = new Properties();
+            for (int j=0; j<RAND.nextInt(100); j++) {
+                String key = "k" + RAND.nextInt(1000);
+                String value = "v" + RAND.nextInt(1000);
+                props.put(key, value);
+            }
+            basher[i] = new Basher(props);
+        }
+
+        ExecutorService pool = Executors.newFixedThreadPool(NTASKS);
+        try {
+            // kick off the bashers
+            Future<Void>[] task = new Future[NTASKS];
+            for (int i=0; i<NTASKS; i++) {
+                task[i] = pool.submit(basher[i]);
+            }
+
+            // give them time to interfere with each each
+            Thread.sleep(2000);
+            done = true;
+
+            // check the result
+            for (int i=0; i<NTASKS; i++) {
+                task[i].get();
+            }
+        } finally {
+            done = true;
+            pool.shutdown();
+        }
+
+    }
+}