1 /* 2 * Copyright (c) 2013, 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 8004476 26 * @summary test XPath extension functions 27 * @run main/othervm XPathExFuncTest 28 */ 29 import java.io.FileInputStream; 30 import java.io.InputStream; 31 import java.security.AllPermission; 32 import java.security.CodeSource; 33 import java.security.Permission; 34 import java.security.PermissionCollection; 35 import java.security.Permissions; 36 import java.security.Policy; 37 import java.security.ProtectionDomain; 38 import java.util.Iterator; 39 import java.util.List; 40 import javax.xml.XMLConstants; 41 import javax.xml.namespace.NamespaceContext; 42 import javax.xml.namespace.QName; 43 import javax.xml.parsers.DocumentBuilder; 44 import javax.xml.parsers.DocumentBuilderFactory; 45 import javax.xml.xpath.XPath; 46 import javax.xml.xpath.XPathExpressionException; 47 import javax.xml.xpath.XPathFactory; 48 import javax.xml.xpath.XPathFactoryConfigurationException; 49 import javax.xml.xpath.XPathFunction; 50 import javax.xml.xpath.XPathFunctionException; 51 import javax.xml.xpath.XPathFunctionResolver; 52 import org.w3c.dom.Document; 53 54 /** 55 * test XPath extension functions 56 * 57 * @author huizhe.wang@oracle.com 58 */ 59 public class XPathExFuncTest extends TestBase { 60 61 final static String ENABLE_EXTENSION_FUNCTIONS = "http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions"; 62 final static String CLASSNAME = "DocumentBuilderFactoryImpl"; 63 final String XPATH_EXPRESSION = "ext:helloWorld()"; 64 65 /** 66 * Creates a new instance of StreamReader 67 */ 68 public XPathExFuncTest(String name) { 69 super(name); 70 } 71 boolean hasSM; 72 String xslFile, xslFileId; 73 String xmlFile, xmlFileId; 74 75 protected void setUp() { 76 super.setUp(); 77 xmlFile = filepath + "/SecureProcessingTest.xml"; 78 79 } 80 81 /** 82 * @param args the command line arguments 83 */ 84 public static void main(String[] args) { 85 XPathExFuncTest test = new XPathExFuncTest("OneTest"); 86 test.setUp(); 87 88 test.testExtFunc(); 89 test.testExtFuncNotAllowed(); 90 test.testEnableExtFunc(); 91 test.tearDown(); 92 93 } 94 95 /** 96 * by default, extension function is enabled 97 */ 98 public void testExtFunc() { 99 100 try { 101 evaluate(false); 102 System.out.println("testExtFunc: OK"); 103 } catch (XPathFactoryConfigurationException e) { 104 fail(e.getMessage()); 105 } catch (XPathExpressionException e) { 106 fail(e.getMessage()); 107 } 108 } 109 110 /** 111 * Security is enabled, extension function not allowed 112 */ 113 public void testExtFuncNotAllowed() { 114 Policy p = new SimplePolicy(new AllPermission()); 115 Policy.setPolicy(p); 116 System.setSecurityManager(new SecurityManager()); 117 118 try { 119 evaluate(false); 120 } catch (XPathFactoryConfigurationException e) { 121 fail(e.getMessage()); 122 } catch (XPathExpressionException ex) { 123 //expected since extension function is disallowed 124 System.out.println("testExtFuncNotAllowed: OK"); 125 } finally { 126 System.setSecurityManager(null); 127 } 128 } 129 130 /** 131 * Security is enabled, use new feature: enableExtensionFunctions 132 */ 133 public void testEnableExtFunc() { 134 Policy p = new SimplePolicy(new AllPermission()); 135 Policy.setPolicy(p); 136 System.setSecurityManager(new SecurityManager()); 137 138 139 try { 140 evaluate(true); 141 System.out.println("testEnableExt: OK"); 142 } catch (XPathFactoryConfigurationException e) { 143 fail(e.getMessage()); 144 } catch (XPathExpressionException e) { 145 fail(e.getMessage()); 146 } finally { 147 System.setSecurityManager(null); 148 } 149 } 150 151 Document getDocument() { 152 // the xml source 153 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); 154 DocumentBuilder documentBuilder = null; 155 Document document = null; 156 157 try { 158 documentBuilder = documentBuilderFactory.newDocumentBuilder(); 159 InputStream xmlStream = new FileInputStream(xmlFile); 160 document = documentBuilder.parse(xmlStream); 161 } catch (Exception e) { 162 fail(e.toString()); 163 } 164 return document; 165 } 166 167 void evaluate(boolean enableExt) throws XPathFactoryConfigurationException, XPathExpressionException { 168 Document document = getDocument(); 169 170 XPathFactory xPathFactory = XPathFactory.newInstance(); 171 /** 172 * Use of the extension function 'http://exslt.org/strings:tokenize' is 173 * not allowed when the secure processing feature is set to true. 174 * Attempt to use the new property to enable extension function 175 */ 176 if (enableExt) { 177 boolean isExtensionSupported = enableExtensionFunction(xPathFactory); 178 } 179 180 xPathFactory.setXPathFunctionResolver(new MyXPathFunctionResolver()); 181 if (System.getSecurityManager() == null) { 182 xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false); 183 } 184 185 XPath xPath = xPathFactory.newXPath(); 186 xPath.setNamespaceContext(new MyNamespaceContext()); 187 188 String xPathResult = xPath.evaluate(XPATH_EXPRESSION, document); 189 System.out.println( 190 "XPath result (enableExtensionFunction == " + enableExt + ") = \"" 191 + xPathResult 192 + "\""); 193 } 194 195 public class MyXPathFunctionResolver 196 implements XPathFunctionResolver { 197 198 public XPathFunction resolveFunction(QName functionName, int arity) { 199 200 // not a real ewsolver, always return a default XPathFunction 201 return new MyXPathFunction(); 202 } 203 } 204 205 public class MyXPathFunction 206 implements XPathFunction { 207 208 public Object evaluate(List list) throws XPathFunctionException { 209 210 return "Hello World"; 211 } 212 } 213 214 public class MyNamespaceContext implements NamespaceContext { 215 216 public String getNamespaceURI(String prefix) { 217 if (prefix == null) { 218 throw new IllegalArgumentException("The prefix cannot be null."); 219 } 220 221 if (prefix.equals("ext")) { 222 return "http://ext.com"; 223 } else { 224 return null; 225 } 226 } 227 228 public String getPrefix(String namespace) { 229 230 if (namespace == null) { 231 throw new IllegalArgumentException("The namespace uri cannot be null."); 232 } 233 234 if (namespace.equals("http://ext.com")) { 235 return "ext"; 236 } else { 237 return null; 238 } 239 } 240 241 public Iterator getPrefixes(String namespace) { 242 return null; 243 } 244 } 245 246 boolean enableExtensionFunction(XPathFactory factory) { 247 boolean isSupported = true; 248 try { 249 factory.setFeature(ENABLE_EXTENSION_FUNCTIONS, true); 250 } catch (XPathFactoryConfigurationException ex) { 251 isSupported = false; 252 } 253 return isSupported; 254 } 255 256 class SimplePolicy extends Policy { 257 258 private final Permissions perms; 259 260 public SimplePolicy(Permission... permissions) { 261 perms = new Permissions(); 262 for (Permission permission : permissions) { 263 perms.add(permission); 264 } 265 } 266 267 @Override 268 public PermissionCollection getPermissions(CodeSource cs) { 269 return perms; 270 } 271 272 @Override 273 public PermissionCollection getPermissions(ProtectionDomain pd) { 274 return perms; 275 } 276 277 @Override 278 public boolean implies(ProtectionDomain pd, Permission p) { 279 return perms.implies(p); 280 } 281 282 //for older jdk 283 @Override 284 public void refresh() { 285 } 286 } 287 }