bval-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mben...@apache.org
Subject svn commit: r1643452 - in /bval/branches/bval-11/bval-core/src/main/java/org/apache/bval: ConstructorAccess.java util/AccessStrategy.java util/FieldAccess.java util/MethodAccess.java util/PropertyAccess.java util/reflection/Reflection.java
Date Fri, 05 Dec 2014 22:16:51 GMT
Author: mbenson
Date: Fri Dec  5 22:16:50 2014
New Revision: 1643452

URL: http://svn.apache.org/r1643452
Log:
clean up when we alter accessibility of members

Modified:
    bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/ConstructorAccess.java
    bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/AccessStrategy.java
    bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/FieldAccess.java
    bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/MethodAccess.java
    bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/PropertyAccess.java
    bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/reflection/Reflection.java

Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/ConstructorAccess.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/ConstructorAccess.java?rev=1643452&r1=1643451&r2=1643452&view=diff
==============================================================================
--- bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/ConstructorAccess.java (original)
+++ bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/ConstructorAccess.java Fri
Dec  5 22:16:50 2014
@@ -28,7 +28,6 @@ public class ConstructorAccess extends A
 
     public ConstructorAccess(final Constructor<?> constructor) {
         this.constructor = constructor;
-        setAccessible(constructor);
     }
 
     @Override

Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/AccessStrategy.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/AccessStrategy.java?rev=1643452&r1=1643451&r2=1643452&view=diff
==============================================================================
--- bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/AccessStrategy.java
(original)
+++ bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/AccessStrategy.java
Fri Dec  5 22:16:50 2014
@@ -17,11 +17,8 @@
 package org.apache.bval.util;
 
 import java.lang.annotation.ElementType;
-import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Type;
 
-import org.apache.commons.weaver.privilizer.Privileged;
-
 /**
  * Description: abstract class to encapsulate different strategies
  * to get the value of a Property.  This class is designed such that
@@ -59,20 +56,4 @@ public abstract class AccessStrategy {
      */
     public abstract String getPropertyName();
 
-    /**
-     * Set {@code accessibleObject} as being accessible
-     * @param accessibleObject
-     */
-    protected boolean setAccessible(AccessibleObject accessibleObject) {
-        if (accessibleObject.isAccessible()) {
-            return false;
-        }
-        doSetAccessible(accessibleObject);
-        return true;
-    }
-
-    @Privileged
-    private void doSetAccessible(AccessibleObject accessibleObject) {
-        accessibleObject.setAccessible(true);
-    }
 }

Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/FieldAccess.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/FieldAccess.java?rev=1643452&r1=1643451&r2=1643452&view=diff
==============================================================================
--- bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/FieldAccess.java (original)
+++ bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/FieldAccess.java Fri
Dec  5 22:16:50 2014
@@ -20,9 +20,14 @@ import java.lang.annotation.ElementType;
 import java.lang.reflect.Field;
 import java.lang.reflect.Type;
 
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+
 /**
  * Description: direct field access strategy.<br/>
  */
