You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mb...@apache.org on 2018/04/29 19:41:03 UTC

[commons-weaver] 12/13: blueprint method references; reject blueprint methods that access inaccessible classes/methods/ctors (other than other methods also being imported

This is an automated email from the ASF dual-hosted git repository.

mbenson pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-weaver.git

commit 6569dd18ec5c9a02cb3308d1552de7d0c5ed3505
Author: Matt Benson <mb...@apache.org>
AuthorDate: Tue Apr 24 17:16:02 2018 -0500

    blueprint method references; reject blueprint methods that access inaccessible classes/methods/ctors (other than other methods also being imported
---
 modules/privilizer/weaver/src/it/sample/pom.xml    |   7 +
 .../example/MethodReferencesUsingBlueprints.java   |  67 ++++++
 .../MethodReferencesUsingBlueprintsTest.java       |  81 +++++++
 .../weaver/privilizer/BlueprintingVisitor.java     | 256 ++++++++++++++-------
 .../commons/weaver/privilizer/Privilizer.java      |  44 ++--
 5 files changed, 346 insertions(+), 109 deletions(-)

diff --git a/modules/privilizer/weaver/src/it/sample/pom.xml b/modules/privilizer/weaver/src/it/sample/pom.xml
index e0c2d20..c1927c4 100755
--- a/modules/privilizer/weaver/src/it/sample/pom.xml
+++ b/modules/privilizer/weaver/src/it/sample/pom.xml
@@ -54,6 +54,13 @@ under the License.
   <build>
     <plugins>
       <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+      <plugin>
         <groupId>@project.groupId@</groupId>
         <artifactId>commons-weaver-maven-plugin</artifactId>
         <version>@project.version@</version>
diff --git a/modules/privilizer/weaver/src/it/sample/src/main/java/org/apache/commons/weaver/privilizer/example/MethodReferencesUsingBlueprints.java b/modules/privilizer/weaver/src/it/sample/src/main/java/org/apache/commons/weaver/privilizer/example/MethodReferencesUsingBlueprints.java
new file mode 100644
index 0000000..3e696be
--- /dev/null
+++ b/modules/privilizer/weaver/src/it/sample/src/main/java/org/apache/commons/weaver/privilizer/example/MethodReferencesUsingBlueprints.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.commons.weaver.privilizer.example;
+
+import java.util.function.BiFunction;
+import java.util.function.BinaryOperator;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
+
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+
+@Privilizing({ @CallTo(Utils.class), @CallTo(value = Utils.More.class, methods = "getProperty") })
+public class MethodReferencesUsingBlueprints {
+
+    public String utilsReadPublicConstant() {
+        final Supplier<String> s = Utils::readPublicConstant;
+        return s.get();
+    }
+
+    public int utilsReadPrivateField() {
+        final IntSupplier s = Utils::readPrivateField;
+        return s.getAsInt();
+    }
+
+    public String utilsGetProperty() {
+        final Supplier<String> s = Utils::getProperty;
+        return s.get();
+    }
+
+    public String utilsGetProperty(int i, String key) {
+        final BiFunction<Integer, String, String> f = Utils::getProperty;
+        return f.apply(i, key);
+    }
+
+    public String utilsGetProperty(String key) {
+        final UnaryOperator<String> o = Utils::getProperty;
+        return o.apply(key);
+    }
+
+    public String moreGetProperty() {
+        final Supplier<String> s = Utils.More::getProperty;
+        return s.get();
+    }
+
+    public String moreGetTopStackElementClassName() {
+        final Supplier<String> s = Utils.More::getTopStackElementClassName;
+        return s.get();
+    }
+}
diff --git a/modules/privilizer/weaver/src/it/sample/src/test/java/org/apache/commons/weaver/privilizer/example/MethodReferencesUsingBlueprintsTest.java b/modules/privilizer/weaver/src/it/sample/src/test/java/org/apache/commons/weaver/privilizer/example/MethodReferencesUsingBlueprintsTest.java
new file mode 100644
index 0000000..1fb59d6
--- /dev/null
+++ b/modules/privilizer/weaver/src/it/sample/src/test/java/org/apache/commons/weaver/privilizer/example/MethodReferencesUsingBlueprintsTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.commons.weaver.privilizer.example;
+
+import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.SystemUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class MethodReferencesUsingBlueprintsTest {
+
+    private MethodReferencesUsingBlueprints methodReferencesUsingBlueprints;
+
+    @Before
+    public void setUp() throws Exception {
+        Setup.setProperty("foo", "foo-value");
+        Setup.setProperty("bar", "bar-value");
+        Setup.setProperty("baz", "baz-value");
+        methodReferencesUsingBlueprints = new MethodReferencesUsingBlueprints();
+    }
+
+    @Test
+    public void testUtilsReadPublicConstant() {
+        assertEquals(Utils.FOO, methodReferencesUsingBlueprints.utilsReadPublicConstant());
+    }
+
+    @Test
+    public void testUtilsReadPrivateField() {
+        assertEquals(999, methodReferencesUsingBlueprints.utilsReadPrivateField());
+    }
+
+    @Test
+    public void testUtilsGetProperty() {
+        assertEquals("foo-value", methodReferencesUsingBlueprints.utilsGetProperty());
+    }
+
+    @Test
+    public void testUtilsGetProperty_String() {
+        assertEquals("foo-value", methodReferencesUsingBlueprints.utilsGetProperty("foo"));
+        assertEquals("bar-value", methodReferencesUsingBlueprints.utilsGetProperty("bar"));
+        assertEquals("baz-value", methodReferencesUsingBlueprints.utilsGetProperty("baz"));
+    }
+
+    @Test
+    public void testUtilsGetProperty_int_String() {
+        assertEquals("foo-value", methodReferencesUsingBlueprints.utilsGetProperty(2, "foo"));
+        assertEquals("bar-value", methodReferencesUsingBlueprints.utilsGetProperty(2, "bar"));
+        assertEquals("baz-value", methodReferencesUsingBlueprints.utilsGetProperty(2, "baz"));
+    }
+
+    @Test
+    public void testMoreGetProperty() {
+        assertEquals("bar-value", methodReferencesUsingBlueprints.moreGetProperty());
+    }
+
+    @Test
+    public void testMoreGetTopStackElementClassName() {
+        assumeTrue(StringUtils.containsIgnoreCase(SystemUtils.JAVA_VENDOR, "oracle"));
+        assertEquals(Utils.More.class.getName(), methodReferencesUsingBlueprints.moreGetTopStackElementClassName());
+    }
+}
diff --git a/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/BlueprintingVisitor.java b/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/BlueprintingVisitor.java
index b306a39..e6c6226 100644
--- a/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/BlueprintingVisitor.java
+++ b/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/BlueprintingVisitor.java
@@ -19,25 +19,29 @@
 package org.apache.commons.weaver.privilizer;
 
 import java.io.InputStream;
+import java.lang.invoke.LambdaMetafactory;
 import java.lang.reflect.Modifier;
-import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.BitSet;
-import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.Validate;
-import org.apache.commons.lang3.mutable.MutableObject;
 import org.apache.commons.lang3.tuple.Pair;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Handle;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
@@ -46,19 +50,40 @@ import org.objectweb.asm.commons.AdviceAdapter;
 import org.objectweb.asm.commons.GeneratorAdapter;
 import org.objectweb.asm.commons.Method;
 import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
 import org.objectweb.asm.tree.MethodNode;
 
 /**
  * {@link ClassVisitor} to import so-called "blueprint methods".
  */
 class BlueprintingVisitor extends Privilizer.PrivilizerClassVisitor {
+    static class TypeInfo {
+        final int access;
+        final String superName;
+        final Map<String, FieldNode> fields;
+        final Map<Method, MethodNode> methods;
+
+        TypeInfo(int access, String superName, Map<String, FieldNode> fields, Map<Method, MethodNode> methods) {
+            super();
+            this.access = access;
+            this.superName = superName;
+            this.fields = fields;
+            this.methods = methods;
+        }
+    }
+
+    private static final Type LAMBDA_METAFACTORY = Type.getType(LambdaMetafactory.class);
+
+    private static Pair<Type, Method> methodKey(String owner, String name, String desc) {
+        return Pair.of(Type.getObjectType(owner), new Method(name, desc));
+    }
 
     private final Set<Type> blueprintTypes = new HashSet<>();
     private final Map<Pair<Type, Method>, MethodNode> blueprintRegistry = new HashMap<>();
 
     private final Map<Pair<Type, Method>, String> importedMethods = new HashMap<>();
 
-    private final Map<Type, Map<Method, MethodNode>> methodCache = new HashMap<>();
+    private final Map<Type, TypeInfo> typeInfoCache = new HashMap<>();
     private final Map<Pair<Type, String>, FieldAccess> fieldAccessMap = new HashMap<>();
 
     private final ClassVisitor nextVisitor;
@@ -79,46 +104,28 @@ class BlueprintingVisitor extends Privilizer.PrivilizerClassVisitor {
         for (final Privilizing.CallTo callTo : config.value()) {
             final Type blueprintType = Type.getType(callTo.value());
             blueprintTypes.add(blueprintType);
-            for (final Map.Entry<Method, MethodNode> entry : getMethods(blueprintType).entrySet()) {
-                boolean found = false;
-                if (callTo.methods().length == 0) {
-                    found = true;
-                } else {
-                    for (final String name : callTo.methods()) {
-                        if (entry.getKey().getName().equals(name)) {
-                            found = true;
-                            break;
-                        }
-                    }
-                }
-                if (found) {
-                    blueprintRegistry.put(Pair.of(blueprintType, entry.getKey()), entry.getValue());
-                }
-            }
-        }
-    }
 
-    private Map<Method, MethodNode> getMethods(final Type type) {
-        if (methodCache.containsKey(type)) {
-            return methodCache.get(type);
+            final Set<String> methodNames = new HashSet<>(Arrays.asList(callTo.methods()));
+
+            typeInfo(blueprintType).methods.entrySet().stream()
+                .filter(e -> methodNames.isEmpty() || methodNames.contains(e.getKey().getName()))
+                .forEach(e -> blueprintRegistry.put(Pair.of(blueprintType, e.getKey()), e.getValue()));
         }
-        final ClassNode classNode = read(type.getClassName());
-        final Map<Method, MethodNode> result = new HashMap<>();
+    }
 
-        final List<MethodNode> methods = classNode.methods;
+    private TypeInfo typeInfo(Type type) {
+        return typeInfoCache.computeIfAbsent(type, k -> {
+            final ClassNode cn = read(k.getClassName());
 
-        for (final MethodNode methodNode : methods) {
-            if (Modifier.isStatic(methodNode.access) && !"<clinit>".equals(methodNode.name)) {
-                result.put(new Method(methodNode.name, methodNode.desc), methodNode);
-            }
-        }
-        methodCache.put(type, result);
-        return result;
+            return new TypeInfo(cn.access, cn.superName,
+                cn.fields.stream().collect(Collectors.toMap(f -> f.name, Function.identity())),
+                cn.methods.stream().collect(Collectors.toMap(m -> new Method(m.name, m.desc), Function.identity())));
+        });
     }
 
     private ClassNode read(final String className) {
         final ClassNode result = new ClassNode(Privilizer.ASM_VERSION);
-        try (InputStream bytecode = privilizer().env.getClassfile(className).getInputStream();) {
+        try (InputStream bytecode = privilizer().env.getClassfile(className).getInputStream()) {
             new ClassReader(bytecode).accept(result, ClassReader.SKIP_DEBUG | ClassReader.EXPAND_FRAMES);
         } catch (final Exception e) {
             throw new RuntimeException(e);
@@ -159,7 +166,7 @@ class BlueprintingVisitor extends Privilizer.PrivilizerClassVisitor {
         privilizer().env.debug("importing %s#%s as %s", key.getLeft().getClassName(), key.getRight(), result);
         final int access = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC + Opcodes.ACC_SYNTHETIC;
 
-        final MethodNode source = getMethods(key.getLeft()).get(key.getRight());
+        final MethodNode source = typeInfo(key.getLeft()).methods.get(key.getRight());
 
         final String[] exceptions = source.exceptions.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
 
@@ -182,7 +189,7 @@ class BlueprintingVisitor extends Privilizer.PrivilizerClassVisitor {
             new MethodNode(access, result, source.desc, source.signature, exceptions);
 
         // spider own methods:
-        MethodVisitor mv = new NestedMethodInvocationHandler(withAccessibleAdvice, key.getLeft()); //NOPMD
+        MethodVisitor mv = new NestedMethodInvocationHandler(withAccessibleAdvice, key); //NOPMD
 
         if (!fieldAccesses.isEmpty()) {
             mv = new AccessibleAdvisor(mv, access, result, source.desc, new ArrayList<>(fieldAccesses));
@@ -199,49 +206,11 @@ class BlueprintingVisitor extends Privilizer.PrivilizerClassVisitor {
     }
 
     private FieldAccess fieldAccess(final Type owner, final String name) {
-        final Pair<Type, String> key = Pair.of(owner, name);
-        if (!fieldAccessMap.containsKey(key)) {
-            try {
-                final MutableObject<Type> next = new MutableObject<>(owner);
-                final Deque<Type> stk = new ArrayDeque<>();
-                while (next.getValue() != null) {
-                    stk.push(next.getValue());
-                    try (InputStream bytecode =
-                        privilizer().env.getClassfile(next.getValue().getInternalName()).getInputStream()) {
-                        new ClassReader(bytecode).accept(privilizer().new PrivilizerClassVisitor() {
-                            @Override
-                            @SuppressWarnings("PMD.UseVarargs") // overridden method
-                            public void visit(final int version, final int access, final String name,
-                                final String signature, final String superName, final String[] interfaces) {
-                                super.visit(version, access, name, signature, superName, interfaces);
-                                next.setValue(Type.getObjectType(superName));
-                            }
-
-                            @Override
-                            public FieldVisitor visitField(final int access, final String name, final String desc,
-                                final String signature, final Object value) {
-                                for (final Type type : stk) {
-                                    final Pair<Type, String> key = Pair.of(type, name);
-                                    // skip shadowed fields:
-                                    if (!fieldAccessMap.containsKey(key)) {
-                                        fieldAccessMap.put(key,
-                                            new FieldAccess(access, target, name, Type.getType(desc)));
-                                    }
-                                }
-                                return null;
-                            }
-                        }, ClassReader.SKIP_CODE);
-                    }
-                    if (fieldAccessMap.containsKey(key)) {
-                        break;
-                    }
-                }
-            } catch (final Exception e) {
-                throw new RuntimeException(e);
-            }
-            Validate.isTrue(fieldAccessMap.containsKey(key), "Could not locate %s.%s", owner.getClassName(), name);
-        }
-        return fieldAccessMap.get(key);
+        return fieldAccessMap.computeIfAbsent(Pair.of(owner, name), k -> {
+            final FieldNode fieldNode = typeInfo(k.getLeft()).fields.get(k.getRight());
+            Validate.validState(fieldNode != null, "Could not locate %s.%s", k.getLeft().getClassName(), k.getRight());
+            return new FieldAccess(fieldNode.access, k.getLeft(), fieldNode.name, Type.getType(fieldNode.desc));
+        });
     }
 
     @Override
@@ -259,26 +228,109 @@ class BlueprintingVisitor extends Privilizer.PrivilizerClassVisitor {
         public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc,
             final boolean itf) {
             if (opcode == Opcodes.INVOKESTATIC) {
-                final Method methd = new Method(name, desc);
-                final Pair<Type, Method> methodKey = Pair.of(Type.getObjectType(owner), methd);
+                final Pair<Type, Method> methodKey = methodKey(owner, name, desc);
                 if (shouldImport(methodKey)) {
                     final String importedName = importMethod(methodKey);
                     super.visitMethodInsn(opcode, className, importedName, desc, itf);
                     return;
                 }
             }
+            visitNonImportedMethodInsn(opcode, owner, name, desc, itf);
+        }
+
+        protected void visitNonImportedMethodInsn(final int opcode, final String owner, final String name,
+            final String desc, final boolean itf) {
             super.visitMethodInsn(opcode, owner, name, desc, itf);
         }
 
+        @Override
+        public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle,
+            Object... bootstrapMethodArguments) {
+
+            if (isLambda(bootstrapMethodHandle)) {
+                Object[] args = bootstrapMethodArguments;
+
+                Handle handle = null;
+
+                for (int i = 0; i < args.length; i++) {
+                    if (bootstrapMethodArguments[i] instanceof Handle) {
+                        if (handle != null) {
+                            // we don't know what to do with multiple handles; skip the whole thing:
+                            args = bootstrapMethodArguments;
+                            break;
+                        }
+                        handle = (Handle) args[i];
+
+                        if (handle.getTag() == Opcodes.H_INVOKESTATIC) {
+                            final Pair<Type, Method> methodKey =
+                                methodKey(handle.getOwner(), handle.getName(), handle.getDesc());
+
+                            if (shouldImport(methodKey)) {
+                                final String importedName = importMethod(methodKey);
+                                args = bootstrapMethodArguments.clone();
+                                args[i] = new Handle(handle.getTag(), className, importedName, handle.getDesc(), false);
+                            }
+                        }
+                    }
+                }
+                if (handle != null) {
+                    if (args == bootstrapMethodArguments) {
+                        validateLambda(handle);
+                    } else {
+                        super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, args);
+                        return;
+                    }
+                }
+            }
+            super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+        }
+
+        protected void validateLambda(Handle handle) {
+        }
+
         abstract boolean shouldImport(Pair<Type, Method> methodKey);
+
+        private boolean isLambda(Handle handle) {
+            return handle.getTag() == Opcodes.H_INVOKESTATIC
+                && LAMBDA_METAFACTORY.getInternalName().equals(handle.getOwner())
+                && "metafactory".equals(handle.getName());
+        }
     }
 
     class NestedMethodInvocationHandler extends MethodInvocationHandler {
+        final Pair<Type, Method> methodKey;
         final Type owner;
 
-        NestedMethodInvocationHandler(final MethodVisitor mvr, final Type owner) {
+        NestedMethodInvocationHandler(final MethodVisitor mvr, final Pair<Type,Method> methodKey) {
             super(mvr);
-            this.owner = owner;
+            this.methodKey = methodKey;
+            this.owner = methodKey.getLeft();
+        }
+
+        @Override
+        protected void visitNonImportedMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
+            final Type ownerType = Type.getObjectType(owner);
+            final Method m = new Method(name, desc);
+
+            if (isAccessible(ownerType) && isAccessible(ownerType, m)) {
+                super.visitNonImportedMethodInsn(opcode, owner, name, desc, itf);
+            } else {
+                throw new IllegalStateException(String.format("Blueprint method %s.%s calls inaccessible method %s.%s",
+                    this.owner, methodKey.getRight(), owner, m));
+            }
+        }
+
+        @Override
+        protected void validateLambda(Handle handle) {
+            super.validateLambda(handle);
+            final Type ownerType = Type.getObjectType(handle.getOwner());
+            final Method m = new Method(handle.getName(), handle.getDesc());
+
+            if (!(isAccessible(ownerType) && isAccessible(ownerType, m))) {
+                throw new IllegalStateException(
+                    String.format("Blueprint method %s.%s utilizes inaccessible method reference %s::%s", owner,
+                        methodKey.getRight(), handle.getOwner(), m));
+            }
         }
 
         @Override
@@ -301,6 +353,36 @@ class BlueprintingVisitor extends Privilizer.PrivilizerClassVisitor {
         private Class<?> load(final Type type) throws ClassNotFoundException {
             return privilizer().env.classLoader.loadClass(type.getClassName());
         }
+
+        private boolean isAccessible(Type type) {
+            final TypeInfo typeInfo = typeInfo(type);
+            return isAccessible(type, typeInfo.access);
+        }
+
+        private boolean isAccessible(Type type, Method m) {
+            Type t = type;
+            while (t != null) {
+                final TypeInfo typeInfo = typeInfo(t);
+                final MethodNode methodNode = typeInfo.methods.get(m);
+                if (methodNode == null) {
+                    t = Optional.ofNullable(typeInfo.superName).map(Type::getObjectType).orElse(null);
+                    continue;
+                }
+                return isAccessible(type, methodNode.access);
+            }
+            throw new IllegalStateException(String.format("Cannot find method %s.%s", type, m));
+        }
+
+        private boolean isAccessible(Type type, int access) {
+            if (Modifier.isPublic(access)) {
+                return true;
+            }
+            if (Modifier.isProtected(access) || Modifier.isPrivate(access)) {
+                return false;
+            }
+            return Stream.of(target, type).map(Type::getInternalName).map(n -> StringUtils.substringBeforeLast(n, "/"))
+                    .distinct().count() == 1;
+        }
     }
 
     /**
@@ -424,7 +506,7 @@ class BlueprintingVisitor extends Privilizer.PrivilizerClassVisitor {
             invokeVirtual(fieldType, access);
 
             if (opcode == GETSTATIC) {
-                checkCast(privilizer().wrap(fieldAccess.type));
+                checkCast(Privilizer.wrap(fieldAccess.type));
                 if (fieldAccess.type.getSort() < Type.ARRAY) {
                     unbox(fieldAccess.type);
                 }
diff --git a/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java b/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java
index 5da66bd..50f84f4 100644
--- a/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java
+++ b/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java
@@ -174,28 +174,7 @@ public class Privilizer {
     static final int ASM_VERSION = Opcodes.ASM5;
     static final Type[] EMPTY_TYPE_ARRAY = new Type[0];
 
-    final WeaveEnvironment env;
-    final AccessLevel accessLevel;
-    final Policy policy;
-    final boolean verify;
-
-    /**
-     * Create a new {@link Privilizer}.
-     * @param env to use
-     */
-    public Privilizer(final WeaveEnvironment env) {
-        super();
-        this.env = env;
-        this.policy = Policy.parse(env.config.getProperty(CONFIG_POLICY));
-        this.accessLevel = AccessLevel.parse(env.config.getProperty(CONFIG_ACCESS_LEVEL));
-        verify = BooleanUtils.toBoolean(env.config.getProperty(CONFIG_VERIFY));
-    }
-
-    String generateName(final String simple) {
-        return String.format(GENERATE_NAME, simple);
-    }
-
-    Type wrap(final Type type) {
+    static Type wrap(final Type type) {
         switch (type.getSort()) {
         case Type.BOOLEAN:
             return Type.getType(Boolean.class);
@@ -220,6 +199,27 @@ public class Privilizer {
         }
     }
 
+    final WeaveEnvironment env;
+    final AccessLevel accessLevel;
+    final Policy policy;
+    final boolean verify;
+
+    /**
+     * Create a new {@link Privilizer}.
+     * @param env to use
+     */
+    public Privilizer(final WeaveEnvironment env) {
+        super();
+        this.env = env;
+        this.policy = Policy.parse(env.config.getProperty(CONFIG_POLICY));
+        this.accessLevel = AccessLevel.parse(env.config.getProperty(CONFIG_ACCESS_LEVEL));
+        verify = BooleanUtils.toBoolean(env.config.getProperty(CONFIG_VERIFY));
+    }
+
+    String generateName(final String simple) {
+        return String.format(GENERATE_NAME, simple);
+    }
+
     void blueprint(final Class<?> type, final Privilizing privilizing) {
         final Object[] args = { type.getName(), privilizing };
         env.debug("blueprinting class %s %s", args);

-- 
To stop receiving notification emails like this one, please contact
mbenson@apache.org.