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