diff --git a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java index d8ebf23a7..462001960 100644 --- a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java +++ b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java @@ -109,7 +109,8 @@ public ContainerDef getContainerConfiguration() @Override public ContainerConfiguration createDeployableConfiguration() throws Exception { - ContainerConfiguration config = deployableContainer.getConfigurationClass().newInstance(); + ContainerConfiguration config = SecurityActions.newInstance( + deployableContainer.getConfigurationClass(), new Class[0], new Object[0]); MapObject.populate(config, containerConfiguration.getContainerProperties()); config.validate(); return config; diff --git a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/SecurityActions.java b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/SecurityActions.java new file mode 100644 index 000000000..f71d02c76 --- /dev/null +++ b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/SecurityActions.java @@ -0,0 +1,367 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2009, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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.jboss.arquillian.container.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; + +/** + * A set of privileged actions that are not to leak out + * of this package + * + * @version $Revision: $ + */ +final class SecurityActions +{ + + //-------------------------------------------------------------------------------|| + // Constructor ------------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * No instantiation + */ + private SecurityActions() + { + throw new UnsupportedOperationException("No instantiation"); + } + + //-------------------------------------------------------------------------------|| + // Utility Methods --------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * Obtains the Thread Context ClassLoader + */ + static ClassLoader getThreadContextClassLoader() + { + return AccessController.doPrivileged(GetTcclAction.INSTANCE); + } + + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) + { + try + { + return Class.forName(className, true, getThreadContextClassLoader()); + } + catch (ClassNotFoundException e) + { + try + { + return Class.forName(className, true, SecurityActions.class.getClassLoader()); + } + catch (ClassNotFoundException e2) + { + throw new RuntimeException("Could not load class " + className, e2); + } + } + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + + /** + * Create a new instance by finding a constructor that matches the argumentTypes signature + * using the arguments for instantiation. + * + * @param className Full classname of class to create + * @param argumentTypes The constructor argument types + * @param arguments The constructor arguments + * @return a new instance + * @throws IllegalArgumentException if className, argumentTypes, or arguments are null + * @throws RuntimeException if any exceptions during creation + * @author Aslak Knutsen + * @author ALR + */ + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) + { + if (implClass == null) + { + throw new IllegalArgumentException("ImplClass must be specified"); + } + if (argumentTypes == null) + { + throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); + } + if (arguments == null) + { + throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); + } + final T obj; + try + { + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + obj = constructor.newInstance(arguments); + } + catch (Exception e) + { + throw new RuntimeException("Could not create new instance of " + implClass, e); + } + + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { + try + { + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException + { + try + { + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + //-------------------------------------------------------------------------------|| + // Inner Classes ----------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * Single instance to get the TCCL + */ + private enum GetTcclAction implements PrivilegedAction { + INSTANCE; + + public ClassLoader run() + { + return Thread.currentThread().getContextClassLoader(); + } + + } +} \ No newline at end of file diff --git a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/container/ContainerRegistryCreator.java b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/container/ContainerRegistryCreator.java index 9638371bd..539a0e27f 100644 --- a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/container/ContainerRegistryCreator.java +++ b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/container/ContainerRegistryCreator.java @@ -177,12 +177,12 @@ private void validateConfiguration(ArquillianDescriptor desc) private String getActivatedConfiguration() { - if(exists(System.getProperty(ARQUILLIAN_LAUNCH_PROPERTY))) + if(exists(SecurityActions.getProperty(ARQUILLIAN_LAUNCH_PROPERTY))) { - return System.getProperty(ARQUILLIAN_LAUNCH_PROPERTY); + return SecurityActions.getProperty(ARQUILLIAN_LAUNCH_PROPERTY); } - InputStream arquillianLaunchStream = Thread.currentThread().getContextClassLoader() + InputStream arquillianLaunchStream = SecurityActions.getThreadContextClassLoader() .getResourceAsStream(ARQUILLIAN_LAUNCH_DEFAULT); if(arquillianLaunchStream != null) { diff --git a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/container/SecurityActions.java b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/container/SecurityActions.java new file mode 100644 index 000000000..0ee95e744 --- /dev/null +++ b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/container/SecurityActions.java @@ -0,0 +1,367 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2009, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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.jboss.arquillian.container.impl.client.container; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; + +/** + * A set of privileged actions that are not to leak out + * of this package + * + * @version $Revision: $ + */ +final class SecurityActions +{ + + //-------------------------------------------------------------------------------|| + // Constructor ------------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * No instantiation + */ + private SecurityActions() + { + throw new UnsupportedOperationException("No instantiation"); + } + + //-------------------------------------------------------------------------------|| + // Utility Methods --------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * Obtains the Thread Context ClassLoader + */ + static ClassLoader getThreadContextClassLoader() + { + return AccessController.doPrivileged(GetTcclAction.INSTANCE); + } + + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) + { + try + { + return Class.forName(className, true, getThreadContextClassLoader()); + } + catch (ClassNotFoundException e) + { + try + { + return Class.forName(className, true, SecurityActions.class.getClassLoader()); + } + catch (ClassNotFoundException e2) + { + throw new RuntimeException("Could not load class " + className, e2); + } + } + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + + /** + * Create a new instance by finding a constructor that matches the argumentTypes signature + * using the arguments for instantiation. + * + * @param className Full classname of class to create + * @param argumentTypes The constructor argument types + * @param arguments The constructor arguments + * @return a new instance + * @throws IllegalArgumentException if className, argumentTypes, or arguments are null + * @throws RuntimeException if any exceptions during creation + * @author Aslak Knutsen + * @author ALR + */ + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) + { + if (implClass == null) + { + throw new IllegalArgumentException("ImplClass must be specified"); + } + if (argumentTypes == null) + { + throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); + } + if (arguments == null) + { + throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); + } + final T obj; + try + { + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + obj = constructor.newInstance(arguments); + } + catch (Exception e) + { + throw new RuntimeException("Could not create new instance of " + implClass, e); + } + + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { + try + { + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException + { + try + { + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + //-------------------------------------------------------------------------------|| + // Inner Classes ----------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * Single instance to get the TCCL + */ + private enum GetTcclAction implements PrivilegedAction { + INSTANCE; + + public ClassLoader run() + { + return Thread.currentThread().getContextClassLoader(); + } + + } +} \ No newline at end of file diff --git a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/deployment/ArchiveDeploymentExporter.java b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/deployment/ArchiveDeploymentExporter.java index c50fc5519..c4289c8f2 100644 --- a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/deployment/ArchiveDeploymentExporter.java +++ b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/deployment/ArchiveDeploymentExporter.java @@ -52,7 +52,7 @@ public void callback(@Observes BeforeDeploy event) throws Exception } EngineDef engine = descriptor.engine(); - String systemExport = System.getProperty("arquillian.deploymentExportPath"); + String systemExport = SecurityActions.getProperty("arquillian.deploymentExportPath"); String exportPath = (systemExport == null || systemExport.length() == 0) ? engine.getDeploymentExportPath():systemExport; if(exportPath != null && event.getDeployment().isArchiveDeployment()) diff --git a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/deployment/SecurityActions.java b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/deployment/SecurityActions.java new file mode 100644 index 000000000..5ebc1e54d --- /dev/null +++ b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/client/deployment/SecurityActions.java @@ -0,0 +1,367 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2009, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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.jboss.arquillian.container.impl.client.deployment; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; + +/** + * A set of privileged actions that are not to leak out + * of this package + * + * @version $Revision: $ + */ +final class SecurityActions +{ + + //-------------------------------------------------------------------------------|| + // Constructor ------------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * No instantiation + */ + private SecurityActions() + { + throw new UnsupportedOperationException("No instantiation"); + } + + //-------------------------------------------------------------------------------|| + // Utility Methods --------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * Obtains the Thread Context ClassLoader + */ + static ClassLoader getThreadContextClassLoader() + { + return AccessController.doPrivileged(GetTcclAction.INSTANCE); + } + + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) + { + try + { + return Class.forName(className, true, getThreadContextClassLoader()); + } + catch (ClassNotFoundException e) + { + try + { + return Class.forName(className, true, SecurityActions.class.getClassLoader()); + } + catch (ClassNotFoundException e2) + { + throw new RuntimeException("Could not load class " + className, e2); + } + } + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + + /** + * Create a new instance by finding a constructor that matches the argumentTypes signature + * using the arguments for instantiation. + * + * @param className Full classname of class to create + * @param argumentTypes The constructor argument types + * @param arguments The constructor arguments + * @return a new instance + * @throws IllegalArgumentException if className, argumentTypes, or arguments are null + * @throws RuntimeException if any exceptions during creation + * @author Aslak Knutsen + * @author ALR + */ + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) + { + if (implClass == null) + { + throw new IllegalArgumentException("ImplClass must be specified"); + } + if (argumentTypes == null) + { + throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); + } + if (arguments == null) + { + throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); + } + final T obj; + try + { + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + obj = constructor.newInstance(arguments); + } + catch (Exception e) + { + throw new RuntimeException("Could not create new instance of " + implClass, e); + } + + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { + try + { + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException + { + try + { + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + //-------------------------------------------------------------------------------|| + // Inner Classes ----------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * Single instance to get the TCCL + */ + private enum GetTcclAction implements PrivilegedAction { + INSTANCE; + + public ClassLoader run() + { + return Thread.currentThread().getContextClassLoader(); + } + + } +} \ No newline at end of file diff --git a/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java b/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java index c61eda36c..75bf637d1 100644 --- a/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java +++ b/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java @@ -99,23 +99,52 @@ public void shouldBeAbleToCreateContainerConfiguration() throws Exception { String name = "some-name"; String prop = "prop-value"; - + ContainerRegistry registry = new LocalContainerRegistry(injector.get()); registry.create(new ContainerDefImpl(ARQUILLIAN_XML).setContainerName(name) .property("property", prop), serviceLoader); - + Container container = registry.getContainer(new TargetDescription(name)); - + Assert.assertEquals( "Verify that the only registered container is returned as default", name, container.getName()); Assert.assertEquals( "Verify that the configuration was populated", - prop, + prop, ((DummyContainerConfiguration)container.createDeployableConfiguration()).getProperty()); } - + + @Test + public void shouldBeAbleToCreatePrivateContainerConfiguration() throws Exception + { + // Override default configured class + ServiceLoader serviceLoader = Mockito.mock(ServiceLoader.class); + DeployableContainer deployableContainer = Mockito.mock(DeployableContainer.class); + + Mockito.when(serviceLoader.onlyOne(Mockito.same(DeployableContainer.class))).thenReturn(deployableContainer); + Mockito.when(deployableContainer.getConfigurationClass()).thenReturn(PrivateDummyContainerConfiguration.class); + + String name = "some-name"; + String prop = "prop-value"; + + ContainerRegistry registry = new LocalContainerRegistry(injector.get()); + registry.create(new ContainerDefImpl(ARQUILLIAN_XML).setContainerName(name) + .property("property", prop), serviceLoader); + + Container container = registry.getContainer(new TargetDescription(name)); + + Assert.assertEquals( + "Verify that the only registered container is returned as default", + name, container.getName()); + + Assert.assertEquals( + "Verify that the configuration was populated", + prop, + ((PrivateDummyContainerConfiguration)container.createDeployableConfiguration()).getProperty()); + } + @Test public void shouldBeAbleToSpecifyTarget() throws Exception { @@ -169,14 +198,16 @@ public String getProperty() return property; } - /* (non-Javadoc) - * @see org.jboss.arquillian.spi.client.container.ContainerConfiguration#validate() - */ @Override public void validate() throws ConfigurationException { - // TODO Auto-generated method stub - + } + } + + private static class PrivateDummyContainerConfiguration extends DummyContainerConfiguration + { + private PrivateDummyContainerConfiguration() + { } } } diff --git a/container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/RemoteExtensionLoader.java b/container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/RemoteExtensionLoader.java index c853f3fb5..800811c45 100644 --- a/container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/RemoteExtensionLoader.java +++ b/container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/RemoteExtensionLoader.java @@ -19,7 +19,6 @@ import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.reflect.Constructor; import java.net.URL; import java.util.ArrayList; import java.util.Collection; @@ -172,6 +171,16 @@ private String skipCommentAndTrim(String line) return line; } + private Set createInstances(Class serviceType, Set> providers) + { + Set providerImpls = new LinkedHashSet(); + for(Class serviceClass: providers) + { + providerImpls.add(createInstance(serviceClass)); + } + return providerImpls; + } + /** * Create a new instance of the found Service.
* @@ -188,26 +197,11 @@ private T createInstance(Class serviceImplClass) { try { - Constructor constructor = SecurityActions.getConstructor(serviceImplClass); - if (!constructor.isAccessible()) - { - constructor.setAccessible(true); - } - return constructor.newInstance(); + return SecurityActions.newInstance(serviceImplClass, new Class[0], new Object[0]); } catch (Exception e) { throw new RuntimeException("Could not create a new instance of Service implementation " + serviceImplClass.getName(), e); } } - - private Set createInstances(Class serviceType, Set> providers) - { - Set providerImpls = new LinkedHashSet(); - for(Class serviceClass: providers) - { - providerImpls.add(createInstance(serviceClass)); - } - return providerImpls; - } } diff --git a/container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/SecurityActions.java b/container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/SecurityActions.java index ce3b9d47c..c8a7df917 100644 --- a/container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/SecurityActions.java +++ b/container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/SecurityActions.java @@ -16,19 +16,21 @@ */ package org.jboss.arquillian.container.test.impl; +import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; /** - * SecurityActions - * * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -58,47 +60,34 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - public Constructor run() throws NoSuchMethodException - { - return clazz.getConstructor(argumentTypes); - } - }); + return Class.forName(className, true, getThreadContextClassLoader()); } - // Unwrap - catch (final PrivilegedActionException pae) + catch (ClassNotFoundException e) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) + try { - throw (NoSuchMethodException) t; + return Class.forName(className, true, SecurityActions.class.getClassLoader()); } - else + catch (ClassNotFoundException e2) { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + throw new RuntimeException("Could not load class " + className, e2); } } } @@ -161,6 +150,9 @@ static T newInstance(final Class implClass, final Class[] argumentType try { Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } obj = constructor.newInstance(arguments); } catch (Exception e) @@ -171,6 +163,191 @@ static T newInstance(final Class implClass, final Class[] argumentType return obj; } + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { + try + { + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException + { + try + { + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| //-------------------------------------------------------------------------------|| @@ -187,5 +364,4 @@ public ClassLoader run() } } - -} +} \ No newline at end of file diff --git a/container/test-impl-base/src/test/java/org/jboss/arquillian/container/test/impl/client/deployment/AnnotationDeploymentScenarioGeneratorTestCase.java b/container/test-impl-base/src/test/java/org/jboss/arquillian/container/test/impl/client/deployment/AnnotationDeploymentScenarioGeneratorTestCase.java index c4e282dd2..a59331672 100644 --- a/container/test-impl-base/src/test/java/org/jboss/arquillian/container/test/impl/client/deployment/AnnotationDeploymentScenarioGeneratorTestCase.java +++ b/container/test-impl-base/src/test/java/org/jboss/arquillian/container/test/impl/client/deployment/AnnotationDeploymentScenarioGeneratorTestCase.java @@ -19,6 +19,7 @@ import java.util.List; import org.jboss.arquillian.container.spi.client.deployment.DeploymentDescription; +import org.jboss.arquillian.container.spi.client.deployment.DeploymentScenario; import org.jboss.arquillian.container.spi.client.deployment.TargetDescription; import org.jboss.arquillian.container.spi.client.protocol.ProtocolDescription; import org.jboss.arquillian.container.test.api.Deployment; @@ -133,15 +134,31 @@ public void shouldReadExpectedAndOverrideDeployment() Assert.assertEquals(Exception.class, deploymentOne.getExpectedException()); } + @Test public void shouldAllowNoDeploymentPresent() throws Exception { - List descriptors = new AnnotationDeploymentScenarioGenerator().generate( - new TestClass(DeploymentNotPresent.class)); + List descriptors = generate(DeploymentNotPresent.class); Assert.assertNotNull(descriptors); Assert.assertEquals(0, descriptors.size()); } + @Test + public void shouldAllowNonPublicDeploymentMethods() throws Exception { + List descriptors = generate(DeploymentProtectedMethods.class); + + Assert.assertNotNull(descriptors); + Assert.assertEquals(3, descriptors.size()); + } + + @Test + public void shouldAllowNonPublicDeploymentMethodsFromSuperClass() throws Exception { + List descriptors = generate(DeploymentProtectedMethodsInherited.class); + + Assert.assertNotNull(descriptors); + Assert.assertEquals(3, descriptors.size()); + } + @Test(expected = IllegalArgumentException.class) public void shouldThrowExceptionOnDeploymentNotStatic() throws Exception { @@ -203,6 +220,28 @@ public static Archive deploymentOne() } } + @SuppressWarnings("unused") + private static class DeploymentProtectedMethods { + + @Deployment + static JavaArchive one() { + return ShrinkWrap.create(JavaArchive.class); + } + + @Deployment + private static JavaArchive two() { + return ShrinkWrap.create(JavaArchive.class); + } + + @Deployment + protected static JavaArchive tree() { + return ShrinkWrap.create(JavaArchive.class); + } + } + + private static class DeploymentProtectedMethodsInherited extends DeploymentProtectedMethods { + } + private static class DeploymentNotPresent { } diff --git a/container/test-spi/src/main/java/org/jboss/arquillian/container/test/spi/util/SecurityActions.java b/container/test-spi/src/main/java/org/jboss/arquillian/container/test/spi/util/SecurityActions.java index 13615d74a..c88c0107e 100644 --- a/container/test-spi/src/main/java/org/jboss/arquillian/container/test/spi/util/SecurityActions.java +++ b/container/test-spi/src/main/java/org/jboss/arquillian/container/test/spi/util/SecurityActions.java @@ -19,6 +19,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; @@ -27,12 +28,9 @@ import java.util.List; /** - * SecurityActions - * * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -62,51 +60,65 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - public Constructor run() throws NoSuchMethodException - { - return clazz.getConstructor(argumentTypes); - } - }); + return Class.forName(className, true, getThreadContextClassLoader()); } - // Unwrap - catch (final PrivilegedActionException pae) + catch (ClassNotFoundException e) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) + try { - throw (NoSuchMethodException) t; + return Class.forName(className, true, SecurityActions.class.getClassLoader()); } - else + catch (ClassNotFoundException e2) { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + throw new RuntimeException("Could not load class " + className, e2); } } } + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + /** * Create a new instance by finding a constructor that matches the argumentTypes signature * using the arguments for instantiation. @@ -120,12 +132,11 @@ public Constructor run() throws NoSuchMethodException * @author Aslak Knutsen * @author ALR */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) { - if (className == null) + if (implClass == null) { - throw new IllegalArgumentException("ClassName must be specified"); + throw new IllegalArgumentException("ImplClass must be specified"); } if (argumentTypes == null) { @@ -135,48 +146,120 @@ static T newInstance(final String className, final Class[] argumentTypes, { throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); } - final Object obj; + final T obj; try { - final ClassLoader tccl = getThreadContextClassLoader(); - final Class implClass = Class.forName(className, false, tccl); - Constructor constructor = getConstructor(implClass, argumentTypes); + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } obj = constructor.newInstance(arguments); } catch (Exception e) { - throw new RuntimeException("Could not create new instance of " + className - + ", missing package from classpath?", e); + throw new RuntimeException("Could not create new instance of " + implClass, e); } - // Cast + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { try { - return expectedType.cast(obj); + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); } - catch (final ClassCastException cce) + // Unwrap + catch (final PrivilegedActionException pae) { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - public static boolean isClassPresent(String name) + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException { - try + try { - ClassLoader classLoader = getThreadContextClassLoader(); - classLoader.loadClass(name); - return true; + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); } - catch (ClassNotFoundException e) + // Unwrap + catch (final PrivilegedActionException pae) { - return false; + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - - static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) { List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() { @@ -203,7 +286,68 @@ public List run() }); return declaredAccessableFields; } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| //-------------------------------------------------------------------------------|| @@ -220,5 +364,4 @@ public ClassLoader run() } } - -} +} \ No newline at end of file diff --git a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/ObserverImpl.java b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/ObserverImpl.java index 170a8eb48..9cb836df0 100644 --- a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/ObserverImpl.java +++ b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/ObserverImpl.java @@ -87,6 +87,10 @@ public boolean invoke(Manager manager, Object event) { return false; } + if(!method.isAccessible()) + { + method.setAccessible(true); + } method.invoke(target, arguments); return true; } diff --git a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/Reflections.java b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/Reflections.java index 1b07118ba..dc66a0259 100644 --- a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/Reflections.java +++ b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/Reflections.java @@ -17,7 +17,6 @@ package org.jboss.arquillian.core.impl; import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; @@ -50,7 +49,7 @@ public static List getObserverMethods(Class clazz) { return observerMethods; } - for(Method method : clazz.getMethods()) + for(Method method : clazz.getDeclaredMethods()) { if(isObserverMethod(method)) { @@ -120,12 +119,7 @@ public static Class getScope(Field field) public static T createInstance(Class clazz) throws Exception { - Constructor constructor = clazz.getDeclaredConstructor(); - if(!constructor.isAccessible()) - { - constructor.setAccessible(true); - } - return constructor.newInstance(); + return SecurityActions.newInstance(clazz, new Class[0], new Object[0]); } public static boolean isType(Type type, Class clazz) @@ -246,6 +240,4 @@ private static boolean containsAnnotation(Class match, Ann } return false; } - - -} +} \ No newline at end of file diff --git a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/SecurityActions.java b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/SecurityActions.java index 0fab81380..c2f502a29 100644 --- a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/SecurityActions.java +++ b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/SecurityActions.java @@ -16,71 +16,352 @@ */ package org.jboss.arquillian.core.impl; +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; /** - * SecurityActions - * - * A set of privileged actions that are not to leak out of this package - * - * - * @author Karel Piwko + * A set of privileged actions that are not to leak out + * of this package * * @version $Revision: $ */ -final class SecurityActions { - - // -------------------------------------------------------------------------------|| - // Constructor - // ------------------------------------------------------------------|| - // -------------------------------------------------------------------------------|| - - /** - * No instantiation - */ - private SecurityActions() { - throw new UnsupportedOperationException("No instantiation"); - } - - // -------------------------------------------------------------------------------|| - // Utility Methods - // --------------------------------------------------------------|| - // -------------------------------------------------------------------------------|| - - static String getProperty(final String key) { - try { - String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { - public String run() { - return System.getProperty(key); - } - }); - return value; - } - // Unwrap - catch (final PrivilegedActionException pae) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof SecurityException) { - throw (SecurityException) t; +final class SecurityActions +{ + + //-------------------------------------------------------------------------------|| + // Constructor ------------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * No instantiation + */ + private SecurityActions() + { + throw new UnsupportedOperationException("No instantiation"); + } + + //-------------------------------------------------------------------------------|| + // Utility Methods --------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * Obtains the Thread Context ClassLoader + */ + static ClassLoader getThreadContextClassLoader() + { + return AccessController.doPrivileged(GetTcclAction.INSTANCE); + } + + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) + { + try + { + return Class.forName(className, true, getThreadContextClassLoader()); + } + catch (ClassNotFoundException e) + { + try + { + return Class.forName(className, true, SecurityActions.class.getClassLoader()); + } + catch (ClassNotFoundException e2) + { + throw new RuntimeException("Could not load class " + className, e2); + } + } + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + + /** + * Create a new instance by finding a constructor that matches the argumentTypes signature + * using the arguments for instantiation. + * + * @param className Full classname of class to create + * @param argumentTypes The constructor argument types + * @param arguments The constructor arguments + * @return a new instance + * @throws IllegalArgumentException if className, argumentTypes, or arguments are null + * @throws RuntimeException if any exceptions during creation + * @author Aslak Knutsen + * @author ALR + */ + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) + { + if (implClass == null) + { + throw new IllegalArgumentException("ImplClass must be specified"); + } + if (argumentTypes == null) + { + throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); + } + if (arguments == null) + { + throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); + } + final T obj; + try + { + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + obj = constructor.newInstance(arguments); + } + catch (Exception e) + { + throw new RuntimeException("Could not create new instance of " + implClass, e); + } + + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { + try + { + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); } - if (t instanceof NullPointerException) { - throw (NullPointerException) t; - } else if (t instanceof IllegalArgumentException) { - throw (IllegalArgumentException) t; - } else { - // No other checked Exception thrown by System.getProperty - try { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; } - } - } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException + { + try + { + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + //-------------------------------------------------------------------------------|| + // Inner Classes ----------------------------------------------------------------|| + //-------------------------------------------------------------------------------|| + + /** + * Single instance to get the TCCL + */ + private enum GetTcclAction implements PrivilegedAction { + INSTANCE; + + public ClassLoader run() + { + return Thread.currentThread().getContextClassLoader(); + } -} + } +} \ No newline at end of file diff --git a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/loadable/JavaSPIExtensionLoader.java b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/loadable/JavaSPIExtensionLoader.java index 797012cfd..ccf01d314 100644 --- a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/loadable/JavaSPIExtensionLoader.java +++ b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/loadable/JavaSPIExtensionLoader.java @@ -19,7 +19,6 @@ import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.reflect.Constructor; import java.net.URL; import java.util.Collection; import java.util.Enumeration; @@ -154,7 +153,17 @@ private String skipCommentAndTrim(String line) line = line.trim(); return line; } - + + private Set createInstances(Class serviceType, Set> providers) + { + Set providerImpls = new LinkedHashSet(); + for(Class serviceClass: providers) + { + providerImpls.add(createInstance(serviceClass)); + } + return providerImpls; + } + /** * Create a new instance of the found Service.
* @@ -171,26 +180,11 @@ private T createInstance(Class serviceImplClass) { try { - Constructor constructor = SecurityActions.getConstructor(serviceImplClass); - if (!constructor.isAccessible()) - { - constructor.setAccessible(true); - } - return constructor.newInstance(); + return SecurityActions.newInstance(serviceImplClass, new Class[0], new Object[0]); } catch (Exception e) { throw new RuntimeException("Could not create a new instance of Service implementation " + serviceImplClass.getName(), e); } } - - private Set createInstances(Class serviceType, Set> providers) - { - Set providerImpls = new LinkedHashSet(); - for(Class serviceClass: providers) - { - providerImpls.add(createInstance(serviceClass)); - } - return providerImpls; - } } diff --git a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/loadable/SecurityActions.java b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/loadable/SecurityActions.java index e784fc9e2..392666e4c 100644 --- a/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/loadable/SecurityActions.java +++ b/core/impl-base/src/main/java/org/jboss/arquillian/core/impl/loadable/SecurityActions.java @@ -16,19 +16,21 @@ */ package org.jboss.arquillian.core.impl.loadable; +import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; /** - * SecurityActions - * * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -58,47 +60,34 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - public Constructor run() throws NoSuchMethodException - { - return clazz.getConstructor(argumentTypes); - } - }); + return Class.forName(className, true, getThreadContextClassLoader()); } - // Unwrap - catch (final PrivilegedActionException pae) + catch (ClassNotFoundException e) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) + try { - throw (NoSuchMethodException) t; + return Class.forName(className, true, SecurityActions.class.getClassLoader()); } - else + catch (ClassNotFoundException e2) { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + throw new RuntimeException("Could not load class " + className, e2); } } } @@ -161,6 +150,9 @@ static T newInstance(final Class implClass, final Class[] argumentType try { Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } obj = constructor.newInstance(arguments); } catch (Exception e) @@ -171,6 +163,191 @@ static T newInstance(final Class implClass, final Class[] argumentType return obj; } + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { + try + { + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException + { + try + { + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| //-------------------------------------------------------------------------------|| @@ -187,5 +364,4 @@ public ClassLoader run() } } - -} +} \ No newline at end of file diff --git a/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/ClassPermissionTestCase.java b/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/ClassPermissionTestCase.java new file mode 100644 index 000000000..e7db8bfbf --- /dev/null +++ b/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/ClassPermissionTestCase.java @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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.jboss.arquillian.core.impl; + +import java.lang.reflect.Field; + +import org.jboss.arquillian.core.spi.Manager; +import org.jboss.arquillian.core.spi.ManagerBuilder; +import org.junit.Assert; +import org.junit.Test; + +public class ClassPermissionTestCase +{ + + @Test + public void shouldBeAbleToUseProtectedFieldsAndMethods() throws Exception + { + Class observerClass = SecurityActions.loadClass( + this.getClass().getPackage().getName() + ".test.PrivateObserver"); + Manager manager = ManagerBuilder.from().extension(observerClass).create(); + + manager.fire("Test"); + + Field wasCalled = observerClass.getField("wasCalled"); + wasCalled.setAccessible(true); + Assert.assertTrue((Boolean)wasCalled.get(null)); + } +} diff --git a/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/loadable/ServiceRegistryLoaderTestCase.java b/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/loadable/ServiceRegistryLoaderTestCase.java index fbafcbdb7..b8c195edb 100644 --- a/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/loadable/ServiceRegistryLoaderTestCase.java +++ b/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/loadable/ServiceRegistryLoaderTestCase.java @@ -146,4 +146,18 @@ public void loadedDefaultServicesShouldBeStaticallyInjected() throws Exception "Verify service has been statically injected", service.isValid()); } + + /* + * ARQ-1024: Protected services should be loadable + */ + @SuppressWarnings("unchecked") + @Test + public void shouldBeAbleToLoadProtectedServices() throws Exception { + ServiceRegistry registry = new ServiceRegistry(injector.get()); + registry.addService( + FakeService.class, (Class)Class.forName("org.jboss.arquillian.core.impl.loadable.util.PackageProtectedService")); + + FakeService service = registry.getServiceLoader().onlyOne(FakeService.class); + Assert.assertNotNull("Could load package protected service", service); + } } diff --git a/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/loadable/util/PackageProtectedService.java b/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/loadable/util/PackageProtectedService.java new file mode 100644 index 000000000..7d09cde76 --- /dev/null +++ b/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/loadable/util/PackageProtectedService.java @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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.jboss.arquillian.core.impl.loadable.util; + +/** + * Loaded via Reflection in ServiceRegistryLoader + */ +class PackageProtectedService implements FakeService +{ + @Override + public boolean isValid() + { + return true; + } +} \ No newline at end of file diff --git a/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/test/PrivateObserver.java b/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/test/PrivateObserver.java new file mode 100644 index 000000000..f86d41382 --- /dev/null +++ b/core/impl-base/src/test/java/org/jboss/arquillian/core/impl/test/PrivateObserver.java @@ -0,0 +1,36 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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.jboss.arquillian.core.impl.test; + +import org.jboss.arquillian.core.api.Event; +import org.jboss.arquillian.core.api.annotation.Inject; +import org.jboss.arquillian.core.api.annotation.Observes; + +class PrivateObserver { + + public static boolean wasCalled = false; + + @Inject + private Event fireEvent; + + PrivateObserver() {} + + public void test(@Observes String event) { + wasCalled=true; + fireEvent.fire(100); + } +} diff --git a/core/spi/src/main/java/org/jboss/arquillian/core/spi/SecurityActions.java b/core/spi/src/main/java/org/jboss/arquillian/core/spi/SecurityActions.java index 5140a7646..e605b6f29 100644 --- a/core/spi/src/main/java/org/jboss/arquillian/core/spi/SecurityActions.java +++ b/core/spi/src/main/java/org/jboss/arquillian/core/spi/SecurityActions.java @@ -16,17 +16,21 @@ */ package org.jboss.arquillian.core.spi; +import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; /** * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -56,6 +60,109 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) + { + try + { + return Class.forName(className, true, getThreadContextClassLoader()); + } + catch (ClassNotFoundException e) + { + try + { + return Class.forName(className, true, SecurityActions.class.getClassLoader()); + } + catch (ClassNotFoundException e2) + { + throw new RuntimeException("Could not load class " + className, e2); + } + } + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + + /** + * Create a new instance by finding a constructor that matches the argumentTypes signature + * using the arguments for instantiation. + * + * @param className Full classname of class to create + * @param argumentTypes The constructor argument types + * @param arguments The constructor arguments + * @return a new instance + * @throws IllegalArgumentException if className, argumentTypes, or arguments are null + * @throws RuntimeException if any exceptions during creation + * @author Aslak Knutsen + * @author ALR + */ + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) + { + if (implClass == null) + { + throw new IllegalArgumentException("ImplClass must be specified"); + } + if (argumentTypes == null) + { + throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); + } + if (arguments == null) + { + throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); + } + final T obj; + try + { + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + obj = constructor.newInstance(arguments); + } + catch (Exception e) + { + throw new RuntimeException("Could not create new instance of " + implClass, e); + } + + return obj; + } + /** * Obtains the Constructor specified from the given Class and argument types * @param clazz @@ -63,15 +170,14 @@ static ClassLoader getThreadContextClassLoader() * @return * @throws NoSuchMethodException */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) throws NoSuchMethodException { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() + return AccessController.doPrivileged(new PrivilegedExceptionAction>() { - @Override - public Constructor run() throws NoSuchMethodException + public Constructor run() throws NoSuchMethodException { return clazz.getDeclaredConstructor(argumentTypes); } @@ -103,73 +209,144 @@ public Constructor run() throws NoSuchMethodException } /** - * Create a new instance by finding a constructor that matches the argumentTypes signature - * using the arguments for instantiation. + * Set a single Field value * - * @param className Full classname of class to create - * @param argumentTypes The constructor argument types - * @param arguments The constructor arguments - * @return a new instance - * @throws IllegalArgumentException if className, argumentTypes, or arguments are null - * @throws RuntimeException if any exceptions during creation - * @author Aslak Knutsen - * @author ALR + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException { - if (className == null) - { - throw new IllegalArgumentException("ClassName must be specified"); - } - if (argumentTypes == null) - { - throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); - } - if (arguments == null) - { - throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); - } - final Object obj; - final Class implClass; try { - final ClassLoader tccl = getThreadContextClassLoader(); - implClass = Class.forName(className, false, tccl); + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); } - catch (Exception e) + // Unwrap + catch (final PrivilegedActionException pae) { - throw new RuntimeException("Could not load class " + className - + ", missing package from classpath?", e); + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } + } - try + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() { - Constructor constructor = getConstructor(implClass, argumentTypes); - if(!constructor.isAccessible()) + public List run() { - constructor.setAccessible(true); + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; } - obj = constructor.newInstance(arguments); - } - catch (Exception e) - { - throw new RuntimeException("Could not create a new instance of class " + className - + " see cause.", e); - } + }); + return declaredAccessableFields; + } - // Cast - try + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() { - return expectedType.cast(obj); + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; } - catch (final ClassCastException cce) - { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } - } + } //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| @@ -181,12 +358,10 @@ static T newInstance(final String className, final Class[] argumentTypes, private enum GetTcclAction implements PrivilegedAction { INSTANCE; - @Override public ClassLoader run() { return Thread.currentThread().getContextClassLoader(); } } - -} +} \ No newline at end of file diff --git a/junit/core/src/main/java/org/jboss/arquillian/junit/SecurityActions.java b/junit/core/src/main/java/org/jboss/arquillian/junit/SecurityActions.java index a37993d54..8d78817dc 100644 --- a/junit/core/src/main/java/org/jboss/arquillian/junit/SecurityActions.java +++ b/junit/core/src/main/java/org/jboss/arquillian/junit/SecurityActions.java @@ -16,14 +16,21 @@ */ package org.jboss.arquillian.junit; +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; /** * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -52,12 +59,12 @@ static ClassLoader getThreadContextClassLoader() { return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - - static boolean existsClass(String className) + + static boolean isClassPresent(String name) { - try + try { - loadClass(className); + loadClass(name); return true; } catch (Exception e) @@ -72,12 +79,274 @@ static Class loadClass(String className) { return Class.forName(className, true, getThreadContextClassLoader()); } + catch (ClassNotFoundException e) + { + try + { + return Class.forName(className, true, SecurityActions.class.getClassLoader()); + } + catch (ClassNotFoundException e2) + { + throw new RuntimeException("Could not load class " + className, e2); + } + } + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } catch (Exception e) { - throw new RuntimeException("Could not load class", e); + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + + /** + * Create a new instance by finding a constructor that matches the argumentTypes signature + * using the arguments for instantiation. + * + * @param className Full classname of class to create + * @param argumentTypes The constructor argument types + * @param arguments The constructor arguments + * @return a new instance + * @throws IllegalArgumentException if className, argumentTypes, or arguments are null + * @throws RuntimeException if any exceptions during creation + * @author Aslak Knutsen + * @author ALR + */ + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) + { + if (implClass == null) + { + throw new IllegalArgumentException("ImplClass must be specified"); + } + if (argumentTypes == null) + { + throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); + } + if (arguments == null) + { + throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); + } + final T obj; + try + { + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + obj = constructor.newInstance(arguments); + } + catch (Exception e) + { + throw new RuntimeException("Could not create new instance of " + implClass, e); + } + + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { + try + { + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException + { + try + { + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); + } + // Unwrap + catch (final PrivilegedActionException pae) + { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| @@ -89,12 +358,10 @@ static Class loadClass(String className) private enum GetTcclAction implements PrivilegedAction { INSTANCE; - @Override public ClassLoader run() { return Thread.currentThread().getContextClassLoader(); } } - -} +} \ No newline at end of file diff --git a/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/runner/SecurityActions.java b/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/runner/SecurityActions.java index e4f50bc44..cf9cc9705 100644 --- a/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/runner/SecurityActions.java +++ b/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/runner/SecurityActions.java @@ -16,22 +16,24 @@ */ package org.jboss.arquillian.protocol.servlet.runner; +import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; /** - * SecurityActions - * * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ -public final class SecurityActions +final class SecurityActions { //-------------------------------------------------------------------------------|| @@ -58,6 +60,109 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) + { + try + { + return Class.forName(className, true, getThreadContextClassLoader()); + } + catch (ClassNotFoundException e) + { + try + { + return Class.forName(className, true, SecurityActions.class.getClassLoader()); + } + catch (ClassNotFoundException e2) + { + throw new RuntimeException("Could not load class " + className, e2); + } + } + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + + /** + * Create a new instance by finding a constructor that matches the argumentTypes signature + * using the arguments for instantiation. + * + * @param className Full classname of class to create + * @param argumentTypes The constructor argument types + * @param arguments The constructor arguments + * @return a new instance + * @throws IllegalArgumentException if className, argumentTypes, or arguments are null + * @throws RuntimeException if any exceptions during creation + * @author Aslak Knutsen + * @author ALR + */ + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) + { + if (implClass == null) + { + throw new IllegalArgumentException("ImplClass must be specified"); + } + if (argumentTypes == null) + { + throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); + } + if (arguments == null) + { + throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); + } + final T obj; + try + { + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + obj = constructor.newInstance(arguments); + } + catch (Exception e) + { + throw new RuntimeException("Could not create new instance of " + implClass, e); + } + + return obj; + } + /** * Obtains the Constructor specified from the given Class and argument types * @param clazz @@ -65,16 +170,16 @@ static ClassLoader getThreadContextClassLoader() * @return * @throws NoSuchMethodException */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) throws NoSuchMethodException { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() + return AccessController.doPrivileged(new PrivilegedExceptionAction>() { - public Constructor run() throws NoSuchMethodException + public Constructor run() throws NoSuchMethodException { - return clazz.getConstructor(argumentTypes); + return clazz.getDeclaredConstructor(argumentTypes); } }); } @@ -104,59 +209,144 @@ public Constructor run() throws NoSuchMethodException } /** - * Create a new instance by finding a constructor that matches the argumentTypes signature - * using the arguments for instantiation. + * Set a single Field value * - * @param className Full classname of class to create - * @param argumentTypes The constructor argument types - * @param arguments The constructor arguments - * @return a new instance - * @throws IllegalArgumentException if className, argumentTypes, or arguments are null - * @throws RuntimeException if any exceptions during creation - * @author Aslak Knutsen - * @author ALR + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException { - if (className == null) - { - throw new IllegalArgumentException("ClassName must be specified"); - } - if (argumentTypes == null) - { - throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); - } - if (arguments == null) - { - throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); - } - final Object obj; try { - final ClassLoader tccl = getThreadContextClassLoader(); - final Class implClass = Class.forName(className, false, tccl); - Constructor constructor = getConstructor(implClass, argumentTypes); - obj = constructor.newInstance(arguments); + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); } - catch (Exception e) + // Unwrap + catch (final PrivilegedActionException pae) { - throw new RuntimeException("Could not create new instance of " + className - + ", missing package from classpath?", e); + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } + } - // Cast - try + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() { - return expectedType.cast(obj); - } - catch (final ClassCastException cce) + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); - } + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| @@ -174,5 +364,4 @@ public ClassLoader run() } } - -} +} \ No newline at end of file diff --git a/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_2_5/ProtocolDeploymentAppender.java b/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_2_5/ProtocolDeploymentAppender.java index 92b3f0534..c3441b52d 100644 --- a/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_2_5/ProtocolDeploymentAppender.java +++ b/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_2_5/ProtocolDeploymentAppender.java @@ -18,7 +18,6 @@ import org.jboss.arquillian.container.test.spi.RemoteLoadableExtension; import org.jboss.arquillian.container.test.spi.client.deployment.AuxiliaryArchiveAppender; -import org.jboss.arquillian.protocol.servlet.runner.SecurityActions; import org.jboss.arquillian.protocol.servlet.runner.ServletRemoteExtension; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.StringAsset; @@ -40,7 +39,7 @@ public WebArchive createAuxiliaryArchive() { // Load based on package to avoid ClassNotFoundException on HttpServlet when loading ServletTestRunner return ShrinkWrap.create(WebArchive.class, "arquillian-protocol.war") - .addPackage(SecurityActions.class.getPackage()) + .addPackage(ServletRemoteExtension.class.getPackage()) .setWebXML(new StringAsset( WebUtils.createNewDescriptor().exportAsString() )) diff --git a/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_3/ProtocolDeploymentAppender.java b/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_3/ProtocolDeploymentAppender.java index d6d2d11d7..6c115b180 100644 --- a/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_3/ProtocolDeploymentAppender.java +++ b/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_3/ProtocolDeploymentAppender.java @@ -18,7 +18,6 @@ import org.jboss.arquillian.container.test.spi.RemoteLoadableExtension; import org.jboss.arquillian.container.test.spi.client.deployment.AuxiliaryArchiveAppender; -import org.jboss.arquillian.protocol.servlet.runner.SecurityActions; import org.jboss.arquillian.protocol.servlet.runner.ServletRemoteExtension; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; @@ -39,7 +38,7 @@ public JavaArchive createAuxiliaryArchive() { // Load based on package to avoid ClassNotFoundException on HttpServlet when loading ServletTestRunner return ShrinkWrap.create(JavaArchive.class, "arquillian-protocol.jar") - .addPackage(SecurityActions.class.getPackage()) // servlet.runner + .addPackage(ServletRemoteExtension.class.getPackage()) // servlet.runner .addAsManifestResource( "org/jboss/arquillian/protocol/servlet/v_3/web-fragment.xml", "web-fragment.xml") diff --git a/test/impl-base/src/main/java/org/jboss/arquillian/test/impl/enricher/resource/SecurityActions.java b/test/impl-base/src/main/java/org/jboss/arquillian/test/impl/enricher/resource/SecurityActions.java index 565a13ebe..d3d7bcc13 100644 --- a/test/impl-base/src/main/java/org/jboss/arquillian/test/impl/enricher/resource/SecurityActions.java +++ b/test/impl-base/src/main/java/org/jboss/arquillian/test/impl/enricher/resource/SecurityActions.java @@ -19,6 +19,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; @@ -27,12 +28,9 @@ import java.util.List; /** - * SecurityActions - * * A set of privileged actions that are not to leak out - * of this package + * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -62,55 +60,69 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - public Constructor run() throws NoSuchMethodException - { - return clazz.getConstructor(argumentTypes); - } - }); + return Class.forName(className, true, getThreadContextClassLoader()); } - // Unwrap - catch (final PrivilegedActionException pae) + catch (ClassNotFoundException e) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) + try { - throw (NoSuchMethodException) t; + return Class.forName(className, true, SecurityActions.class.getClassLoader()); } - else + catch (ClassNotFoundException e2) { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + throw new RuntimeException("Could not load class " + className, e2); } } } + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + /** - * Create a new instance by finding a constructor that matches the argumentTypes signature + * Create a new instance by finding a constructor that matches the argumentTypes signature * using the arguments for instantiation. - * + * * @param className Full classname of class to create * @param argumentTypes The constructor argument types * @param arguments The constructor arguments @@ -120,12 +132,11 @@ public Constructor run() throws NoSuchMethodException * @author Aslak Knutsen * @author ALR */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) { - if (className == null) + if (implClass == null) { - throw new IllegalArgumentException("ClassName must be specified"); + throw new IllegalArgumentException("ImplClass must be specified"); } if (argumentTypes == null) { @@ -135,48 +146,120 @@ static T newInstance(final String className, final Class[] argumentTypes, { throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); } - final Object obj; + final T obj; try { - final ClassLoader tccl = getThreadContextClassLoader(); - final Class implClass = Class.forName(className, false, tccl); - Constructor constructor = getConstructor(implClass, argumentTypes); + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } obj = constructor.newInstance(arguments); } catch (Exception e) { - throw new RuntimeException("Could not create new instance of " + className - + ", missing package from classpath?", e); + throw new RuntimeException("Could not create new instance of " + implClass, e); } - // Cast + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { try { - return expectedType.cast(obj); + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); } - catch (final ClassCastException cce) + // Unwrap + catch (final PrivilegedActionException pae) { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - public static boolean isClassPresent(String name) + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException { try { - ClassLoader classLoader = getThreadContextClassLoader(); - classLoader.loadClass(name); - return true; + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); } - catch (ClassNotFoundException e) + // Unwrap + catch (final PrivilegedActionException pae) { - return false; + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) { List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() { @@ -189,7 +272,7 @@ public List run() { if(field.isAnnotationPresent(annotationClass)) { - if(!field.isAccessible()) + if(!field.isAccessible()) { field.setAccessible(true); } @@ -204,6 +287,67 @@ public List run() return declaredAccessableFields; } + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| //-------------------------------------------------------------------------------|| @@ -220,5 +364,4 @@ public ClassLoader run() } } - -} +} \ No newline at end of file diff --git a/test/spi/src/main/java/org/jboss/arquillian/test/spi/SecurityActions.java b/test/spi/src/main/java/org/jboss/arquillian/test/spi/SecurityActions.java index 22b0d5067..77f8a7ac9 100644 --- a/test/spi/src/main/java/org/jboss/arquillian/test/spi/SecurityActions.java +++ b/test/spi/src/main/java/org/jboss/arquillian/test/spi/SecurityActions.java @@ -16,18 +16,21 @@ */ package org.jboss.arquillian.test.spi; +import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; /** * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -56,65 +59,66 @@ static ClassLoader getThreadContextClassLoader() { return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - - static Class loadClass(String className) + + static boolean isClassPresent(String name) { - try + try { - return Class.forName(className, true, getThreadContextClassLoader()); + loadClass(name); + return true; } catch (Exception e) { - throw new RuntimeException("Could not load class", e); + return false; } } - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException + static Class loadClass(String className) { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - @Override - public Constructor run() throws NoSuchMethodException - { - return clazz.getDeclaredConstructor(argumentTypes); - } - }); + return Class.forName(className, true, getThreadContextClassLoader()); } - // Unwrap - catch (final PrivilegedActionException pae) + catch (ClassNotFoundException e) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) + try { - throw (NoSuchMethodException) t; + return Class.forName(className, true, SecurityActions.class.getClassLoader()); } - else + catch (ClassNotFoundException e2) { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + throw new RuntimeException("Could not load class " + className, e2); } } } + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + /** * Create a new instance by finding a constructor that matches the argumentTypes signature * using the arguments for instantiation. @@ -128,12 +132,11 @@ public Constructor run() throws NoSuchMethodException * @author Aslak Knutsen * @author ALR */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) { - if (className == null) + if (implClass == null) { - throw new IllegalArgumentException("ClassName must be specified"); + throw new IllegalArgumentException("ImplClass must be specified"); } if (argumentTypes == null) { @@ -143,47 +146,68 @@ static T newInstance(final String className, final Class[] argumentTypes, { throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); } - final Object obj; - final Class implClass; - try - { - final ClassLoader tccl = getThreadContextClassLoader(); - implClass = Class.forName(className, false, tccl); - } - catch (Exception e) - { - throw new RuntimeException("Could not load class " + className - + ", missing package from classpath?", e); - } - + final T obj; try { - Constructor constructor = getConstructor(implClass, argumentTypes); - if(!constructor.isAccessible()) - { + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { constructor.setAccessible(true); } obj = constructor.newInstance(arguments); } catch (Exception e) { - throw new RuntimeException("Could not create a new instance of class " + className - + " see cause.", e); + throw new RuntimeException("Could not create new instance of " + implClass, e); } - // Cast + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { try { - return expectedType.cast(obj); + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); } - catch (final ClassCastException cce) + // Unwrap + catch (final PrivilegedActionException pae) { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - + /** * Set a single Field value * @@ -235,6 +259,95 @@ public Void run() throws Exception } } + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundFields = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) + { + if(field.isAnnotationPresent(annotationClass)) + { + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundFields; + } + }); + return declaredAccessableFields; + } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| //-------------------------------------------------------------------------------|| @@ -245,12 +358,10 @@ public Void run() throws Exception private enum GetTcclAction implements PrivilegedAction { INSTANCE; - @Override public ClassLoader run() { return Thread.currentThread().getContextClassLoader(); } } - -} +} \ No newline at end of file diff --git a/test/spi/src/main/java/org/jboss/arquillian/test/spi/TestClass.java b/test/spi/src/main/java/org/jboss/arquillian/test/spi/TestClass.java index c6d5eb2de..c62024545 100644 --- a/test/spi/src/main/java/org/jboss/arquillian/test/spi/TestClass.java +++ b/test/spi/src/main/java/org/jboss/arquillian/test/spi/TestClass.java @@ -18,8 +18,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; /** @@ -62,29 +60,16 @@ public A getAnnotation(Class annotation) public Method getMethod(Class annotation) { - Method[] methods = testClass.getMethods(); - for(Method method: methods) + Method[] methods = getMethods(annotation); + if(methods.length > 0) { - if(method.isAnnotationPresent(annotation)) - { - return method; - } + return methods[0]; } return null; } public Method[] getMethods(Class annotation) { - List foundMethods = new ArrayList(); - Method[] methods = testClass.getMethods(); - for(Method method: methods) - { - if(method.isAnnotationPresent(annotation)) - { - foundMethods.add(method); - } - } - return foundMethods.toArray(new Method[0]); + return SecurityActions.getMethodsWithAnnotation(testClass, annotation).toArray(new Method[0]); } - -} +} \ No newline at end of file diff --git a/test/spi/src/main/java/org/jboss/arquillian/test/spi/util/SecurityActions.java b/test/spi/src/main/java/org/jboss/arquillian/test/spi/util/SecurityActions.java deleted file mode 100644 index 9ee527a7f..000000000 --- a/test/spi/src/main/java/org/jboss/arquillian/test/spi/util/SecurityActions.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * JBoss, Home of Professional Open Source - * Copyright 2009, Red Hat Middleware LLC, and individual contributors - * by the @authors tag. See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * Licensed 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.jboss.arquillian.test.spi.util; - -import java.lang.reflect.Constructor; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - -/** - * SecurityActions - * - * A set of privileged actions that are not to leak out - * of this package - * - * @author ALR - * @version $Revision: $ - */ -final class SecurityActions -{ - - //-------------------------------------------------------------------------------|| - // Constructor ------------------------------------------------------------------|| - //-------------------------------------------------------------------------------|| - - /** - * No instantiation - */ - private SecurityActions() - { - throw new UnsupportedOperationException("No instantiation"); - } - - //-------------------------------------------------------------------------------|| - // Utility Methods --------------------------------------------------------------|| - //-------------------------------------------------------------------------------|| - - /** - * Obtains the Thread Context ClassLoader - */ - static ClassLoader getThreadContextClassLoader() - { - return AccessController.doPrivileged(GetTcclAction.INSTANCE); - } - - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException - { - try - { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - public Constructor run() throws NoSuchMethodException - { - return clazz.getConstructor(argumentTypes); - } - }); - } - // Unwrap - catch (final PrivilegedActionException pae) - { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) - { - throw (NoSuchMethodException) t; - } - else - { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } - } - } - } - - /** - * Create a new instance by finding a constructor that matches the argumentTypes signature - * using the arguments for instantiation. - * - * @param className Full classname of class to create - * @param argumentTypes The constructor argument types - * @param arguments The constructor arguments - * @return a new instance - * @throws IllegalArgumentException if className, argumentTypes, or arguments are null - * @throws RuntimeException if any exceptions during creation - * @author Aslak Knutsen - * @author ALR - */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) - { - if (className == null) - { - throw new IllegalArgumentException("ClassName must be specified"); - } - if (argumentTypes == null) - { - throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments"); - } - if (arguments == null) - { - throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); - } - final Object obj; - try - { - final ClassLoader tccl = getThreadContextClassLoader(); - final Class implClass = Class.forName(className, false, tccl); - Constructor constructor = getConstructor(implClass, argumentTypes); - obj = constructor.newInstance(arguments); - } - catch (Exception e) - { - throw new RuntimeException("Could not create new instance of " + className - + ", missing package from classpath?", e); - } - - // Cast - try - { - return expectedType.cast(obj); - } - catch (final ClassCastException cce) - { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); - } - } - - //-------------------------------------------------------------------------------|| - // Inner Classes ----------------------------------------------------------------|| - //-------------------------------------------------------------------------------|| - - /** - * Single instance to get the TCCL - */ - private enum GetTcclAction implements PrivilegedAction { - INSTANCE; - - public ClassLoader run() - { - return Thread.currentThread().getContextClassLoader(); - } - - } - -} diff --git a/testenrichers/cdi/src/main/java/org/jboss/arquillian/testenricher/cdi/SecurityActions.java b/testenrichers/cdi/src/main/java/org/jboss/arquillian/testenricher/cdi/SecurityActions.java index 55ba56819..679a09edf 100644 --- a/testenrichers/cdi/src/main/java/org/jboss/arquillian/testenricher/cdi/SecurityActions.java +++ b/testenrichers/cdi/src/main/java/org/jboss/arquillian/testenricher/cdi/SecurityActions.java @@ -19,6 +19,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; @@ -27,12 +28,9 @@ import java.util.List; /** - * SecurityActions - * * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -62,51 +60,65 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - public Constructor run() throws NoSuchMethodException - { - return clazz.getConstructor(argumentTypes); - } - }); + return Class.forName(className, true, getThreadContextClassLoader()); } - // Unwrap - catch (final PrivilegedActionException pae) + catch (ClassNotFoundException e) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) + try { - throw (NoSuchMethodException) t; + return Class.forName(className, true, SecurityActions.class.getClassLoader()); } - else + catch (ClassNotFoundException e2) { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + throw new RuntimeException("Could not load class " + className, e2); } } } + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + /** * Create a new instance by finding a constructor that matches the argumentTypes signature * using the arguments for instantiation. @@ -120,12 +132,11 @@ public Constructor run() throws NoSuchMethodException * @author Aslak Knutsen * @author ALR */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) { - if (className == null) + if (implClass == null) { - throw new IllegalArgumentException("ClassName must be specified"); + throw new IllegalArgumentException("ImplClass must be specified"); } if (argumentTypes == null) { @@ -135,47 +146,119 @@ static T newInstance(final String className, final Class[] argumentTypes, { throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); } - final Object obj; + final T obj; try { - final ClassLoader tccl = getThreadContextClassLoader(); - final Class implClass = Class.forName(className, false, tccl); - Constructor constructor = getConstructor(implClass, argumentTypes); + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } obj = constructor.newInstance(arguments); } catch (Exception e) { - throw new RuntimeException("Could not create new instance of " + className - + ", missing package from classpath?", e); + throw new RuntimeException("Could not create new instance of " + implClass, e); } - // Cast + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { try { - return expectedType.cast(obj); + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); } - catch (final ClassCastException cce) + // Unwrap + catch (final PrivilegedActionException pae) { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - public static boolean isClassPresent(String name) + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException { - try + try { - ClassLoader classLoader = getThreadContextClassLoader(); - classLoader.loadClass(name); - return true; + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); } - catch (ClassNotFoundException e) + // Unwrap + catch (final PrivilegedActionException pae) { - return false; + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) { List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() @@ -183,23 +266,88 @@ public static List getFieldsWithAnnotation(final Class source, final C public List run() { List foundFields = new ArrayList(); - for(Field field : source.getDeclaredFields()) - { - if(field.isAnnotationPresent(annotationClass)) + Class nextSource = source; + while (nextSource != Object.class) { + for(Field field : nextSource.getDeclaredFields()) { - if(!field.isAccessible()) + if(field.isAnnotationPresent(annotationClass)) { - field.setAccessible(true); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + foundFields.add(field); } - foundFields.add(field); } + nextSource = nextSource.getSuperclass(); } return foundFields; } }); return declaredAccessableFields; } + + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + { + List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() + { + public List run() + { + List foundMethods = new ArrayList(); + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) + { + if(method.isAnnotationPresent(annotationClass)) + { + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); + } + } + nextSource = nextSource.getSuperclass(); + } + return foundMethods; + } + }); + return declaredAccessableMethods; + } + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| //-------------------------------------------------------------------------------|| @@ -216,5 +364,4 @@ public ClassLoader run() } } - -} +} \ No newline at end of file diff --git a/testenrichers/ejb/src/main/java/org/jboss/arquillian/testenricher/ejb/SecurityActions.java b/testenrichers/ejb/src/main/java/org/jboss/arquillian/testenricher/ejb/SecurityActions.java index de2ca3265..9f0fd156e 100644 --- a/testenrichers/ejb/src/main/java/org/jboss/arquillian/testenricher/ejb/SecurityActions.java +++ b/testenrichers/ejb/src/main/java/org/jboss/arquillian/testenricher/ejb/SecurityActions.java @@ -28,12 +28,9 @@ import java.util.List; /** - * SecurityActions - * * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -63,51 +60,65 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - public Constructor run() throws NoSuchMethodException - { - return clazz.getConstructor(argumentTypes); - } - }); + return Class.forName(className, true, getThreadContextClassLoader()); } - // Unwrap - catch (final PrivilegedActionException pae) + catch (ClassNotFoundException e) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) + try { - throw (NoSuchMethodException) t; + return Class.forName(className, true, SecurityActions.class.getClassLoader()); } - else + catch (ClassNotFoundException e2) { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + throw new RuntimeException("Could not load class " + className, e2); } } } + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + /** * Create a new instance by finding a constructor that matches the argumentTypes signature * using the arguments for instantiation. @@ -121,12 +132,11 @@ public Constructor run() throws NoSuchMethodException * @author Aslak Knutsen * @author ALR */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) { - if (className == null) + if (implClass == null) { - throw new IllegalArgumentException("ClassName must be specified"); + throw new IllegalArgumentException("ImplClass must be specified"); } if (argumentTypes == null) { @@ -136,48 +146,120 @@ static T newInstance(final String className, final Class[] argumentTypes, { throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); } - final Object obj; + final T obj; try { - final ClassLoader tccl = getThreadContextClassLoader(); - final Class implClass = Class.forName(className, false, tccl); - Constructor constructor = getConstructor(implClass, argumentTypes); + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } obj = constructor.newInstance(arguments); } catch (Exception e) { - throw new RuntimeException("Could not create new instance of " + className - + ", missing package from classpath?", e); + throw new RuntimeException("Could not create new instance of " + implClass, e); } - // Cast + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { try { - return expectedType.cast(obj); + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); } - catch (final ClassCastException cce) + // Unwrap + catch (final PrivilegedActionException pae) { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - static boolean isClassPresent(String name) + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException { - try + try { - ClassLoader classLoader = getThreadContextClassLoader(); - classLoader.loadClass(name); - return true; + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); } - catch (ClassNotFoundException e) + // Unwrap + catch (final PrivilegedActionException pae) { - return false; + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - - static List getFieldsWithAnnotation(final Class source, final Class annotationClass) + + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) { List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() { @@ -205,23 +287,27 @@ public List run() return declaredAccessableFields; } - static List getMethodsWithAnnotation(final Class source, final Class annotationClass) + public static List getMethodsWithAnnotation(final Class source, final Class annotationClass) { List declaredAccessableMethods = AccessController.doPrivileged(new PrivilegedAction>() { public List run() { List foundMethods = new ArrayList(); - for(Method method : source.getDeclaredMethods()) - { - if(method.isAnnotationPresent(annotationClass)) + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) { - if(!method.isAccessible()) + if(method.isAnnotationPresent(annotationClass)) { - method.setAccessible(true); + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); } - foundMethods.add(method); } + nextSource = nextSource.getSuperclass(); } return foundMethods; } @@ -229,6 +315,39 @@ public List run() return declaredAccessableMethods; } + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } + //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| //-------------------------------------------------------------------------------|| @@ -245,5 +364,4 @@ public ClassLoader run() } } - -} +} \ No newline at end of file diff --git a/testenrichers/resource/src/main/java/org/jboss/arquillian/testenricher/resource/SecurityActions.java b/testenrichers/resource/src/main/java/org/jboss/arquillian/testenricher/resource/SecurityActions.java index 73110e89e..52b883309 100644 --- a/testenrichers/resource/src/main/java/org/jboss/arquillian/testenricher/resource/SecurityActions.java +++ b/testenrichers/resource/src/main/java/org/jboss/arquillian/testenricher/resource/SecurityActions.java @@ -28,12 +28,9 @@ import java.util.List; /** - * SecurityActions - * * A set of privileged actions that are not to leak out * of this package * - * @author ALR * @version $Revision: $ */ final class SecurityActions @@ -63,51 +60,65 @@ static ClassLoader getThreadContextClassLoader() return AccessController.doPrivileged(GetTcclAction.INSTANCE); } - /** - * Obtains the Constructor specified from the given Class and argument types - * @param clazz - * @param argumentTypes - * @return - * @throws NoSuchMethodException - */ - static Constructor getConstructor(final Class clazz, final Class... argumentTypes) - throws NoSuchMethodException + static boolean isClassPresent(String name) + { + try + { + loadClass(name); + return true; + } + catch (Exception e) + { + return false; + } + } + + static Class loadClass(String className) { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction>() - { - public Constructor run() throws NoSuchMethodException - { - return clazz.getConstructor(argumentTypes); - } - }); + return Class.forName(className, true, getThreadContextClassLoader()); } - // Unwrap - catch (final PrivilegedActionException pae) + catch (ClassNotFoundException e) { - final Throwable t = pae.getCause(); - // Rethrow - if (t instanceof NoSuchMethodException) + try { - throw (NoSuchMethodException) t; + return Class.forName(className, true, SecurityActions.class.getClassLoader()); } - else + catch (ClassNotFoundException e2) { - // No other checked Exception thrown by Class.getConstructor - try - { - throw (RuntimeException) t; - } - // Just in case we've really messed up - catch (final ClassCastException cce) - { - throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); - } + throw new RuntimeException("Could not load class " + className, e2); } } } + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType) + { + return newInstance(className, argumentTypes, arguments, expectedType, getThreadContextClassLoader()); + } + + static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, final Class expectedType, ClassLoader classLoader) + { + Class clazz = null; + try + { + clazz = Class.forName(className, false, classLoader); + } + catch (Exception e) + { + throw new RuntimeException("Could not load class " + className, e); + } + Object obj = newInstance(clazz, argumentTypes, arguments); + try + { + return expectedType.cast(obj); + } + catch (Exception e) + { + throw new RuntimeException("Loaded class " + className + " is not of expected type " + expectedType, e); + } + } + /** * Create a new instance by finding a constructor that matches the argumentTypes signature * using the arguments for instantiation. @@ -121,12 +132,11 @@ public Constructor run() throws NoSuchMethodException * @author Aslak Knutsen * @author ALR */ - static T newInstance(final String className, final Class[] argumentTypes, final Object[] arguments, - final Class expectedType) + static T newInstance(final Class implClass, final Class[] argumentTypes, final Object[] arguments) { - if (className == null) + if (implClass == null) { - throw new IllegalArgumentException("ClassName must be specified"); + throw new IllegalArgumentException("ImplClass must be specified"); } if (argumentTypes == null) { @@ -136,47 +146,119 @@ static T newInstance(final String className, final Class[] argumentTypes, { throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments"); } - final Object obj; + final T obj; try { - final ClassLoader tccl = getThreadContextClassLoader(); - final Class implClass = Class.forName(className, false, tccl); - Constructor constructor = getConstructor(implClass, argumentTypes); + Constructor constructor = getConstructor(implClass, argumentTypes); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } obj = constructor.newInstance(arguments); } catch (Exception e) { - throw new RuntimeException("Could not create new instance of " + className - + ", missing package from classpath?", e); + throw new RuntimeException("Could not create new instance of " + implClass, e); } - // Cast + return obj; + } + + /** + * Obtains the Constructor specified from the given Class and argument types + * @param clazz + * @param argumentTypes + * @return + * @throws NoSuchMethodException + */ + static Constructor getConstructor(final Class clazz, final Class... argumentTypes) + throws NoSuchMethodException + { try { - return expectedType.cast(obj); + return AccessController.doPrivileged(new PrivilegedExceptionAction>() + { + public Constructor run() throws NoSuchMethodException + { + return clazz.getDeclaredConstructor(argumentTypes); + } + }); } - catch (final ClassCastException cce) + // Unwrap + catch (final PrivilegedActionException pae) { - // Reconstruct so we get some useful information - throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for " - + obj.getClass().getName()); + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchMethodException) + { + throw (NoSuchMethodException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - public static boolean isClassPresent(String name) + /** + * Set a single Field value + * + * @param target The object to set it on + * @param fieldName The field name + * @param value The new value + */ + public static void setFieldValue(final Class source, final Object target, final String fieldName, final Object value) throws NoSuchFieldException { - try + try { - ClassLoader classLoader = getThreadContextClassLoader(); - classLoader.loadClass(name); - return true; + AccessController.doPrivileged(new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + Field field = source.getDeclaredField(fieldName); + if(!field.isAccessible()) + { + field.setAccessible(true); + } + field.set(target, value); + return null; + } + }); } - catch (ClassNotFoundException e) + // Unwrap + catch (final PrivilegedActionException pae) { - return false; + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof NoSuchFieldException) + { + throw (NoSuchFieldException) t; + } + else + { + // No other checked Exception thrown by Class.getConstructor + try + { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) + { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } } } - + public static List getFieldsWithAnnotation(final Class source, final Class annotationClass) { List declaredAccessableFields = AccessController.doPrivileged(new PrivilegedAction>() @@ -212,22 +294,59 @@ public static List getMethodsWithAnnotation(final Class source, final public List run() { List foundMethods = new ArrayList(); - for(Method method : source.getDeclaredMethods()) - { - if(method.isAnnotationPresent(annotationClass)) + Class nextSource = source; + while (nextSource != Object.class) { + for(Method method : nextSource.getDeclaredMethods()) { - if(!method.isAccessible()) + if(method.isAnnotationPresent(annotationClass)) { - method.setAccessible(true); + if(!method.isAccessible()) + { + method.setAccessible(true); + } + foundMethods.add(method); } - foundMethods.add(method); } + nextSource = nextSource.getSuperclass(); } return foundMethods; } }); return declaredAccessableMethods; } + + static String getProperty(final String key) { + try { + String value = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public String run() { + return System.getProperty(key); + } + }); + return value; + } + // Unwrap + catch (final PrivilegedActionException pae) { + final Throwable t = pae.getCause(); + // Rethrow + if (t instanceof SecurityException) { + throw (SecurityException) t; + } + if (t instanceof NullPointerException) { + throw (NullPointerException) t; + } else if (t instanceof IllegalArgumentException) { + throw (IllegalArgumentException) t; + } else { + // No other checked Exception thrown by System.getProperty + try { + throw (RuntimeException) t; + } + // Just in case we've really messed up + catch (final ClassCastException cce) { + throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t); + } + } + } + } //-------------------------------------------------------------------------------|| // Inner Classes ----------------------------------------------------------------|| @@ -245,5 +364,4 @@ public ClassLoader run() } } - -} +} \ No newline at end of file