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