1 /*
2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /* @test
25  * @bug 8005281
26  * @summary Test that the Properties storeToXML and loadFromXML methods are
27  *   thread safe
28  * @key randomness
29  */
30 
31 package test.java.util.Properties;
32 
33 import java.io.*;
34 import java.util.Properties;
35 import java.util.Random;
36 import java.util.concurrent.Callable;
37 import java.util.concurrent.Executors;
38 import java.util.concurrent.ExecutorService;
39 import java.util.concurrent.Future;
40 
41 public class ConcurrentLoadAndStoreXML {
42 
43     static final Random RAND = new Random();
44 
45     static volatile boolean done;
46 
47     /**
48      * Simple task that bashes on storeToXML and loadFromXML until the "done"
49      * flag is set.
50      */
51     static class Basher implements Callable<Void> {
52         final Properties props;
53 
Basher(Properties props)54         Basher(Properties props) {
55             this.props = props;
56         }
57 
call()58         public Void call() throws IOException {
59             while (!done) {
60 
61                 // store as XML format
62                 ByteArrayOutputStream out = new ByteArrayOutputStream();
63                 props.storeToXML(out, null, "UTF-8");
64 
65                 // load from XML format
66                 Properties p = new Properties();
67                 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
68                 p.loadFromXML(in);
69 
70                 // check that the properties are as expected
71                 if (!p.equals(props))
72                     throw new RuntimeException("Properties not equal");
73             }
74             return null;
75         }
76     }
77 
main(String[] args)78     public static void main(String[] args) throws Exception {
79         final int NTASKS = 4 + RAND.nextInt(4);
80 
81         // create Bashers with Properties of random keys and values
82         Basher[] basher = new Basher[NTASKS];
83         for (int i=0; i<NTASKS; i++) {
84             Properties props = new Properties();
85             for (int j=0; j<RAND.nextInt(100); j++) {
86                 String key = "k" + RAND.nextInt(1000);
87                 String value = "v" + RAND.nextInt(1000);
88                 props.put(key, value);
89             }
90             basher[i] = new Basher(props);
91         }
92 
93         ExecutorService pool = Executors.newFixedThreadPool(NTASKS);
94         try {
95             // kick off the bashers
96             Future<Void>[] task = new Future[NTASKS];
97             for (int i=0; i<NTASKS; i++) {
98                 task[i] = pool.submit(basher[i]);
99             }
100 
101             // give them time to interfere with each each
102             Thread.sleep(2000);
103             done = true;
104 
105             // check the result
106             for (int i=0; i<NTASKS; i++) {
107                 task[i].get();
108             }
109         } finally {
110             done = true;
111             pool.shutdown();
112         }
113 
114     }
115 }
116