+@Privilizing(@CallTo(Reflection.class))
 public class FieldAccess extends AccessStrategy {
 
     private final Field field;
@@ -33,17 +38,21 @@ public class FieldAccess extends AccessS
      */
     public FieldAccess(final Field field) {
         this.field = field;
-        setAccessible(field);
     }
 
     /**
      * {@inheritDoc}
      */
     public Object get(final Object instance) {
+        final boolean mustUnset = Reflection.setAccessible(field, true);
         try {
             return field.get(instance);
         } catch (IllegalAccessException e) {
             throw new IllegalArgumentException(e);
+        } finally {
+            if (mustUnset) {
+                Reflection.setAccessible(field, false);
+            }
         }
     }
 

Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/MethodAccess.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/MethodAccess.java?rev=1643452&r1=1643451&r2=1643452&view=diff
==============================================================================
--- bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/MethodAccess.java (original)
+++ bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/MethodAccess.java Fri
Dec  5 22:16:50 2014
@@ -22,9 +22,14 @@ import java.lang.reflect.InvocationTarge
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+
 /**
  * Description: invoke a zero-argument method (getter)<br/>
  */
+@Privilizing(@CallTo(Reflection.class))
 public class MethodAccess extends AccessStrategy {
     private final Method method;
     private final String propertyName;
@@ -45,7 +50,6 @@ public class MethodAccess extends Access
     public MethodAccess(String propertyName, final Method method) {
         this.method = method;
         this.propertyName = propertyName;
-        setAccessible(method);
     }
 
     /**
@@ -80,12 +84,17 @@ public class MethodAccess extends Access
      * {@inheritDoc}
      */
     public Object get(final Object instance) {
+        final boolean mustUnset = Reflection.setAccessible(method, true);
         try {
             return method.invoke(instance);
         } catch (IllegalAccessException e) {
             throw new IllegalArgumentException(e);
         } catch (InvocationTargetException e) {
             throw new IllegalArgumentException(e);
+        } finally {
+            if (mustUnset) {
+                Reflection.setAccessible(method, false);
+            }
         }
     }
 

Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/PropertyAccess.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/PropertyAccess.java?rev=1643452&r1=1643451&r2=1643452&view=diff
==============================================================================
--- bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/PropertyAccess.java
(original)
+++ bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/PropertyAccess.java
Fri Dec  5 22:16:50 2014
@@ -16,6 +16,7 @@
  */
 package org.apache.bval.util;
 
+import org.apache.bval.util.reflection.Reflection;
 import org.apache.commons.beanutils.PropertyUtils;
 
 import java.beans.PropertyDescriptor;
@@ -149,6 +150,17 @@ public class PropertyAccess extends Acce
         return null;
     }
 
+    private static Object readField(Field field, Object bean) throws IllegalAccessException
{
+        final boolean mustUnset = Reflection.setAccessible(field, true);
+        try {
+            return field.get(bean);
+        } finally {
+            if (mustUnset) {
+                Reflection.setAccessible(field, false);
+            }
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -162,7 +174,7 @@ public class PropertyAccess extends Acce
     public Object get(Object bean) {
         try {
             if (rememberField != null) { // cache field of previous access
-                return rememberField.get(bean);
+                return readField(rememberField, bean);
             }
             try { // try public method
                 return getPublicProperty(bean, propertyName);
@@ -180,15 +192,12 @@ public class PropertyAccess extends Acce
         Field field = getField(propertyName, beanClass);
         if (field != null) {
             cacheField(field);
-            return rememberField.get(bean);
+            return readField(rememberField, bean);
         }
         throw new IllegalArgumentException("cannot access field " + propertyName);
     }
 
     private void cacheField(Field field) {
-        if (!field.isAccessible()) {
-            field.setAccessible(true);
-        }
         this.rememberField = field;
     }
 

Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/reflection/Reflection.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/reflection/Reflection.java?rev=1643452&r1=1643451&r2=1643452&view=diff
==============================================================================
--- bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/reflection/Reflection.java
(original)
+++ bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/util/reflection/Reflection.java
Fri Dec  5 22:16:50 2014
@@ -17,89 +17,112 @@
 package org.apache.bval.util.reflection;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
 import org.apache.commons.lang3.ClassUtils;
+import org.apache.commons.weaver.privilizer.Privilizing;
 
 /**
- * Security-agnostic "blueprint" class for reflection-related operations.
+ * Security-agnostic "blueprint" class for reflection-related operations. Intended for use
by Apache BVal code.
  * 
  * @version $Rev$ $Date$
  */
 public class Reflection {
 
-    private static void setAccessibility(final Field field) {
-        // FIXME 2011-03-27 jw:
-        // - Why not simply call field.setAccessible(true)?
-        // - Fields can not be abstract.
-        if (!Modifier.isPublic(field.getModifiers())
-            || (Modifier.isPublic(field.getModifiers()) && Modifier.isAbstract(field.getModifiers())))
{
-            field.setAccessible(true);
-        }
-    }
-
+    /**
+     * Get the named {@link Class} from the specified {@link ClassLoader}.
+     * @param classLoader
+     * @param className
+     * @return Class
+     * @throws Exception
+     */
     public static Class<?> getClass(final ClassLoader classLoader, final String className)
throws Exception {
         return ClassUtils.getClass(classLoader, className, true);
     }
 
+    /**
+     * Get the named value from the specified {@link Annotation}.
+     * @param annotation
+     * @param name
+     * @return Object value
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
     public static Object getAnnotationValue(final Annotation annotation, final String name)
         throws IllegalAccessException, InvocationTargetException {
-        Method valueMethod;
+        final Method valueMethod;
         try {
             valueMethod = annotation.annotationType().getDeclaredMethod(name);
         } catch (final NoSuchMethodException ex) {
             // do nothing
-            valueMethod = null;
+            return null;
         }
-        if (null != valueMethod) {
-            if (!valueMethod.isAccessible()) {
-                valueMethod.setAccessible(true);
-            }
+        final boolean mustUnset = setAccessible(valueMethod, true);
+        try {
             return valueMethod.invoke(annotation);
+        } finally {
+            if (mustUnset) {
+                setAccessible(valueMethod, false);
+            }
         }
-        return null;
     }
 
+    /**
+     * Get a usable {@link ClassLoader}: that of {@code clazz} if {@link Thread#getContextClassLoader()}
returns {@code null}.
+     * @param clazz
+     * @return {@link ClassLoader}
+     */
     public static ClassLoader getClassLoader(final Class<?> clazz) {
         final ClassLoader cl = Thread.currentThread().getContextClassLoader();
-        if (cl != null) {
-            return cl;
-        }
-        return clazz.getClassLoader();
+        return cl == null ? clazz.getClassLoader() : cl;
     }
 
+    /**
+     * Convenient point for {@link Privilizing} {@link System#getProperty(String)}.
+     * @param name
+     * @return String
+     */
     public static String getProperty(final String name) {
         return System.getProperty(name);
     }
 
+    /**
+     * Get the declared field from {@code clazz}.
+     * @param clazz
+     * @param fieldName
+     * @return {@link Field} or {@code null}
+     */
     public static Field getDeclaredField(final Class<?> clazz, final String fieldName)
{
-        final Field f;
         try {
-            f = clazz.getDeclaredField(fieldName);
+            return clazz.getDeclaredField(fieldName);
         } catch (final NoSuchFieldException e) {
             return null;
         }
-        setAccessibility(f);
-        return f;
     }
 
+    /**
+     * Convenient point for {@link Privilizing} {@link Class#getDeclaredFields()}.
+     * @param clazz
+     * @return {@link Field} array
+     */
     public static Field[] getDeclaredFields(final Class<?> clazz) {
-        final Field[] fields = clazz.getDeclaredFields();
-        if (fields.length > 0) {
-            for (final Field f : fields) {
-                if (!f.isAccessible()) {
-                    f.setAccessible(true);
-                }
-            }
-        }
-        return fields;
+        return clazz.getDeclaredFields();
     }
 
-    public static Constructor<?> getDeclaredConstructor(final Class<?> clazz,
final Class<?>... parameters) {
+    /**
+     * Get the declared constructor from {@code clazz}.
+     * @param T generic type
+     * @param clazz
+     * @param parameters
+     * @return {@link Constructor} or {@code null}
+     */
+    public static <T> Constructor<T> getDeclaredConstructor(final Class<T>
clazz, final Class<?>... parameters) {
         try {
             return clazz.getDeclaredConstructor(parameters);
         } catch (final NoSuchMethodException e) {
@@ -107,6 +130,13 @@ public class Reflection {
         }
     }
 
+    /**
+     * Get the declared method from {@code clazz}.
+     * @param clazz
+     * @param name
+     * @param parameters
+     * @return {@link Method} or {@code null}
+     */
     public static Method getDeclaredMethod(final Class<?> clazz, final String name,
final Class<?>... parameters) {
         try {
             return clazz.getDeclaredMethod(name, parameters);
@@ -115,22 +145,43 @@ public class Reflection {
         }
     }
 
+    /**
+     * Convenient point for {@link Privilizing} {@link Class#getDeclaredMethods()}.
+     * @param clazz
+     * @return {@link Method} array
+     */
     public static Method[] getDeclaredMethods(final Class<?> clazz) {
         return clazz.getDeclaredMethods();
     }
 
+    /**
+     * Convenient point for {@link Privilizing} {@link Class#getDeclaredConstructors()}.
+     * @param clazz
+     * @return {@link Constructor} array
+     */
     public static Constructor<?>[] getDeclaredConstructors(final Class<?> clazz)
{
         return clazz.getDeclaredConstructors();
     }
 
-    public static Method getPublicMethod(final Class<?> clazz, final String methodName)
{
+    /**
+     * Get the specified {@code public} {@link Method} from {@code clazz}.
+     * @param clazz
+     * @param methodName
+     * @return {@link Method} or {@code null}
+     */
+    public static Method getPublicMethod(final Class<?> clazz, final String methodName,
Class<?>... parameterTypes) {
         try {
-            return clazz.getMethod(methodName);
+            return clazz.getMethod(methodName, parameterTypes);
         } catch (final NoSuchMethodException e) {
             return null;
         }
     }
 
+    /**
+     * Construct a new instance of {@code cls} using its default constructor.
+     * @param cls
+     * @return T
+     */
     public static <T> T newInstance(final Class<T> cls) {
         try {
             return cls.newInstance();
@@ -139,4 +190,39 @@ public class Reflection {
         }
     }
 
+    /**
+     * Set the accessibility of {@code o} to {@code accessible}.
+     * @param o
+     * @param accessible
+     * @return whether a change was made.
+     */
+    public static boolean setAccessible(final AccessibleObject o, boolean accessible) {
+        if (o == null || o.isAccessible() == accessible) {
+            return false;
+        }
+        final Member m = (Member) o;
+        if (Modifier.isPublic(m.getModifiers())) {
+            /*
+             * For objects with public accessibility, we do nothing and return with one exception.
+             * 
+             * Following explanation copied from Apache Commons [lang] MemberUtils:
+             * When a {@code public} class has a default access superclass with {@code public}
members,
+             * these members are accessible. Calling them from compiled code works fine.
+             * Unfortunately, on some JVMs, using reflection to invoke these members
+             * seems to (wrongly) prevent access even when the modifier is {@code public}.
+             * Calling {@code setAccessible(true)} solves the problem but will only work
from
+             * sufficiently privileged code.
+             */
+            if (!isPackageAccess(m.getDeclaringClass().getModifiers())) {
+                return false;
+            }
+        }
+        o.setAccessible(accessible);
+        return true;
+    }
+
+    private static boolean isPackageAccess(final int modifiers) {
+        return (modifiers & (Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC))
== 0;
+    }
+
 }



Mime
View raw message