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 /* 25 * @test 26 * @bug 8000354 8000685 8004371 8043119 27 * @summary Basic test of storeToXML and loadToXML 28 */ 29 30 import java.io.ByteArrayInputStream; 31 import java.io.ByteArrayOutputStream; 32 import java.io.IOException; 33 import java.io.InputStream; 34 import java.io.UnsupportedEncodingException; 35 import java.nio.file.DirectoryStream; 36 import java.nio.file.Files; 37 import java.nio.file.Path; 38 import java.nio.file.Paths; 39 import java.security.CodeSource; 40 import java.security.Permission; 41 import java.security.PermissionCollection; 42 import java.security.Permissions; 43 import java.security.Policy; 44 import java.security.ProtectionDomain; 45 import java.util.InvalidPropertiesFormatException; 46 import java.util.Properties; 47 import java.util.PropertyPermission; 48 49 public class LoadAndStoreXML { 50 51 /** 52 * Simple policy implementation that grants a set of permissions to 53 * all code sources and protection domains. 54 */ 55 static class SimplePolicy extends Policy { 56 private final Permissions perms; 57 58 public SimplePolicy(Permission...permissions) { 59 perms = new Permissions(); 60 for (Permission permission : permissions) 61 perms.add(permission); 62 } 63 64 @Override 65 public PermissionCollection getPermissions(CodeSource cs) { 66 return perms; 67 } 68 69 @Override 70 public PermissionCollection getPermissions(ProtectionDomain pd) { 71 return perms; 72 } 73 74 @Override 75 public boolean implies(ProtectionDomain pd, Permission p) { 76 return perms.implies(p); 77 } 78 } 79 80 /** 81 * A {@code ByteArrayInputStream} that allows testing if the 82 * {@code close} method has been invoked. 83 */ 84 static class TestInputStream extends ByteArrayInputStream { 85 private boolean closed; 86 87 TestInputStream(byte[] buf) { 88 super(buf); 89 } 90 91 boolean isOpen() { 92 return !closed; 93 } 94 95 public void close() throws IOException { 96 try { 97 super.close(); 98 } finally { 99 closed = true; 100 } 101 } 102 } 103 104 /** 105 * A {@code ByteArrayOutputStream} that allows testing if the 106 * {@code close} method has been invoked. 107 */ 108 static class TestOutputStream extends ByteArrayOutputStream { 109 private boolean closed; 110 111 boolean isOpen() { 112 return !closed; 113 } 114 115 public void close() throws IOException { 116 try { 117 super.close(); 118 } finally { 119 closed = true; 120 } 121 } 122 } 123 124 /** 125 * Sanity test that properties saved with Properties#storeToXML can be 126 * read with Properties#loadFromXML. 127 */ 128 static void testLoadAndStore(String encoding) throws IOException { 129 System.out.println("testLoadAndStore, encoding=" + encoding); 130 131 Properties props = new Properties(); 132 props.put("k1", "foo"); 133 props.put("k2", "bar"); 134 props.put("k3", "\\u0020\\u0391\\u0392\\u0393\\u0394\\u0395\\u0396\\u0397"); 135 props.put("k4", "\u7532\u9aa8\u6587"); 136 props.put("k5", "<java.home>/lib/jaxp.properties"); 137 138 TestOutputStream out = new TestOutputStream(); 139 props.storeToXML(out, null, encoding); 140 if (!out.isOpen()) 141 throw new RuntimeException("OutputStream closed by storeToXML"); 142 143 Properties p = new Properties(); 144 TestInputStream in = new TestInputStream(out.toByteArray()); 145 p.loadFromXML(in); 146 if (in.isOpen()) 147 throw new RuntimeException("InputStream not closed by loadFromXML"); 148 149 if (!p.equals(props)) { 150 System.err.println("stored: " + props); 151 System.err.println("loaded: " + p); 152 throw new RuntimeException("Test failed"); 153 } 154 } 155 156 /** 157 * Test loadFromXML with a document that does not have an encoding declaration 158 */ 159 static void testLoadWithoutEncoding() throws IOException { 160 System.out.println("testLoadWithoutEncoding"); 161 162 Properties expected = new Properties(); 163 expected.put("foo", "bar"); 164 165 String s = "<?xml version=\"1.0\"?>" + 166 "<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">" + 167 "<properties>" + 168 "<entry key=\"foo\">bar</entry>" + 169 "</properties>"; 170 ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes("UTF-8")); 171 Properties props = new Properties(); 172 props.loadFromXML(in); 173 174 if (!props.equals(expected)) { 175 System.err.println("loaded: " + props + ", expected: " + expected); 176 throw new RuntimeException("Test failed"); 177 } 178 } 179 180 /** 181 * Test loadFromXML with unsupported encoding 182 */ 183 static void testLoadWithBadEncoding() throws IOException { 184 System.out.println("testLoadWithBadEncoding"); 185 String s = "<?xml version=\"1.0\" encoding=\"BAD\"?>" + 186 "<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">" + 187 "<properties>" + 188 "<entry key=\"foo\">bar</entry>" + 189 "</properties>"; 190 ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes("UTF-8")); 191 Properties props = new Properties(); 192 try { 193 props.loadFromXML(in); 194 throw new RuntimeException("UnsupportedEncodingException expected"); 195 } catch (UnsupportedEncodingException expected) { } 196 } 197 198 /** 199 * Test storeToXML with unsupported encoding 200 */ 201 static void testStoreWithBadEncoding() throws IOException { 202 System.out.println("testStoreWithBadEncoding"); 203 Properties props = new Properties(); 204 props.put("foo", "bar"); 205 ByteArrayOutputStream out = new ByteArrayOutputStream(); 206 try { 207 props.storeToXML(out, null, "BAD"); 208 throw new RuntimeException("UnsupportedEncodingException expected"); 209 } catch (UnsupportedEncodingException expected) { } 210 } 211 212 /** 213 * Test loadFromXML with malformed documents 214 */ 215 static void testLoadWithMalformedDoc(Path dir) throws IOException { 216 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.xml")) { 217 for (Path file: stream) { 218 System.out.println("testLoadWithMalformedDoc, file=" + file.getFileName()); 219 try (InputStream in = Files.newInputStream(file)) { 220 Properties props = new Properties(); 221 try { 222 props.loadFromXML(in); 223 throw new RuntimeException("InvalidPropertiesFormatException not thrown"); 224 } catch (InvalidPropertiesFormatException x) { 225 System.out.println(x); 226 } 227 } 228 } 229 } 230 } 231 232 public static void main(String[] args) throws IOException { 233 234 testLoadAndStore("UTF-8"); 235 testLoadAndStore("UTF-16"); 236 testLoadWithoutEncoding(); 237 testLoadWithBadEncoding(); 238 testStoreWithBadEncoding(); 239 240 // malformed documents 241 String src = System.getProperty("test.src"); 242 String subdir = "invalidxml"; 243 Path dir = (src == null) ? Paths.get(subdir) : Paths.get(src, subdir); 244 testLoadWithMalformedDoc(dir); 245 246 // re-run sanity test with security manager 247 Policy orig = Policy.getPolicy(); 248 Policy p = new SimplePolicy(new RuntimePermission("setSecurityManager"), 249 new PropertyPermission("line.separator", "read")); 250 Policy.setPolicy(p); 251 System.setSecurityManager(new SecurityManager()); 252 try { 253 testLoadAndStore("UTF-8"); 254 } finally { 255 // turn off security manager and restore policy 256 System.setSecurityManager(null); 257 Policy.setPolicy(orig); 258 } 259 260 } 261 }