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 2013/03/23 19:31:01 UTC
svn commit: r1460203 - in /commons/sandbox/weaver/branches/fields: ./
example/ example/src/main/java/org/apache/commons/weaver/privilizer/example/
example/src/test/java/org/apache/commons/weaver/privilizer/example/
example/src/test/resources/ modules/p...
Author: mbenson
Date: Sat Mar 23 18:31:00 2013
New Revision: 1460203
URL: http://svn.apache.org/r1460203
Log:
brain dump of attempts to handle blueprint methods that reference fields; this yields code with VerifyErrors... HELP\!
Added:
commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingOACL3Blueprints.java
commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingOACL3BlueprintsTest.java
commons/sandbox/weaver/branches/fields/processor/src/main/java/org/apache/commons/weaver/utils/Assistant.java (with props)
Modified:
commons/sandbox/weaver/branches/fields/ (props changed)
commons/sandbox/weaver/branches/fields/example/pom.xml
commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingBlueprints.java
commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/Utils.java
commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingBlueprintsTest.java
commons/sandbox/weaver/branches/fields/example/src/test/resources/java.policy
commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/pom.xml
commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/FilesystemPrivilizer.java
commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java
commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/PrivilizerWeaver.java
commons/sandbox/weaver/branches/fields/pom.xml
commons/sandbox/weaver/branches/fields/processor/pom.xml
Propchange: commons/sandbox/weaver/branches/fields/
------------------------------------------------------------------------------
Merged /commons/sandbox/weaver/trunk:r1460197
Modified: commons/sandbox/weaver/branches/fields/example/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/example/pom.xml?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/example/pom.xml (original)
+++ commons/sandbox/weaver/branches/fields/example/pom.xml Sat Mar 23 18:31:00 2013
@@ -27,12 +27,18 @@
<name>Commons Weaver Privilizer Example</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <privilizer.policy>ON_INIT</privilizer.policy>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
<artifactId>commons-weaver-privilizer-api</artifactId>
<version>${project.version}</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
@@ -49,7 +55,7 @@
<configuration>
<weaverConfig>
<privilizer.accessLevel>PACKAGE</privilizer.accessLevel>
- <privilizer.policy>ON_INIT</privilizer.policy>
+ <privilizer.policy>${privilizer.policy}</privilizer.policy>
</weaverConfig>
</configuration>
<executions>
@@ -104,6 +110,11 @@
</lifecycleMappingMetadata>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ </plugin>
</plugins>
</pluginManagement>
</build>
Modified: commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingBlueprints.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingBlueprints.java?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingBlueprints.java (original)
+++ commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingBlueprints.java Sat Mar 23 18:31:00 2013
@@ -21,6 +21,10 @@ import org.apache.commons.weaver.privili
@Privilizing({ @CallTo(Utils.class), @CallTo(value = Utils.More.class, methods = "getProperty") })
public class UsingBlueprints {
+ public String utilsReadConstant() {
+ return Utils.readConstant();
+ }
+
public String utilsGetProperty() {
return Utils.getProperty();
}
Added: commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingOACL3Blueprints.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingOACL3Blueprints.java?rev=1460203&view=auto
==============================================================================
--- commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingOACL3Blueprints.java (added)
+++ commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/UsingOACL3Blueprints.java Sat Mar 23 18:31:00 2013
@@ -0,0 +1,46 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * 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.apache.commons.weaver.privilizer.example;
+
+import org.apache.commons.lang3.ClassUtils;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+
+@Privilizing(@CallTo(value = ClassUtils.class, methods = "getShortClassName"))
+public class UsingOACL3Blueprints {
+
+ public Class<?> getClass(String className) {
+ try {
+ return ClassUtils.getClass(className);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ public String getShortClassName(String className) {
+ /*
+ * method with field access but does not call other methods:
+ */
+ return ClassUtils.getShortClassName(className);
+ }
+
+ public static void main(String[] args) {
+ final UsingOACL3Blueprints usingOACL3Blueprints = new UsingOACL3Blueprints();
+ for (String arg : args) {
+ System.out.println(usingOACL3Blueprints.getShortClassName(arg));
+ }
+ }
+}
Modified: commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/Utils.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/Utils.java?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/Utils.java (original)
+++ commons/sandbox/weaver/branches/fields/example/src/main/java/org/apache/commons/weaver/privilizer/example/Utils.java Sat Mar 23 18:31:00 2013
@@ -32,6 +32,12 @@ public class Utils {
private Utils() {
}
+ private static final String foo = "foo".intern();
+
+ public static String readConstant() {
+ return foo;
+ }
+
public static String getProperty() {
return getProperty("foo");
}
Modified: commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingBlueprintsTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingBlueprintsTest.java?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingBlueprintsTest.java (original)
+++ commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingBlueprintsTest.java Sat Mar 23 18:31:00 2013
@@ -42,6 +42,11 @@ public class UsingBlueprintsTest {
}
@Test
+ public void testUtilsReadConstant() {
+ assertEquals("foo", usingBlueprints.utilsReadConstant());
+ }
+
+ @Test
public void testUtilsGetProperty() {
assertEquals("foo-value", usingBlueprints.utilsGetProperty());
}
Added: commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingOACL3BlueprintsTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingOACL3BlueprintsTest.java?rev=1460203&view=auto
==============================================================================
--- commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingOACL3BlueprintsTest.java (added)
+++ commons/sandbox/weaver/branches/fields/example/src/test/java/org/apache/commons/weaver/privilizer/example/UsingOACL3BlueprintsTest.java Sat Mar 23 18:31:00 2013
@@ -0,0 +1,36 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * 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.apache.commons.weaver.privilizer.example;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class UsingOACL3BlueprintsTest {
+
+ private UsingOACL3Blueprints usingOACL3Blueprints;
+
+ @Before
+ public void setUp() throws Exception {
+ usingOACL3Blueprints = new UsingOACL3Blueprints();
+ }
+
+// @Test
+ public void testGetClass() {
+ assertEquals(Utils.class, usingOACL3Blueprints.getClass(Utils.class.getName()));
+ }
+}
Modified: commons/sandbox/weaver/branches/fields/example/src/test/resources/java.policy
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/example/src/test/resources/java.policy?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/example/src/test/resources/java.policy (original)
+++ commons/sandbox/weaver/branches/fields/example/src/test/resources/java.policy Sat Mar 23 18:31:00 2013
@@ -42,4 +42,5 @@ grant codeBase "file:${user.dir}/target/
permission java.util.PropertyPermission "foo", "read";
permission java.util.PropertyPermission "bar", "read";
permission java.util.PropertyPermission "baz", "read";
+ #permission java.lang.RuntimePermission "getClassLoader";
};
Modified: commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/pom.xml?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/pom.xml (original)
+++ commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/pom.xml Sat Mar 23 18:31:00 2013
@@ -47,7 +47,6 @@
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
- <version>3.17.1-GA</version>
</dependency>
</dependencies>
Modified: commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/FilesystemPrivilizer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/FilesystemPrivilizer.java?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/FilesystemPrivilizer.java (original)
+++ commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/FilesystemPrivilizer.java Sat Mar 23 18:31:00 2013
@@ -30,7 +30,7 @@ import org.apache.commons.lang3.Validate
/**
* Handles weaving of methods annotated with {@link Privileged}.
*/
-public class FilesystemPrivilizer extends Privilizer<FilesystemPrivilizer> {
+public class FilesystemPrivilizer extends Privilizer {
private static ClassPool createClassPool(ClassLoader classpath, File target) {
final ClassPool result = new ClassPool();
Modified: commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java (original)
+++ commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java Sat Mar 23 18:31:00 2013
@@ -41,35 +41,33 @@ import javassist.CtPrimitiveType;
import javassist.NotFoundException;
import javassist.bytecode.Descriptor;
import javassist.expr.ExprEditor;
+import javassist.expr.FieldAccess;
import javassist.expr.MethodCall;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
+import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.commons.lang3.text.StrBuilder;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+import org.apache.commons.weaver.utils.Assistant;
import org.apache.commons.weaver.utils.Body;
/**
- * Handles weaving of methods annotated with {@link Privileged}.
+ * Handles:
+ * <ul>
+ * <li>weaving of methods annotated with {@link Privileged}</li>
+ * <li>weaving of blueprint annotation methods</li>
+ * </ul>
+ *
+ * @see Privileged
+ * @see Privilizing
*/
-public abstract class Privilizer<SELF extends Privilizer<SELF>> {
+public abstract class Privilizer {
public interface ClassFileWriter {
void write(CtClass type) throws CannotCompileException, IOException;
}
- public interface Log {
- void debug(String message);
-
- void verbose(String message);
-
- void error(String message);
-
- void info(String message);
-
- void warn(String message);
- }
-
/**
* Weaving policy: when to use {@link PrivilegedAction}s.
*/
@@ -162,6 +160,8 @@ public abstract class Privilizer<SELF ex
return result;
}
+ private final Assistant assistant;
+
public Privilizer(ClassPool classPool) {
this(Policy.DYNAMIC, classPool);
}
@@ -169,10 +169,12 @@ public abstract class Privilizer<SELF ex
public Privilizer(Policy policy, ClassPool classPool) {
this.policy = Validate.notNull(policy, "policy");
this.classPool = Validate.notNull(classPool, "classPool");
+ this.assistant = new Assistant(classPool, "__privilizer_");
}
/**
- * Weave all {@link Privileged} methods found.
+ * Weave the specified class. Handles all {@link Privileged} methods as well as calls described by
+ * {@code privilizing}.
*
* @param privilizing
*
@@ -217,7 +219,8 @@ public abstract class Privilizer<SELF ex
}
if (policy == Policy.ON_INIT) {
- debug("Initializing field %s to %s", policy.condition, HAS_SECURITY_MANAGER_CONDITION);
+ debug("Initializing field %s.%s to %s", type.getName(), policy.condition,
+ HAS_SECURITY_MANAGER_CONDITION);
CtField securityManager = new CtField(CtClass.booleanType, policy.condition, type);
securityManager.setModifiers(Modifier.STATIC | Modifier.PRIVATE | Modifier.FINAL);
@@ -256,10 +259,9 @@ public abstract class Privilizer<SELF ex
private boolean privilizeBlueprints(final CtClass type, final CtMethod method, final CallTo[] blueprintCalls)
throws CannotCompileException, ClassNotFoundException, NotFoundException, IOException, IllegalAccessException {
- boolean result = false;
+ final MutableBoolean result = new MutableBoolean();
- final List<CtMethod> blueprints = new ArrayList<CtMethod>();
- class CollectBlueprints extends ExprEditor {
+ method.instrument(new ExprEditor() {
@Override
public void edit(MethodCall call) throws CannotCompileException {
super.edit(call);
@@ -272,37 +274,45 @@ public abstract class Privilizer<SELF ex
} catch (NotFoundException e) {
return;
}
+ boolean found = false;
for (CallTo callTo : blueprintCalls) {
final Class<?> owner = callTo.value();
if (owner.getName().equals(call.getClassName())) {
- if (callTo.methods().length > 0) {
- boolean found = false;
- for (String m : callTo.methods()) {
- found = StringUtils.equals(call.getMethodName(), m);
- if (found) {
- break;
- }
- }
- if (!found) {
- continue;
+ if (callTo.methods().length == 0) {
+ found = true;
+ break;
+ }
+ for (String m : callTo.methods()) {
+ found = StringUtils.equals(call.getMethodName(), m);
+ if (found) {
+ break;
}
}
- blueprints.add(called);
- break;
}
}
- }
- }
- method.instrument(new CollectBlueprints());
-
- for (CtMethod blueprint : blueprints) {
- final String name = importedMethodName(blueprint);
+ if (found) {
+ final String name = importedMethodName(called);
- CtMethod copy = copyBlueprintTo(type, name, blueprint, blueprintCalls);
- method.instrument(redirect(blueprint, copy));
- result = true;
- }
- return result;
+ CtMethod copy;
+ try {
+ copy = copyBlueprintTo(type, name, called, blueprintCalls);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ Body redirect = new Body(Privilizer.this, "call %s", Privilizer.this.toString(called));
+ if (Privilizer.this.policy.isConditional()) {
+ redirect.startBlock("if (%s)", Privilizer.this.policy.condition);
+ }
+ redirect.appendLine("$_ = %s($$);", copy.getName());
+ if (Privilizer.this.policy.isConditional()) {
+ redirect.endBlock().startBlock("else").appendLine("$_ = $proceed($$);").endBlock();
+ }
+ call.replace(redirect.complete().toString());
+ result.setValue(Boolean.TRUE);
+ }
+ }
+ });
+ return result.booleanValue();
}
private static String importedMethodName(CtMethod blueprint) {
@@ -311,7 +321,7 @@ public abstract class Privilizer<SELF ex
}
/*
- * This design is almost certainly non-optimal. Basically, we have:
+ * This design is almost certainly suboptimal. Basically, we have:
*
* for a declared method, look for calls to blueprint methods for each blueprint method, copy it when copying,
* inspect blueprint method's code and recursively copy in methods from the source class of *that particular method*
@@ -323,7 +333,7 @@ public abstract class Privilizer<SELF ex
*/
private CtMethod copyBlueprintTo(final CtClass target, final String toName, final CtMethod method,
final CallTo[] blueprintCalls) throws ClassNotFoundException, NotFoundException, IOException,
- IllegalAccessException {
+ IllegalAccessException, CannotCompileException {
if (!Modifier.isStatic(method.getModifiers())) {
return null;
}
@@ -335,8 +345,9 @@ public abstract class Privilizer<SELF ex
}
final CtClass declaring = method.getDeclaringClass();
+ final List<CtField> referencedFields = new ArrayList<CtField>();
final List<CtMethod> ownBlueprints = new ArrayList<CtMethod>();
- class CollectBlueprints extends ExprEditor {
+ class CollectOwnReferences extends ExprEditor {
@Override
public void edit(MethodCall m) throws CannotCompileException {
super.edit(m);
@@ -350,40 +361,55 @@ public abstract class Privilizer<SELF ex
ownBlueprints.add(called);
}
}
+
+ @Override
+ public void edit(FieldAccess f) throws CannotCompileException {
+ super.edit(f);
+ try {
+ referencedFields.add(f.getField());
+ } catch (NotFoundException e) {
+ }
+ }
}
- try {
- method.instrument(new CollectBlueprints());
+ method.instrument(new CollectOwnReferences());
- boolean isRecursive = false;
+ boolean isRecursive = false;
- for (CtMethod blueprint : ownBlueprints) {
- if (blueprint.equals(method)) {
- // recursive method call identified:
- isRecursive = true;
- continue;
- }
- CtMethod local = copyBlueprintTo(target, importedMethodName(blueprint), blueprint, blueprintCalls);
- if (local != null) {
- method.instrument(redirect(blueprint, local));
- }
- }
- final CtMethod result = CtNewMethod.copy(method, toName, target, null);
- result.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
- target.addMethod(result);
- if (isRecursive) {
- CodeConverter redirect = new CodeConverter();
- redirect.redirectMethodCall(method.getName(), result);
- result.instrument(redirect);
- }
- // privilize other classes' blueprint methods recursively:
- privilizeBlueprints(target, result, blueprintCalls);
- // privilize:
+ for (CtMethod blueprint : ownBlueprints) {
+ if (blueprint.equals(method)) {
+ // recursive method call identified:
+ isRecursive = true;
+ continue;
+ }
+ CtMethod local = copyBlueprintTo(target, importedMethodName(blueprint), blueprint, blueprintCalls);
+ if (local != null) {
+ method.instrument(redirect(blueprint, local));
+ }
+ }
+ final CtMethod result = CtNewMethod.copy(method, toName, target, null);
+ result.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
+ target.addMethod(result);
+
+ if (!referencedFields.isEmpty()) {
+ handleReferencedFields(target, result, method, referencedFields);
+ }
+ if (isRecursive) {
+ CodeConverter redirectRecursive = new CodeConverter();
+ redirectRecursive.redirectMethodCall(method.getName(), result);
+ result.instrument(redirectRecursive);
+ }
+ // privilize other classes' blueprint methods recursively:
+ privilizeBlueprints(target, result, blueprintCalls);
+
+ // not really possible to check for what truly may throw a SecurityException and thus requires privilizing,
+ // but we'll assume any public method must be. As anything else, once copied,
+ // can only be called from something we have already privilized
+ // TODO? only privilize methods the instrumented class called originally, directly
+ if (Modifier.isPublic(method.getModifiers())) {
weave(target, result);
-
- return result;
- } catch (CannotCompileException e) {
- return null;
}
+
+ return result;
}
private static CodeConverter redirect(CtMethod origMethod, CtMethod substMethod) throws CannotCompileException {
@@ -392,6 +418,80 @@ public abstract class Privilizer<SELF ex
return result;
}
+ private void handleReferencedFields(final CtClass target, final CtMethod method, final CtMethod source,
+ List<CtField> referencedFields) throws CannotCompileException, NotFoundException {
+
+ method.instrument(new ExprEditor() {
+ @Override
+ public void edit(FieldAccess f) throws CannotCompileException {
+ super.edit(f);
+ CtField fld;
+ boolean primitive;
+ try {
+ fld = f.getField();
+ primitive = fld.getType().isPrimitive();
+ } catch (NotFoundException e) {
+ // no such field implies a reference copied such that the field doesn't exist, probably the usual
+ // case with blueprinted methods containing field refs
+
+ fld = null;
+ primitive = false;
+ CtClass host = source.getDeclaringClass();
+ while (host != null) {
+ try {
+ fld = host.getDeclaredField(f.getFieldName());
+ primitive = fld.getType().isPrimitive();
+ break;
+ } catch (NotFoundException e1) {
+ }
+ try {
+ host = host.getSuperclass();
+ } catch (NotFoundException e1) {
+ break;
+ }
+ }
+ if (fld == null) {
+ throw new RuntimeException(e);
+ }
+ }
+ if (Modifier.isPublic(fld.getModifiers()) || !Modifier.isStatic(fld.getModifiers())) {
+ return;
+ }
+
+ final String replacement;
+ if (f.isReader()) {
+ replacement =
+ String.format("$_ = ($%s) %s(%s.class, \"%s\", null);", primitive ? "w" : "r", assistant
+ .fieldReader(target).getName(), fld.getDeclaringClass().getName(), f.getFieldName());
+ } else {
+ replacement =
+ String.format("%s(%s.class, \"%s\", null, %s);", assistant.fieldWriter(target).getName(), fld
+ .getDeclaringClass().getName(), f.getFieldName(), primitive ? "($w) $1" : "$1");
+ }
+ debug("Replacing %s access of %s.%s", f.isReader() ? "read" : "write", fld.getDeclaringClass()
+ .getName(), f.getFieldName());
+ debug(replacement);
+ f.replace(replacement);
+ }
+ });
+
+ boolean allPublic = true;
+ for (CtField ctField : referencedFields) {
+ Validate.validState(!ctField.getDeclaringClass().equals(target),
+ "Circular reference; cannot blueprint method %s", toString(source));
+ if (!Modifier.isPublic(ctField.getModifiers())) {
+ allPublic = false;
+ break;
+ }
+ }
+ if (!allPublic) {
+ method.insertBefore(assistant.callPushFieldAccess(target, referencedFields));
+ final boolean asFinally = true;
+ method.insertAfter(new StringBuilder(assistant.popFieldAccess(target).getName()).append("();").toString(),
+ asFinally);
+ }
+ }
+
protected void debug(String message, Object... args) {
log.fine(String.format(message, args));
}
@@ -463,12 +563,7 @@ public abstract class Privilizer<SELF ex
sig.append(fld.getType().getName()).append(' ').append(fld.getName());
body.appendLine("this.%1$s = %1$s;", fld.getName());
}
- sig.append(") ").append(body.complete());
-
- final String c = sig.toString();
- debug("Creating action constructor:");
- debug(c);
- result.addConstructor(CtNewConstructor.make(c, result));
+ result.addConstructor(CtNewConstructor.make(sig.append(") ").append(body.complete()).toString(), result));
}
{
final StrBuilder run = new StrBuilder("public Object run() ");
@@ -495,12 +590,7 @@ public abstract class Privilizer<SELF ex
}
}
- run.append(body.complete());
-
- final String r = run.toString();
- debug("Creating run method:");
- debug(r);
- result.addMethod(CtNewMethod.make(r, result));
+ result.addMethod(CtNewMethod.make(run.append(body.complete()).toString(), result));
}
getClassFileWriter().write(result);
debug("Returning action type %s", result);
@@ -542,6 +632,7 @@ public abstract class Privilizer<SELF ex
AccessLevel.PRIVATE, toString(impl));
final Body body = new Body(this, "new body of %s", toString(method));
+
if (policy.isConditional()) {
body.startBlock("if (%s)", policy.condition);
}
@@ -625,9 +716,7 @@ public abstract class Privilizer<SELF ex
body.appendLine("%s($$);", impl.getName());
}
- final String block = body.complete().toString();
- debug("Setting body of %s to:\n%s", toString(method), block);
- method.setBody(block);
+ method.setBody(body.complete().toString());
return true;
}
Modified: commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/PrivilizerWeaver.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/PrivilizerWeaver.java?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/PrivilizerWeaver.java (original)
+++ commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/PrivilizerWeaver.java Sat Mar 23 18:31:00 2013
@@ -23,10 +23,8 @@ public class PrivilizerWeaver implements
public static final String CONFIG_ACCESS_LEVEL = CONFIG_WEAVER + "accessLevel";
public static final String CONFIG_POLICY = CONFIG_WEAVER + "policy";
- private Privilizer<FilesystemPrivilizer> privilizer;
-
+ private Privilizer privilizer;
private Privilizer.Policy policy;
-
private AccessLevel targetAccessLevel;
@Override
Modified: commons/sandbox/weaver/branches/fields/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/pom.xml?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/pom.xml (original)
+++ commons/sandbox/weaver/branches/fields/pom.xml Sat Mar 23 18:31:00 2013
@@ -25,7 +25,6 @@
<version>10-SNAPSHOT</version>
</parent>
- <groupId>org.apache.commons</groupId>
<artifactId>commons-weaver</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>pom</packaging>
@@ -95,6 +94,11 @@
<version>3.1</version>
</dependency>
<dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>3.17.1-GA</version>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
Modified: commons/sandbox/weaver/branches/fields/processor/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/processor/pom.xml?rev=1460203&r1=1460202&r2=1460203&view=diff
==============================================================================
--- commons/sandbox/weaver/branches/fields/processor/pom.xml (original)
+++ commons/sandbox/weaver/branches/fields/processor/pom.xml Sat Mar 23 18:31:00 2013
@@ -43,6 +43,11 @@ under the License.
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
Added: commons/sandbox/weaver/branches/fields/processor/src/main/java/org/apache/commons/weaver/utils/Assistant.java
URL: http://svn.apache.org/viewvc/commons/sandbox/weaver/branches/fields/processor/src/main/java/org/apache/commons/weaver/utils/Assistant.java?rev=1460203&view=auto
==============================================================================
--- commons/sandbox/weaver/branches/fields/processor/src/main/java/org/apache/commons/weaver/utils/Assistant.java (added)
+++ commons/sandbox/weaver/branches/fields/processor/src/main/java/org/apache/commons/weaver/utils/Assistant.java Sat Mar 23 18:31:00 2013
@@ -0,0 +1,291 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * 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.apache.commons.weaver.utils;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.CtNewMethod;
+import javassist.NotFoundException;
+
+import org.apache.commons.lang3.Validate;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.weaver.spi.Weaver;
+
+/**
+ * Helper for Javassist-based {@link Weaver} implementations.
+ */
+public class Assistant {
+
+ /**
+ * Default prefix.
+ */
+ public static final String DEFAULT_PREFIX = "_weaver_assisted_";
+
+ private class LazyExceptionsBody extends Body {
+
+ private LazyExceptionsBody(String message, Object... args) {
+ super(prefix, message, args);
+ startBlock("try");
+ }
+
+ @Override
+ public Body complete() {
+ final String e = generateName("lazyException");
+ endBlock()
+ .startBlock("catch (Exception %s)", e)
+ .appendLine(
+ "throw %1$s instanceof RuntimeException ? (RuntimeException) %1$s : new RuntimeException(%1$s);", e)
+ .endBlock();
+ return super.complete();
+ }
+ }
+
+ private final ClassPool classPool;
+ private final String prefix;
+
+ /**
+ * Create a new {@link Assistant} with the specified {@link ClassPool} and {@code DEFAULT_PREFIX}.
+ *
+ * @param classPool
+ */
+ public Assistant(ClassPool classPool) {
+ this(classPool, DEFAULT_PREFIX);
+ }
+
+ /**
+ * Create a new {@link Assistant}.
+ *
+ * @param classPool
+ * used
+ * @param prefix
+ * used for generated elements.
+ */
+ public Assistant(ClassPool classPool, String prefix) {
+ super();
+ this.classPool = classPool;
+ this.prefix = prefix;
+ }
+
+ /**
+ * Generate a name.
+ *
+ * @param name
+ * @return String
+ */
+ public String generateName(String name) {
+ return new StringBuilder(prefix).append(name).toString();
+ }
+
+ /**
+ * Generate a private method to read fields.
+ *
+ * @param target
+ * @return CtMethod
+ */
+ public CtMethod fieldReader(CtClass target) {
+ final String name = generateName("readField");
+
+ final CtClass[] params = types(Class.class, String.class, Object.class);
+ try {
+ return target.getDeclaredMethod(name, params);
+ } catch (NotFoundException e) {
+ }
+ try {
+ final CtMethod result =
+ CtNewMethod.make(
+ new StringBuilder("private static Object ")
+ .append(name)
+ .append("(Class type, String name, Object instance)")
+ .append(
+ new LazyExceptionsBody("fieldReader").appendLine(
+ "return type.getDeclaredField(name).get(instance);").complete()).toString(), target);
+
+ target.addMethod(result);
+ return result;
+ } catch (CannotCompileException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Generate a private method to write fields.
+ *
+ * @param target
+ * @return CtMethod
+ */
+ public CtMethod fieldWriter(CtClass target) {
+ final String name = generateName("writeField");
+
+ final CtClass[] params = types(Class.class, String.class, Object.class, Object.class);
+ try {
+ return target.getDeclaredMethod(name, params);
+ } catch (NotFoundException e) {
+ }
+ try {
+ final CtMethod result =
+ CtNewMethod.make(
+ new StringBuilder("private static void ")
+ .append(name)
+ .append("(Class type, String name, Object instance, Object value)")
+ .append(
+ new LazyExceptionsBody("fieldWriter").appendLine(
+ "type.getDeclaredField(name).set(instance, value);").complete()).toString(), target);
+ target.addMethod(result);
+ return result;
+ } catch (CannotCompileException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String callPushFieldAccess(CtClass target, Iterable<CtField> fields) {
+ final Body setAccessible = new LazyExceptionsBody("pushFieldAccess");
+
+ final String flds = generateName("flds");
+
+ setAccessible.appendLine("final java.util.List %s = new java.util.ArrayList();", flds);
+
+ final String fld = generateName("fld");
+
+ if (fields != null) {
+ setAccessible.appendLine("java.lang.reflect.Field %s;", fld);
+ final Set<Pair<String, String>> uniqueFields = new HashSet<Pair<String, String>>();
+ for (CtField field : fields) {
+ if (Modifier.isPublic(field.getModifiers())) {
+ continue;
+ }
+ final Pair<String, String> pair = Pair.of(field.getDeclaringClass().getName(), field.getName());
+ if (uniqueFields.add(pair)) {
+ setAccessible.appendLine("%s = %s.class.getDeclaredField(\"%s\");", fld, pair.getLeft(),
+ pair.getRight());
+ setAccessible.startBlock("if (!%s.isAccessible())", fld).appendLine("%s.add(%s);", flds, fld)
+ .endBlock();
+ }
+ }
+ }
+
+ final String fieldArray = generateName("fieldArray");
+ setAccessible
+ .appendLine(
+ "final java.lang.reflect.Field[] %1$s = %2$s.toArray(new java.lang.reflect.Field[%2$s.size()]);",
+ fieldArray, flds).appendLine("%s(%s);", pushFieldAccess(target).getName(), fieldArray).complete();
+
+ return setAccessible.toString();
+ }
+
+ public CtMethod pushFieldAccess(CtClass target) {
+ final String name = generateName("pushFieldAccess");
+
+ final CtClass[] params = types(new Field[0].getClass());
+ try {
+ return target.getDeclaredMethod(name, params);
+ } catch (NotFoundException e) {
+ }
+
+ final String stk = generateName("stk");
+ final String fieldAccessStack = getFieldAccessStack(target).getName();
+
+ Body body =
+ new Body(prefix, "pushFieldAccess").appendLine(
+ "java.lang.reflect.AccessibleObject.setAccessible(fields, true);").appendLine(
+ "java.util.Stack %s = (java.util.Stack) %s.get();", stk, fieldAccessStack);
+
+ body.startBlock("if (%s == null)", stk).appendLine("%s = new java.util.Stack();", stk)
+ .appendLine("%s.set(%s);", fieldAccessStack, stk).endBlock();
+
+ body.appendLine("%s.push(fields);", stk).complete();
+
+ try {
+ final CtMethod result =
+ CtNewMethod.make(
+ new StringBuilder("private static void ").append(name).append("(java.lang.reflect.Field[] fields)")
+ .append(body).toString(), target);
+ target.addMethod(result);
+ return result;
+ } catch (CannotCompileException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public CtMethod popFieldAccess(CtClass target) {
+ final String name = generateName("popFieldAccess");
+
+ final CtClass[] params = new CtClass[0];
+ try {
+ return target.getDeclaredMethod(name, params);
+ } catch (NotFoundException e) {
+ }
+
+ final String stk = generateName("stk");
+ final String fieldAccessStack = getFieldAccessStack(target).getName();
+ final String fieldArray = generateName("fieldArray");
+
+ final Body body = new Body(prefix, "popFieldAccess");
+ body.appendLine("java.util.Stack %s = (java.util.Stack) %s.get();", stk, fieldAccessStack)
+ .appendLine("java.lang.reflect.Field[] %s = (java.lang.reflect.Field[]) %s.pop();", fieldArray, stk)
+ .appendLine("java.lang.reflect.AccessibleObject.setAccessible(%s, false);", fieldArray);
+ body.startBlock("if (%s.isEmpty())", stk).appendLine("%s.remove();", fieldAccessStack).endBlock().complete();
+
+ try {
+ final CtMethod result =
+ CtNewMethod.make(new StringBuilder("private static void ").append(name).append("()").append(body)
+ .toString(), target);
+ target.addMethod(result);
+ return result;
+ } catch (CannotCompileException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private CtField getFieldAccessStack(CtClass target) {
+ final String fieldAccessStackName = generateName("fieldAccessStack");
+
+ try {
+ return target.getField(fieldAccessStackName);
+ } catch (Exception e) {
+ final CtField result;
+ try {
+ result = new CtField(classPool.get(ThreadLocal.class.getName()), fieldAccessStackName, target);
+ result.setModifiers(Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL);
+ target.addField(result, "new ThreadLocal()");
+ } catch (Exception e1) {
+ throw new RuntimeException(e1);
+ }
+ return result;
+ }
+ }
+
+ private CtClass[] types(Class<?>... types) {
+ final CtClass[] result = new CtClass[Validate.noNullElements(types).length];
+ int index = 0;
+ for (Class<?> type : types) {
+ try {
+ result[index++] = classPool.get(type.getName());
+ } catch (NotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return result;
+ }
+
+}
Propchange: commons/sandbox/weaver/branches/fields/processor/src/main/java/org/apache/commons/weaver/utils/Assistant.java
------------------------------------------------------------------------------
svn:executable = *