diff --git a/src/main/java/org/apache/commons/jxpath/ClassFunctions.java b/src/main/java/org/apache/commons/jxpath/ClassFunctions.java index 9e77b595f..6e09419cb 100644 --- a/src/main/java/org/apache/commons/jxpath/ClassFunctions.java +++ b/src/main/java/org/apache/commons/jxpath/ClassFunctions.java @@ -23,6 +23,8 @@ import org.apache.commons.jxpath.functions.ConstructorFunction; import org.apache.commons.jxpath.functions.MethodFunction; +import org.apache.commons.jxpath.ri.JXPathFilter; +import org.apache.commons.jxpath.ri.SystemPropertyJXPathFilter; import org.apache.commons.jxpath.util.MethodLookupUtils; /** @@ -91,6 +93,21 @@ public Function getFunction( final String namespace, final String name, Object[] parameters) { + return getFunction(namespace, name, parameters, new SystemPropertyJXPathFilter()); + } + + @Override + public Function getFunction( + final String namespace, + final String name, + Object[] parameters, + JXPathFilter jxPathFilter) { + if (!jxPathFilter.isClassNameExposed(functionClass.getName())) { + throw new JXPathException( + "Extension function is not allowed: " + (namespace != null ? namespace + ":" + name : name) + + " (in " + functionClass.getName() + ")"); + } + if (namespace == null) { if (this.namespace != null) { return null; diff --git a/src/main/java/org/apache/commons/jxpath/FunctionLibrary.java b/src/main/java/org/apache/commons/jxpath/FunctionLibrary.java index dfd4e75c0..e236fa66d 100644 --- a/src/main/java/org/apache/commons/jxpath/FunctionLibrary.java +++ b/src/main/java/org/apache/commons/jxpath/FunctionLibrary.java @@ -16,6 +16,9 @@ */ package org.apache.commons.jxpath; +import org.apache.commons.jxpath.ri.JXPathFilter; +import org.apache.commons.jxpath.ri.SystemPropertyJXPathFilter; + import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -74,14 +77,20 @@ public Set getUsedNamespaces() { * @return Function found */ @Override - public Function getFunction(final String namespace, final String name, - final Object[] parameters) { + public Function getFunction(final String namespace, final String name, final Object[] parameters) { + return getFunction(namespace, name, parameters, new SystemPropertyJXPathFilter()); + } + + + @Override + public Function getFunction(final String namespace, final String name, final Object[] parameters, final JXPathFilter filter) { final Object candidates = functionCache().get(namespace); if (candidates instanceof Functions) { return ((Functions) candidates).getFunction( namespace, name, - parameters); + parameters, + filter); } if (candidates instanceof List) { final List list = (List) candidates; @@ -91,7 +100,8 @@ public Function getFunction(final String namespace, final String name, ((Functions) list.get(i)).getFunction( namespace, name, - parameters); + parameters, + filter); if (function != null) { return function; } diff --git a/src/main/java/org/apache/commons/jxpath/Functions.java b/src/main/java/org/apache/commons/jxpath/Functions.java index d3788c5c0..bd6d005b9 100644 --- a/src/main/java/org/apache/commons/jxpath/Functions.java +++ b/src/main/java/org/apache/commons/jxpath/Functions.java @@ -16,6 +16,8 @@ */ package org.apache.commons.jxpath; +import org.apache.commons.jxpath.ri.JXPathFilter; + import java.util.Set; /** @@ -43,4 +45,17 @@ public interface Functions { * @return Function */ Function getFunction(String namespace, String name, Object[] parameters); + + /** + * Returns a Function, if any, for the specified namespace, + * name and parameter types if the function is allowed by the filter. + * @param namespace ns + * @param name function name + * @param parameters Object[] + * @param filter JXPathFilter + * @return Function + */ + default Function getFunction(String namespace, String name, Object[] parameters, JXPathFilter filter) { + return getFunction(namespace, name, parameters); + } } diff --git a/src/main/java/org/apache/commons/jxpath/JXPathContext.java b/src/main/java/org/apache/commons/jxpath/JXPathContext.java index c4aac2c63..2b2153fad 100644 --- a/src/main/java/org/apache/commons/jxpath/JXPathContext.java +++ b/src/main/java/org/apache/commons/jxpath/JXPathContext.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.Locale; +import org.apache.commons.jxpath.ri.JXPathFilter; +import org.apache.commons.jxpath.ri.SystemPropertyJXPathFilter; import org.apache.commons.jxpath.util.KeyManagerUtils; /** @@ -422,6 +424,8 @@ public abstract class JXPathContext { /** decimal format map */ protected HashMap decimalFormats; + protected JXPathFilter filter; + private Locale locale; private boolean lenientSet = false; private boolean lenient = false; @@ -469,6 +473,7 @@ private static JXPathContextFactory getContextFactory () { protected JXPathContext(final JXPathContext parentContext, final Object contextBean) { this.parentContext = parentContext; this.contextBean = contextBean; + this.filter = new SystemPropertyJXPathFilter(); } /** @@ -598,6 +603,22 @@ public synchronized Locale getLocale() { return locale; } + /** + * Returns the filter that specifies which classes are allowed. + * @return JXPathFilter + */ + public JXPathFilter getFilter() { + return filter; + } + + /** + * Sets the filter for the context. + * @param filter JXPathFilter + */ + public void setFilter(JXPathFilter filter) { + this.filter = filter; + } + /** * Sets {@link DecimalFormatSymbols} for a given name. The DecimalFormatSymbols * can be referenced as the third, optional argument in the invocation of diff --git a/src/main/java/org/apache/commons/jxpath/PackageFunctions.java b/src/main/java/org/apache/commons/jxpath/PackageFunctions.java index 3a2e4a1ee..93873000f 100644 --- a/src/main/java/org/apache/commons/jxpath/PackageFunctions.java +++ b/src/main/java/org/apache/commons/jxpath/PackageFunctions.java @@ -26,6 +26,8 @@ import org.apache.commons.jxpath.functions.ConstructorFunction; import org.apache.commons.jxpath.functions.MethodFunction; +import org.apache.commons.jxpath.ri.JXPathFilter; +import org.apache.commons.jxpath.ri.SystemPropertyJXPathFilter; import org.apache.commons.jxpath.util.ClassLoaderUtil; import org.apache.commons.jxpath.util.MethodLookupUtils; import org.apache.commons.jxpath.util.TypeUtils; @@ -116,6 +118,15 @@ public Function getFunction( final String namespace, final String name, Object[] parameters) { + return getFunction(namespace, name, parameters, new SystemPropertyJXPathFilter()); + } + + @Override + public Function getFunction(final String namespace, final String name, Object[] parameters, final JXPathFilter filter) { + if (filter == null) { + throw new JXPathException("No extension function is allowed"); + } + if (!Objects.equals(this.namespace, namespace)) { return null; } @@ -124,6 +135,7 @@ public Function getFunction( parameters = EMPTY_ARRAY; } + String functionName = namespace != null ? namespace + ":" + name : name; if (parameters.length >= 1) { Object target = TypeUtils.convert(parameters[0], Object.class); if (target != null) { @@ -133,7 +145,7 @@ public Function getFunction( name, parameters); if (method != null) { - return new MethodFunction(method); + return new MethodFunction(method, filter); } if (target instanceof NodeSet) { @@ -146,7 +158,7 @@ public Function getFunction( name, parameters); if (method != null) { - return new MethodFunction(method); + return new MethodFunction(method, filter); } if (target instanceof Collection) { @@ -169,7 +181,7 @@ public Function getFunction( name, parameters); if (method != null) { - return new MethodFunction(method); + return new MethodFunction(method, filter); } } } @@ -185,12 +197,11 @@ public Function getFunction( Class functionClass; try { - functionClass = ClassLoaderUtil.getClass(className, true); + functionClass = ClassLoaderUtil.getClass(className, true, filter); } catch (final ClassNotFoundException ex) { throw new JXPathException( - "Cannot invoke extension function " - + (namespace != null ? namespace + ":" + name : name), + "Cannot invoke extension function " + functionName, ex); } @@ -208,7 +219,7 @@ public Function getFunction( methodName, parameters); if (method != null) { - return new MethodFunction(method); + return new MethodFunction(method, filter); } } return null; diff --git a/src/main/java/org/apache/commons/jxpath/functions/ConstructorFunction.java b/src/main/java/org/apache/commons/jxpath/functions/ConstructorFunction.java index 9c07f45fc..05dcc610d 100644 --- a/src/main/java/org/apache/commons/jxpath/functions/ConstructorFunction.java +++ b/src/main/java/org/apache/commons/jxpath/functions/ConstructorFunction.java @@ -22,6 +22,8 @@ import org.apache.commons.jxpath.ExpressionContext; import org.apache.commons.jxpath.Function; import org.apache.commons.jxpath.JXPathInvalidAccessException; +import org.apache.commons.jxpath.ri.JXPathFilter; +import org.apache.commons.jxpath.ri.SystemPropertyJXPathFilter; import org.apache.commons.jxpath.util.TypeUtils; /** @@ -32,12 +34,19 @@ public class ConstructorFunction implements Function { private final Constructor constructor; + private final JXPathFilter filter; + /** * Create a new ConstructorFunction. * @param constructor the constructor to call. */ public ConstructorFunction(final Constructor constructor) { + this(constructor, new SystemPropertyJXPathFilter()); + } + + public ConstructorFunction(final Constructor constructor, JXPathFilter filter) { this.constructor = constructor; + this.filter = filter; } /** @@ -66,6 +75,11 @@ public Object invoke(final ExpressionContext context, Object[] parameters) { for (int i = 0; i < parameters.length; i++) { args[i + pi] = TypeUtils.convert(parameters[i], types[i + pi]); } + + if (!filter.isClassNameExposed(constructor.getDeclaringClass().getName())) { + throw new Exception("Calling constructors is not allowed for class: " + constructor.getDeclaringClass().getName()); + } + return constructor.newInstance(args); } catch (Throwable ex) { diff --git a/src/main/java/org/apache/commons/jxpath/functions/MethodFunction.java b/src/main/java/org/apache/commons/jxpath/functions/MethodFunction.java index 28dd87d31..26579ae95 100644 --- a/src/main/java/org/apache/commons/jxpath/functions/MethodFunction.java +++ b/src/main/java/org/apache/commons/jxpath/functions/MethodFunction.java @@ -23,6 +23,8 @@ import org.apache.commons.jxpath.ExpressionContext; import org.apache.commons.jxpath.Function; import org.apache.commons.jxpath.JXPathInvalidAccessException; +import org.apache.commons.jxpath.ri.JXPathFilter; +import org.apache.commons.jxpath.ri.SystemPropertyJXPathFilter; import org.apache.commons.jxpath.util.TypeUtils; import org.apache.commons.jxpath.util.ValueUtils; @@ -34,12 +36,24 @@ public class MethodFunction implements Function { private final Method method; private static final Object[] EMPTY_ARRAY = {}; + private final JXPathFilter filter; + /** * Create a new MethodFunction. * @param method implementing Method */ public MethodFunction(final Method method) { + this(method, new SystemPropertyJXPathFilter()); + } + + /** + * Create a new MethodFunction. + * @param method implementing Method + * @param filter JXPathFilter + */ + public MethodFunction(final Method method, final JXPathFilter filter) { this.method = ValueUtils.getAccessibleMethod(method); + this.filter = filter; } @Override @@ -88,7 +102,11 @@ public Object invoke(final ExpressionContext context, Object[] parameters) { } } + if (!filter.isClassNameExposed(method.getDeclaringClass().getName())) { + throw new Exception("Calling method is not allowed: " + method.getDeclaringClass() + "." + method.getName() + "()"); + } return method.invoke(target, args); + } catch (Throwable ex) { if (ex instanceof InvocationTargetException) { diff --git a/src/main/java/org/apache/commons/jxpath/ri/AbstractJXPathFilter.java b/src/main/java/org/apache/commons/jxpath/ri/AbstractJXPathFilter.java new file mode 100644 index 000000000..b4ec9affc --- /dev/null +++ b/src/main/java/org/apache/commons/jxpath/ri/AbstractJXPathFilter.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jxpath.ri; + +import java.util.Objects; +import java.util.Set; + +public class AbstractJXPathFilter implements JXPathFilter { + protected final Set allowedClasses; + + public AbstractJXPathFilter(final Set allowedClasses) { + this.allowedClasses = allowedClasses; + } + + /** + * Specifies whether the Java class of the specified name be exposed via xpath + * + * @param className is the fully qualified name of the java class being checked. + * This will not be null. Only non-array class names will be passed. + * @return true if the java class can be exposed via xpath, false otherwise + */ + @Override + public boolean isClassNameExposed(String className) { + if (allowedClasses.isEmpty()) { + return false; + } + + if (allowedClasses.contains("*")) { + return true; + } + + return allowedClasses.stream().anyMatch(pattern -> { + if (Objects.equals(className, pattern)) { + return true; + } + else if (pattern.endsWith("*")) { + return className.startsWith(pattern.substring(0, pattern.length() - 1)); + } + return false; + }); + } +} diff --git a/src/main/java/org/apache/commons/jxpath/ri/CustomJXPathFilter.java b/src/main/java/org/apache/commons/jxpath/ri/CustomJXPathFilter.java new file mode 100644 index 000000000..d28e56c8c --- /dev/null +++ b/src/main/java/org/apache/commons/jxpath/ri/CustomJXPathFilter.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jxpath.ri; + +import java.util.Collections; +import java.util.Set; + +/** + * A filter to be used by JXPath based on a configurable custom list of pattern + * provided to the constructor. + */ +public class CustomJXPathFilter extends AbstractJXPathFilter { + + public CustomJXPathFilter(Set allowedClasses) { + super(Collections.unmodifiableSet(allowedClasses)); + } +} diff --git a/src/main/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImpl.java b/src/main/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImpl.java index 2d7319944..08444f8b9 100644 --- a/src/main/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImpl.java +++ b/src/main/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImpl.java @@ -765,7 +765,7 @@ public Function getFunction(final QName functionName, final Object[] parameters) while (funcCtx != null) { funcs = funcCtx.getFunctions(); if (funcs != null) { - func = funcs.getFunction(namespace, name, parameters); + func = funcs.getFunction(namespace, name, parameters, filter); if (func != null) { return func; } diff --git a/src/main/java/org/apache/commons/jxpath/ri/JXPathFilter.java b/src/main/java/org/apache/commons/jxpath/ri/JXPathFilter.java new file mode 100644 index 000000000..d66fe2c3d --- /dev/null +++ b/src/main/java/org/apache/commons/jxpath/ri/JXPathFilter.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jxpath.ri; + +/** + * Class filter (optional) to be used by JXPath. + * + * System property "jxpath.class.allow" can be set to specify the list of allowed classnames. + * This property takes a list of java classnames (use comma as separator to specify more than one class). + * If this property is not set, it exposes no java classes + * Ex: jxpath.class.allow=java.lang.Runtime will allow exposing java.lang.Runtime class via xpath, while all other + * classes will be not exposed. You can use the wildcard (*) to allow all classes. + * @since 1.4 + */ +public interface JXPathFilter { + + /** + * Should the Java class of the specified name be exposed via xpath? + * @param className is the fully qualified name of the java class being + * checked. This will not be null. Only non-array class names will be + * passed. + * @return true if the java class can be exposed via xpath, false otherwise + */ + boolean isClassNameExposed(String className); +} diff --git a/src/main/java/org/apache/commons/jxpath/ri/SystemPropertyJXPathFilter.java b/src/main/java/org/apache/commons/jxpath/ri/SystemPropertyJXPathFilter.java new file mode 100644 index 000000000..5e34a1b1c --- /dev/null +++ b/src/main/java/org/apache/commons/jxpath/ri/SystemPropertyJXPathFilter.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jxpath.ri; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * A filter to be used by JXPath based on the system property jxpath.class.allow. + * This property is a comma separated list of patterns defining which classes + * are allowed to be loaded by JXPath. + */ +public class SystemPropertyJXPathFilter extends AbstractJXPathFilter { + + public SystemPropertyJXPathFilter() { + super(loadAllowedClassesFromSystemProperty()); + } + + private static Set loadAllowedClassesFromSystemProperty() { + final String allowedClasses = System.getProperty("jxpath.class.allow"); + List allowedClassesList = + allowedClasses != null && !allowedClasses.isEmpty() + ? Arrays.asList(allowedClasses.split(",")) + : Collections.emptyList(); + return Collections.unmodifiableSet(new HashSet<>(allowedClassesList)); + } +} diff --git a/src/main/java/org/apache/commons/jxpath/util/ClassLoaderUtil.java b/src/main/java/org/apache/commons/jxpath/util/ClassLoaderUtil.java index fa1db5e66..0f0281da7 100644 --- a/src/main/java/org/apache/commons/jxpath/util/ClassLoaderUtil.java +++ b/src/main/java/org/apache/commons/jxpath/util/ClassLoaderUtil.java @@ -16,6 +16,9 @@ */ package org.apache.commons.jxpath.util; +import org.apache.commons.jxpath.ri.JXPathFilter; +import org.apache.commons.jxpath.ri.SystemPropertyJXPathFilter; + import java.util.HashMap; import java.util.Map; @@ -68,12 +71,19 @@ private static void addAbbreviation(final String primitive, final String abbrevi * @param classLoader the class loader to use to load the class * @param className the class name * @param initialize whether the class must be initialized + * @param jxPathFilter the XPath filter * @return the class represented by className using the classLoader * @throws ClassNotFoundException if the class is not found */ - public static Class getClass(final ClassLoader classLoader, final String className, final boolean initialize) + public static Class getClass(final ClassLoader classLoader, final String className, final boolean initialize, final JXPathFilter jxPathFilter) throws ClassNotFoundException { Class clazz; + + // give chance to ClassFilter to filter out, if present + if (jxPathFilter == null || !jxPathFilter.isClassNameExposed(className)) { + throw new ClassNotFoundException(className); + } + if (abbreviationMap.containsKey(className)) { final String clsName = "[" + abbreviationMap.get(className); clazz = Class.forName(clsName, initialize, classLoader).getComponentType(); @@ -84,6 +94,38 @@ public static Class getClass(final ClassLoader classLoader, final String classNa return clazz; } + /** + * Returns the class represented by className using the + * classLoader. This implementation supports names like + * "java.lang.String[]" as well as "[Ljava.lang.String;". + * + * @param classLoader the class loader to use to load the class + * @param className the class name + * @param initialize whether the class must be initialized + * @return the class represented by className using the classLoader + * @throws ClassNotFoundException if the class is not found + */ + public static Class getClass(ClassLoader classLoader, String className, boolean initialize) + throws ClassNotFoundException { + return getClass(classLoader, className, initialize, new SystemPropertyJXPathFilter()); + } + + /** + * Returns the (initialized) class represented by className + * using the classLoader. This implementation supports names + * like "java.lang.String[]" as well as + * "[Ljava.lang.String;". + * + * @param classLoader the class loader to use to load the class + * @param className the class name + * @param jxPathFilter the XPath filter + * @return the class represented by className using the classLoader + * @throws ClassNotFoundException if the class is not found + */ + public static Class getClass(ClassLoader classLoader, String className, JXPathFilter jxPathFilter) throws ClassNotFoundException { + return getClass(classLoader, className, true, jxPathFilter); + } + /** * Returns the (initialized) class represented by className * using the classLoader. This implementation supports names @@ -96,7 +138,7 @@ public static Class getClass(final ClassLoader classLoader, final String classNa * @throws ClassNotFoundException if the class is not found */ public static Class getClass(final ClassLoader classLoader, final String className) throws ClassNotFoundException { - return getClass(classLoader, className, true); + return getClass(classLoader, className, true, new SystemPropertyJXPathFilter()); } /** @@ -110,7 +152,22 @@ public static Class getClass(final ClassLoader classLoader, final String classNa * @throws ClassNotFoundException if the class is not found */ public static Class getClass(final String className) throws ClassNotFoundException { - return getClass(className, true); + return getClass(className, true, new SystemPropertyJXPathFilter()); + } + + /** + * Returns the (initialized) class represented by className + * using the current thread's context class loader. This implementation + * supports names like "java.lang.String[]" as well as + * "[Ljava.lang.String;". + * + * @param className the class name + * @param jxPathFilter the XPath filter + * @return the class represented by className using the current thread's context class loader + * @throws ClassNotFoundException if the class is not found + */ + public static Class getClass(String className, JXPathFilter jxPathFilter) throws ClassNotFoundException { + return getClass(className, true, jxPathFilter); } /** @@ -125,17 +182,33 @@ public static Class getClass(final String className) throws ClassNotFoundExcepti * @throws ClassNotFoundException if the class is not found */ public static Class getClass(final String className, final boolean initialize) throws ClassNotFoundException { + return getClass(className, initialize, new SystemPropertyJXPathFilter()); + } + + /** + * Returns the class represented by className using the + * current thread's context class loader. This implementation supports + * names like "java.lang.String[]" as well as + * "[Ljava.lang.String;". + * + * @param className the class name + * @param initialize whether the class must be initialized + * @param jxPathFilter the XPath filter + * @return the class represented by className using the current thread's context class loader + * @throws ClassNotFoundException if the class is not found + */ + public static Class getClass(final String className, final boolean initialize, final JXPathFilter jxPathFilter) throws ClassNotFoundException { final ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); final ClassLoader currentCL = ClassLoaderUtil.class.getClassLoader(); if (contextCL != null) { try { - return getClass(contextCL, className, initialize); + return getClass(contextCL, className, initialize, jxPathFilter); } catch (final ClassNotFoundException ignore) { // NOPMD // ignore this exception and try the current class loader } } - return getClass(currentCL, className, initialize); + return getClass(currentCL, className, initialize, jxPathFilter); } /** diff --git a/src/test/java/org/apache/commons/jxpath/BasicNodeSetTest.java b/src/test/java/org/apache/commons/jxpath/BasicNodeSetTest.java index 26643511e..d4066b1f3 100644 --- a/src/test/java/org/apache/commons/jxpath/BasicNodeSetTest.java +++ b/src/test/java/org/apache/commons/jxpath/BasicNodeSetTest.java @@ -35,10 +35,17 @@ public class BasicNodeSetTest extends JXPathTestCase { @Override protected void setUp() throws Exception { super.setUp(); + System.setProperty("jxpath.class.allow", "*"); context = JXPathContext.newContext(new TestMixedModelBean()); nodeSet = new BasicNodeSet(); } + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + /** * Add the pointers for the specified path to nodeSet. * diff --git a/src/test/java/org/apache/commons/jxpath/issues/JXPath113Test.java b/src/test/java/org/apache/commons/jxpath/issues/JXPath113Test.java index 57f894c2f..073c939ec 100644 --- a/src/test/java/org/apache/commons/jxpath/issues/JXPath113Test.java +++ b/src/test/java/org/apache/commons/jxpath/issues/JXPath113Test.java @@ -29,6 +29,17 @@ public class JXPath113Test extends JXPathTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } public void testIssue113() throws Exception { diff --git a/src/test/java/org/apache/commons/jxpath/issues/JXPath118Test.java b/src/test/java/org/apache/commons/jxpath/issues/JXPath118Test.java index 93c9c3fd8..4138a61d5 100644 --- a/src/test/java/org/apache/commons/jxpath/issues/JXPath118Test.java +++ b/src/test/java/org/apache/commons/jxpath/issues/JXPath118Test.java @@ -29,6 +29,17 @@ */ public class JXPath118Test extends TestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } public void testJXPATH118IssueWithAsPath() throws Exception { diff --git a/src/test/java/org/apache/commons/jxpath/issues/JXPath149Test.java b/src/test/java/org/apache/commons/jxpath/issues/JXPath149Test.java index dc4558f7d..b2d4d0bc0 100644 --- a/src/test/java/org/apache/commons/jxpath/issues/JXPath149Test.java +++ b/src/test/java/org/apache/commons/jxpath/issues/JXPath149Test.java @@ -21,6 +21,18 @@ public class JXPath149Test extends JXPathTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + public void testComplexOperationWithVariables() { final JXPathContext context = JXPathContext.newContext(null); context.getVariables().declareVariable("a", Integer.valueOf(0)); diff --git a/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java b/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java index 6899ab753..282ec2403 100644 --- a/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java +++ b/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java @@ -36,6 +36,18 @@ public static TestSuite suite() return new TestSuite(JXPath172DynamicTest.class); } + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + public void testIssue172_propertyExistAndIsNotNull() { final JXPathContext context = getContext("ciao", false); diff --git a/src/test/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImplTestCase.java b/src/test/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImplTestCase.java index 369ccdf80..17f83c49c 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImplTestCase.java +++ b/src/test/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImplTestCase.java @@ -17,11 +17,24 @@ package org.apache.commons.jxpath.ri; +import org.apache.commons.jxpath.JXPathTestCase; import org.apache.commons.jxpath.ri.model.container.ContainerPointerFactory; +import org.apache.commons.jxpath.JXPathContext; -import junit.framework.TestCase; -public class JXPathContextReferenceImplTestCase extends TestCase { +public class JXPathContextReferenceImplTestCase extends JXPathTestCase { + + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "org.apache.commons.jxpath.ri.JXPathContextFactoryReferenceImpl"); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + System.clearProperty("jxpath.class.allow"); + } /** * https://issues.apache.org/jira/browse/JXPATH-166 @@ -36,4 +49,15 @@ public void testInit() { } } } + + public void testDangerousClass() { + try { + JXPathContext context = JXPathContext.newContext(new Object() {}); + String jxPath = "run(newInstance(loadClass(getClassLoader(getClass(/)), \"org.apache.commons.jxpath.ri.TestDangerousClass\")), \"blabla\")"; + context.getValue(jxPath); + fail("failed to block org.apache.commons.jxpath.ri.TestDangerousClass.run()"); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Calling method is not allowed: class java.lang.Object.getClass()")); + } + } } diff --git a/src/test/java/org/apache/commons/jxpath/ri/TestDangerousClass.java b/src/test/java/org/apache/commons/jxpath/ri/TestDangerousClass.java new file mode 100644 index 000000000..93cb575aa --- /dev/null +++ b/src/test/java/org/apache/commons/jxpath/ri/TestDangerousClass.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jxpath.ri; + +/** + * A test class with few methods, with different argument list + */ +public final class TestDangerousClass { + + static { + System.out.println("TestDangerousClass created: static block!"); + } + + public TestDangerousClass() { + System.out.println("TestDangerousClass: constructor!"); + } + + public void run(String param) { + System.out.printf("Running dangerous test with parameter '%s'!%n", param); +// System.exit(42); + } + +} diff --git a/src/test/java/org/apache/commons/jxpath/ri/compiler/CoreFunctionTest.java b/src/test/java/org/apache/commons/jxpath/ri/compiler/CoreFunctionTest.java index 4610d2550..342f0092d 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/compiler/CoreFunctionTest.java +++ b/src/test/java/org/apache/commons/jxpath/ri/compiler/CoreFunctionTest.java @@ -39,6 +39,7 @@ public class CoreFunctionTest extends JXPathTestCase { @Override public void setUp() { + System.setProperty("jxpath.class.allow", "*"); if (context == null) { context = JXPathContext.newContext(new TestMixedModelBean()); final Variables vars = context.getVariables(); @@ -48,6 +49,12 @@ public void setUp() { } } + @Override + protected void tearDown() throws Exception { + super.tearDown(); + System.clearProperty("jxpath.class.allow"); + } + public void testCoreFunctions() { assertXPathValue(context, "string(2)", "2"); assertXPathValue(context, "string($nan)", "NaN"); diff --git a/src/test/java/org/apache/commons/jxpath/ri/compiler/ExtensionFunctionTest.java b/src/test/java/org/apache/commons/jxpath/ri/compiler/ExtensionFunctionTest.java index 7ab105e9f..fa04c6ef5 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/compiler/ExtensionFunctionTest.java +++ b/src/test/java/org/apache/commons/jxpath/ri/compiler/ExtensionFunctionTest.java @@ -16,23 +16,22 @@ */ package org.apache.commons.jxpath.ri.compiler; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; +import java.util.*; -import org.apache.commons.jxpath.ClassFunctions; -import org.apache.commons.jxpath.ExpressionContext; -import org.apache.commons.jxpath.Function; -import org.apache.commons.jxpath.FunctionLibrary; +import org.apache.commons.jxpath.JXPathTestCase; import org.apache.commons.jxpath.Functions; import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.jxpath.JXPathTestCase; -import org.apache.commons.jxpath.NodeSet; -import org.apache.commons.jxpath.PackageFunctions; -import org.apache.commons.jxpath.Pointer; import org.apache.commons.jxpath.TestBean; import org.apache.commons.jxpath.Variables; +import org.apache.commons.jxpath.FunctionLibrary; +import org.apache.commons.jxpath.ClassFunctions; +import org.apache.commons.jxpath.PackageFunctions; +import org.apache.commons.jxpath.NodeSet; +import org.apache.commons.jxpath.Function; +import org.apache.commons.jxpath.ExpressionContext; +import org.apache.commons.jxpath.Pointer; +import org.apache.commons.jxpath.ri.CustomJXPathFilter; +import org.apache.commons.jxpath.ri.SystemPropertyJXPathFilter; import org.apache.commons.jxpath.ri.model.NodePointer; import org.apache.commons.jxpath.util.JXPath11CompatibleTypeConverter; import org.apache.commons.jxpath.util.TypeConverter; @@ -46,9 +45,11 @@ public class ExtensionFunctionTest extends JXPathTestCase { private JXPathContext context; private TestBean testBean; private TypeConverter typeConverter; + private final String DEFAULT_ALLOW_LIST = "org.w3c.*,org.jdom.*,java.lang.String,java.util.*,org.apache.commons.*"; @Override public void setUp() { + System.setProperty("jxpath.class.allow", DEFAULT_ALLOW_LIST); if (context == null) { testBean = new TestBean(); context = JXPathContext.newContext(testBean); @@ -75,6 +76,7 @@ public void setUp() { @Override public void tearDown() { TypeUtils.setTypeConverter(typeConverter); + System.clearProperty("jxpath.class.allow"); } public void testConstructorLookup() { @@ -384,6 +386,151 @@ public void testBCNodeSetHack() { Boolean.TRUE); } + public void testClassFunctionsWithoutClassFilter() { + System.setProperty("jxpath.class.allow", "org.w3c.*,org.jdom.*,java.lang.String,java.util.*"); + Function classFunction = null; + try { + Functions iFunctions = new ClassFunctions(TestFunctions3.class, "test3"); + classFunction = iFunctions.getFunction("test3", "testFunction3Method1", null); + } catch (Throwable t) { + assertTrue((t.getMessage().contains("Extension function is not allowed: test3:testFunction3Method1 (in org.apache.commons.jxpath.ri.compiler.TestFunctions3)"))); + } finally { + assertNull(classFunction); + System.setProperty("jxpath.class.allow", DEFAULT_ALLOW_LIST); + } + } + + public void testClassFunctionsWithClassFilter() { + Function classFunction = null; + try { + Functions iFunctions = new ClassFunctions(TestFunctions2.class, "test"); + classFunction = iFunctions.getFunction("test", "increment", new Object[]{8}); + } catch (Throwable t) { + fail(t.getMessage()); + } finally { + assertNotNull(classFunction); + } + } + + public void testPackageFunctionsWithoutClassFilter() { + System.setProperty("jxpath.class.allow", "org.w3c.*,org.jdom.*,java.lang.String,java.util.*"); + Function packageFunction = null; + try { + Functions iFunctions = new PackageFunctions("org.apache.commons.jxpath.ri.compiler.", "jxpathtests"); + packageFunction = iFunctions.getFunction("jxpathtests", "TestFunctions3.testFunction3Method1", null); + throw new Exception("testPackageFunctionsWithClassFilter() failed."); + } catch (Throwable t) { + assertTrue((t.getMessage().contains("Cannot invoke extension function jxpathtests:TestFunctions3.testFunction3Method1; org.apache.commons.jxpath.ri.compiler.TestFunctions3")) + || (t.getMessage().contains("java.lang.ClassNotFoundException: org.apache.commons.jxpath.ri.compiler.TestFunctions3"))); + } finally { + assertNull(packageFunction); + System.setProperty("jxpath.class.allow", DEFAULT_ALLOW_LIST); + } + } + + public void testPackageFunctionsWithClassFilter() { + System.setProperty("jxpath.class.allow", "org.apache.commons.jxpath.ri.compiler.TestFunctions3"); + Function packageFunction = null; + try { + Functions iFunctions = new PackageFunctions("org.apache.commons.jxpath.ri.compiler.", "jxpathtests"); + packageFunction = iFunctions.getFunction("jxpathtests", "TestFunctions3.testFunction3Method1", null); + } catch (Throwable t) { + fail(t.getMessage()); + } finally { + assertNotNull(packageFunction); + System.setProperty("jxpath.class.allow", DEFAULT_ALLOW_LIST); + } + } + + public void testJXPathContextFunctionsWithoutClassFilter() { + String failedMethods = ""; + try { + context.iterate("java.lang.Thread.sleep(5)"); + throw new Exception("testJXPathContextFunctionsWithClassFilter() failed for iterate()"); + } catch (Throwable t) { + if (!t.getMessage().contains("Cannot invoke extension function java.lang.Thread.sleep; java.lang.Thread") + && !t.getMessage().contains("java.lang.ClassNotFoundException: java.lang.Thread")) { + failedMethods = "org.apache.commons.jxpath.JXPathContext.iterate()"; + } + } + + try { + context.selectSingleNode("java.lang.Thread.sleep(5)"); + throw new Exception("testJXPathContextFunctionsWithClassFilter() failed for iterate()"); + } catch (Throwable t) { + if (!(t.getMessage().contains("Cannot invoke extension function java.lang.Thread.sleep; java.lang.Thread")) + && !(t.getMessage().contains("java.lang.ClassNotFoundException: java.lang.Thread"))) { + failedMethods += ("".equals(failedMethods) ? "org.apache.commons.jxpath.JXPathContext.selectSingleNode()" : ", org.apache.commons.jxpath.JXPathContext.selectSingleNode()"); + } + } + if (!failedMethods.isEmpty()) { + fail("Failed filtering for methods: " + failedMethods); + } + } + + public void testJXPathContextFunctionsWithSystemPropertyFilter() { + try { + System.setProperty("jxpath.class.allow", "java.lang.Thread"); + context.setFilter(new SystemPropertyJXPathFilter()); + long startTime = System.currentTimeMillis(); + context.iterate("java.lang.Thread.sleep(5)"); + assertTrue(System.currentTimeMillis() >= startTime + 5); + + startTime = System.currentTimeMillis(); + context.selectSingleNode("java.lang.Thread.sleep(5)"); + assertTrue(System.currentTimeMillis() >= startTime + 5); + } catch (Throwable t) { + fail(t.getMessage()); + } finally { + System.setProperty("jxpath.class.allow", DEFAULT_ALLOW_LIST); + } + } + + public void testJXPathAllowContextFunctionsWithCustomFilter() { + try { + System.clearProperty("jxpath.class.allow"); + context.setFilter(new CustomJXPathFilter(new HashSet<>(Collections.singletonList("java.lang.Thread")))); + long startTime = System.currentTimeMillis(); + context.iterate("java.lang.Thread.sleep(5)"); + assertTrue(System.currentTimeMillis() >= startTime + 5); + + startTime = System.currentTimeMillis(); + context.selectSingleNode("java.lang.Thread.sleep(5)"); + assertTrue(System.currentTimeMillis() >= startTime + 5); + } catch (Throwable t) { + fail(t.getMessage()); + } finally { + System.setProperty("jxpath.class.allow", DEFAULT_ALLOW_LIST); + } + } + + public void testJXPathDenyContextFunctionsWithCustomFilter() { + System.setProperty("jxpath.class.allow", "*"); + context.setFilter(new CustomJXPathFilter(Collections.emptySet())); + try { + context.iterate("java.lang.Thread.sleep(5)"); + throw new Exception("testJXPathDenyContextFunctionsWithCustomFilter() failed for iterate()"); + } catch (Throwable t) { + if (!(t.getMessage().contains("Cannot invoke extension function java.lang.Thread.sleep; java.lang.Thread")) + && !(t.getMessage().contains("java.lang.ClassNotFoundException: java.lang.Thread"))) { + fail("failed to deny calling java.lang.Thread.sleep(5)"); + } + } + + context.setFilter(new CustomJXPathFilter(Collections.emptySet())); + try { + context.selectSingleNode("java.lang.Thread.sleep(5)"); + throw new Exception("testJXPathDenyContextFunctionsWithCustomFilter() failed for iterate()"); + } catch (Throwable t) { + if (!(t.getMessage().contains("Cannot invoke extension function java.lang.Thread.sleep; java.lang.Thread")) + && !(t.getMessage().contains("java.lang.ClassNotFoundException: java.lang.Thread"))) { + fail("failed to deny calling java.lang.Thread.sleep(5)"); + } + } + + System.setProperty("jxpath.class.allow", DEFAULT_ALLOW_LIST); + } + private static class Context implements ExpressionContext { private final Object object; diff --git a/src/test/java/org/apache/commons/jxpath/ri/compiler/TestFunctions3.java b/src/test/java/org/apache/commons/jxpath/ri/compiler/TestFunctions3.java new file mode 100644 index 000000000..0205041c8 --- /dev/null +++ b/src/test/java/org/apache/commons/jxpath/ri/compiler/TestFunctions3.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jxpath.ri.compiler; + +/** + * A test class with few methods, with different argument list + */ +public final class TestFunctions3 { + + static { + System.out.println("TestFunctions3: static block..."); + } + + public TestFunctions3() { + System.out.println("TestFunctions3: constructor..."); + } + + public static String testFunction3Method1() { + System.out.println("TestFunctions3: testFunction3Method1 method..."); + return "testFunction3Method1"; + } + + public String testFunction3Method2(String str) { + System.out.println("TestFunctions3: testFunction3Method2 method..." + str); + return "testFunction3Method2:" + str; + } + + public String testFunction3Method3(String str1, String str2) { + System.out.println("TestFunctions3: testFunction3Method3 method..." + str1 + ", " + str2); + return "testFunction3Method3:" + str1 + ":" + str2; + } + +} diff --git a/src/test/java/org/apache/commons/jxpath/ri/model/AliasedNamespaceIterationTest.java b/src/test/java/org/apache/commons/jxpath/ri/model/AliasedNamespaceIterationTest.java index 4c97e2bbd..db693ac02 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/model/AliasedNamespaceIterationTest.java +++ b/src/test/java/org/apache/commons/jxpath/ri/model/AliasedNamespaceIterationTest.java @@ -24,14 +24,24 @@ /** * Test aliased/doubled XML namespace iteration; JXPATH-125. - * */ public class AliasedNamespaceIterationTest extends JXPathTestCase { protected JXPathContext context; + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + protected DocumentContainer createDocumentContainer(final String model) { - final DocumentContainer result = new DocumentContainer(JXPathTestCase.class - .getResource("IterateAliasedNS.xml"), model); + final DocumentContainer result = new DocumentContainer(JXPathTestCase.class.getResource("IterateAliasedNS.xml"), model); return result; } diff --git a/src/test/java/org/apache/commons/jxpath/ri/model/BeanModelTestCase.java b/src/test/java/org/apache/commons/jxpath/ri/model/BeanModelTestCase.java index fa9ee56b2..c8a948555 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/model/BeanModelTestCase.java +++ b/src/test/java/org/apache/commons/jxpath/ri/model/BeanModelTestCase.java @@ -42,14 +42,22 @@ public abstract class BeanModelTestCase extends JXPathTestCase { private JXPathContext context; @Override - public void setUp() { + public void setUp() throws Exception { // if (context == null) { - context = JXPathContext.newContext(createContextBean()); - context.setLocale(Locale.US); - context.setFactory(getAbstractFactory()); + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + context = JXPathContext.newContext(createContextBean()); + context.setLocale(Locale.US); + context.setFactory(getAbstractFactory()); // } } + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + protected abstract Object createContextBean(); protected abstract AbstractFactory getAbstractFactory(); diff --git a/src/test/java/org/apache/commons/jxpath/ri/model/JXPath154Test.java b/src/test/java/org/apache/commons/jxpath/ri/model/JXPath154Test.java index eff6253eb..7352365c9 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/model/JXPath154Test.java +++ b/src/test/java/org/apache/commons/jxpath/ri/model/JXPath154Test.java @@ -25,6 +25,18 @@ public class JXPath154Test extends JXPathTestCase { protected JXPathContext context; + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + protected DocumentContainer createDocumentContainer(final String model) { return new DocumentContainer(JXPathTestCase.class.getResource("InnerEmptyNamespace.xml"), model); } diff --git a/src/test/java/org/apache/commons/jxpath/ri/model/MixedModelTest.java b/src/test/java/org/apache/commons/jxpath/ri/model/MixedModelTest.java index e4b23d53f..0473c9c53 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/model/MixedModelTest.java +++ b/src/test/java/org/apache/commons/jxpath/ri/model/MixedModelTest.java @@ -41,6 +41,7 @@ public class MixedModelTest extends JXPathTestCase { @Override public void setUp() { + System.setProperty("jxpath.class.allow", "java.util.*,org.apache.commons.jxpath.*"); final TestMixedModelBean bean = new TestMixedModelBean(); context = JXPathContext.newContext(bean); context.setFactory(new TestMixedModelFactory()); @@ -61,6 +62,12 @@ public void setUp() { vars.declareVariable("matrix", matrix); } + @Override + protected void tearDown() throws Exception { + super.tearDown(); + System.clearProperty("jxpath.class.allow"); + } + public void testVar() { context.getVariables().declareVariable("foo:bar", "baz"); diff --git a/src/test/java/org/apache/commons/jxpath/ri/model/XMLModelTestCase.java b/src/test/java/org/apache/commons/jxpath/ri/model/XMLModelTestCase.java index 4939cf9c3..2a81d7dc9 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/model/XMLModelTestCase.java +++ b/src/test/java/org/apache/commons/jxpath/ri/model/XMLModelTestCase.java @@ -36,6 +36,7 @@ public abstract class XMLModelTestCase extends JXPathTestCase { @Override public void setUp() { + System.setProperty("jxpath.class.allow", "*"); if (context == null) { final DocumentContainer docCtr = createDocumentContainer(); context = createContext(); @@ -46,6 +47,12 @@ public void setUp() { } } + @Override + protected void tearDown() throws Exception { + super.tearDown(); + System.clearProperty("jxpath.class.allow"); + } + protected abstract String getModel(); protected DocumentContainer createDocumentContainer() { diff --git a/src/test/java/org/apache/commons/jxpath/ri/model/XMLSpaceTest.java b/src/test/java/org/apache/commons/jxpath/ri/model/XMLSpaceTest.java index bdbe0ab4e..e0f826386 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/model/XMLSpaceTest.java +++ b/src/test/java/org/apache/commons/jxpath/ri/model/XMLSpaceTest.java @@ -26,6 +26,18 @@ public class XMLSpaceTest extends JXPathTestCase { protected JXPathContext context; + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + protected DocumentContainer createDocumentContainer(final String model) { return new DocumentContainer(JXPathTestCase.class .getResource("XmlSpace.xml"), model); diff --git a/src/test/java/org/apache/commons/jxpath/ri/model/XMLUpperCaseElementsTest.java b/src/test/java/org/apache/commons/jxpath/ri/model/XMLUpperCaseElementsTest.java index afa65c487..cfe11b7af 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/model/XMLUpperCaseElementsTest.java +++ b/src/test/java/org/apache/commons/jxpath/ri/model/XMLUpperCaseElementsTest.java @@ -27,6 +27,18 @@ public class XMLUpperCaseElementsTest extends JXPathTestCase { protected JXPathContext context; + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + protected DocumentContainer createDocumentContainer(final String model) { return new DocumentContainer(JXPathTestCase.class.getResource("VendorUpper.xml"), model); } diff --git a/src/test/java/org/apache/commons/jxpath/servlet/JXPathServletContextTest.java b/src/test/java/org/apache/commons/jxpath/servlet/JXPathServletContextTest.java index 0b8159240..028fd95c7 100644 --- a/src/test/java/org/apache/commons/jxpath/servlet/JXPathServletContextTest.java +++ b/src/test/java/org/apache/commons/jxpath/servlet/JXPathServletContextTest.java @@ -38,6 +38,18 @@ */ public class JXPathServletContextTest extends TestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + System.setProperty("jxpath.class.allow", "*"); + } + + @Override + public void tearDown() throws Exception { + System.clearProperty("jxpath.class.allow"); + super.tearDown(); + } + private ServletContext getServletContext() { final MockServletContext context = new MockServletContext(); context.setAttribute("app", "OK"); diff --git a/src/test/java/org/apache/commons/jxpath/util/ClassLoaderUtilTest.java b/src/test/java/org/apache/commons/jxpath/util/ClassLoaderUtilTest.java index 729f989db..b622744a8 100644 --- a/src/test/java/org/apache/commons/jxpath/util/ClassLoaderUtilTest.java +++ b/src/test/java/org/apache/commons/jxpath/util/ClassLoaderUtilTest.java @@ -46,6 +46,7 @@ public class ClassLoaderUtilTest extends TestCase { */ @Override public void setUp() { + System.setProperty("jxpath.class.allow", "java.lang.ObjectXBeanInfo,org.apache.commons.jxpath.*"); this.orginalContextClassLoader = Thread.currentThread().getContextClassLoader(); } @@ -55,6 +56,7 @@ public void setUp() { @Override public void tearDown() { Thread.currentThread().setContextClassLoader(this.orginalContextClassLoader); + System.clearProperty("jxpath.class.allow"); } /**