Author: mbenson
Date: Sun Mar 31 08:10:09 2013
New Revision: 1462892
URL: http://svn.apache.org/r1462892
Log:
split out accessibility setup to reduce the amount of code that gets inspected
for recursive blueprinting
Modified:
commons/sandbox/weaver/branches/fields/modules/privilizer/weaver/src/main/java/org/apache/commons/weaver/privilizer/Privilizer.java
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=1462892&r1=1462891&r2=1462892&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
Sun Mar 31 08:10:09 2013
@@ -184,7 +184,7 @@ public abstract class Privilizer {
* @throws ClassNotFoundException
*/
public boolean weaveClass(Class<?> clazz, Privilizing privilizing) throws
NotFoundException, IOException,
- CannotCompileException, ClassNotFoundException, IllegalAccessException
{
+ CannotCompileException, ClassNotFoundException,
IllegalAccessException {
return weave(classPool.get(clazz.getName()), privilizing);
}
@@ -200,7 +200,7 @@ public abstract class Privilizer {
* @throws ClassNotFoundException
*/
private boolean weave(CtClass type, Privilizing privilizing) throws
NotFoundException, IOException,
- CannotCompileException, ClassNotFoundException, IllegalAccessException
{
+ CannotCompileException, ClassNotFoundException,
IllegalAccessException {
reportSettings();
final String policyName = generateName(POLICY_NAME);
final String policyValue = toString(type.getAttribute(policyName));
@@ -220,7 +220,7 @@ public abstract class Privilizer {
if (policy == Policy.ON_INIT) {
debug("Initializing field %s.%s to %s", type.getName(),
policy.condition,
- HAS_SECURITY_MANAGER_CONDITION);
+ HAS_SECURITY_MANAGER_CONDITION);
CtField securityManager = new CtField(CtClass.booleanType,
policy.condition, type);
securityManager.setModifiers(Modifier.STATIC |
Modifier.PRIVATE | Modifier.FINAL);
@@ -242,13 +242,13 @@ public abstract class Privilizer {
}
private boolean privilizeBlueprints(CtClass type, Privilizing annotation)
throws CannotCompileException,
- ClassNotFoundException, NotFoundException, IOException,
IllegalAccessException {
+ ClassNotFoundException, NotFoundException, IOException,
IllegalAccessException {
boolean result = false;
if (annotation != null) {
final CallTo[] blueprintCalls = annotation.value();
for (CallTo callTo : blueprintCalls) {
Validate.isTrue(!callTo.value().equals(type.getName()),
- "Type %s cannot use itself as a privilizer blueprint",
callTo.value());
+ "Type %s cannot use itself as a privilizer blueprint",
callTo.value());
}
for (CtMethod method : type.getDeclaredMethods()) {
result = privilizeBlueprints(type, method, blueprintCalls) |
result;
@@ -258,7 +258,8 @@ public abstract class Privilizer {
}
private boolean privilizeBlueprints(final CtClass type, final CtMethod
method, final CallTo[] blueprintCalls)
- throws CannotCompileException, ClassNotFoundException,
NotFoundException, IOException, IllegalAccessException {
+ throws CannotCompileException, ClassNotFoundException,
NotFoundException, IOException,
+ IllegalAccessException {
final MutableBoolean result = new MutableBoolean();
method.instrument(new ExprEditor() {
@@ -271,7 +272,8 @@ public abstract class Privilizer {
if (!Modifier.isStatic(called.getModifiers())) {
return;
}
- } catch (NotFoundException e) {
+ }
+ catch (NotFoundException e) {
return;
}
boolean found = false;
@@ -296,7 +298,8 @@ public abstract class Privilizer {
CtMethod copy;
try {
copy = copyBlueprintTo(type, name, called,
blueprintCalls);
- } catch (Exception e) {
+ }
+ catch (Exception e) {
throw new RuntimeException(e);
}
Body redirect = new Body(Privilizer.this, "call %s",
Privilizer.this.toString(called));
@@ -317,7 +320,7 @@ public abstract class Privilizer {
private static String importedMethodName(CtMethod blueprint) {
return new
StringBuilder(blueprint.getDeclaringClass().getName().replace('.',
'_')).append('$')
- .append(blueprint.getName()).toString();
+ .append(blueprint.getName()).toString();
}
/*
@@ -332,8 +335,8 @@ public abstract class Privilizer {
* my head around it right now. -MJB
*/
private CtMethod copyBlueprintTo(final CtClass target, final String
toName, final CtMethod method,
- final CallTo[] blueprintCalls) throws ClassNotFoundException,
NotFoundException, IOException,
- IllegalAccessException, CannotCompileException {
+ final CallTo[] blueprintCalls) throws ClassNotFoundException,
NotFoundException, IOException,
+ IllegalAccessException, CannotCompileException {
if (!Modifier.isStatic(method.getModifiers())) {
return null;
}
@@ -341,7 +344,8 @@ public abstract class Privilizer {
try {
final CtMethod done = target.getDeclaredMethod(toName,
method.getParameterTypes());
return done;
- } catch (NotFoundException e1) {
+ }
+ catch (NotFoundException e1) {
}
final CtClass declaring = method.getDeclaringClass();
@@ -354,7 +358,8 @@ public abstract class Privilizer {
CtMethod called;
try {
called = m.getMethod();
- } catch (NotFoundException e) {
+ }
+ catch (NotFoundException e) {
return;
}
if (called.getDeclaringClass().equals(declaring)) {
@@ -367,7 +372,8 @@ public abstract class Privilizer {
super.edit(f);
try {
referencedFields.add(f.getField());
- } catch (NotFoundException e) {
+ }
+ catch (NotFoundException e) {
}
}
}
@@ -401,6 +407,11 @@ public abstract class Privilizer {
// privilize other classes' blueprint methods recursively:
privilizeBlueprints(target, result, blueprintCalls);
+ if (!referencedFields.isEmpty()) {
+ // more referenced fields handling, but reduces the amount of
generated code we read through
+ // when blueprinting recursively
+ makeAccessible(target, result, referencedFields);
+ }
// 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
@@ -419,7 +430,12 @@ public abstract class Privilizer {
}
private void handleReferencedFields(final CtClass target, final CtMethod
method, final CtMethod source,
- List<CtField> referencedFields) throws CannotCompileException,
NotFoundException {
+ final List<CtField> referencedFields) throws
CannotCompileException, NotFoundException {
+
+ for (CtField ctField : referencedFields) {
+ Validate.validState(!ctField.getDeclaringClass().equals(target),
+ "Circular reference; cannot blueprint method %s",
toString(source));
+ }
method.instrument(new ExprEditor() {
@Override
@@ -430,7 +446,8 @@ public abstract class Privilizer {
try {
fld = f.getField();
primitive = fld.getType().isPrimitive();
- } catch (NotFoundException e) {
+ }
+ 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
@@ -442,11 +459,13 @@ public abstract class Privilizer {
fld = host.getDeclaredField(f.getFieldName());
primitive = fld.getType().isPrimitive();
break;
- } catch (NotFoundException e1) {
+ }
+ catch (NotFoundException e1) {
}
try {
host = host.getSuperclass();
- } catch (NotFoundException e1) {
+ }
+ catch (NotFoundException e1) {
break;
}
}
@@ -460,36 +479,40 @@ public abstract class Privilizer {
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");
+ 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());
+ .getName(), f.getFieldName());
debug(replacement);
f.replace(replacement);
}
});
+ }
+ private void makeAccessible(final CtClass target, final CtMethod method,
final List<CtField> referencedFields)
+ throws CannotCompileException {
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(),
+ if (allPublic) {
+ // no need to fiddle with access
+ return;
+ }
+ 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) {
@@ -519,7 +542,7 @@ public abstract class Privilizer {
}
private CtClass createAction(CtClass type, CtMethod impl, Class<?> iface)
throws NotFoundException,
- CannotCompileException, IOException {
+ CannotCompileException, IOException {
final boolean exc = impl.getExceptionTypes().length > 0;
final CtClass actionType = classPool.get(iface.getName());
@@ -532,7 +555,8 @@ public abstract class Privilizer {
final CtField owner;
if (Modifier.isStatic(impl.getModifiers())) {
owner = null;
- } else {
+ }
+ else {
owner = new CtField(type, generateName("owner"), result);
owner.setModifiers(Modifier.PRIVATE | Modifier.FINAL);
debug("Adding owner field %s to %s", owner.getName(), simpleName);
@@ -557,7 +581,8 @@ public abstract class Privilizer {
for (final CtField fld : result.getDeclaredFields()) {
if (sep) {
sig.append(", ");
- } else {
+ }
+ else {
sep = true;
}
sig.append(fld.getType().getName()).append('
').append(fld.getName());
@@ -577,12 +602,13 @@ public abstract class Privilizer {
body.append("return ");
}
final String deref = Modifier.isStatic(impl.getModifiers()) ?
type.getName() : owner.getName();
- final String call =
- String.format("%s.%s(%s)", deref, impl.getName(),
StringUtils.join(propagatedParameters, ", "));
+ final String call = String.format("%s.%s(%s)", deref,
impl.getName(),
+ StringUtils.join(propagatedParameters, ", "));
if (!isVoid && rt.isPrimitive()) {
body.appendLine("%2$s.valueOf(%1$s);", call,
((CtPrimitiveType) rt).getWrapperName());
- } else {
+ }
+ else {
body.append(call).append(';').appendNewLine();
if (isVoid) {
@@ -601,8 +627,8 @@ public abstract class Privilizer {
final StringBuilder b = new StringBuilder(m.getName());
if (m.getParameterTypes().length > 0) {
b.append("$$").append(
-
StringUtils.strip(Descriptor.getParamDescriptor(m.getSignature()),
"(;)").replace("[", "ARRAYOF_")
- .replace('/', '_').replace(';', '$'));
+
StringUtils.strip(Descriptor.getParamDescriptor(m.getSignature()),
"(;)").replace("[", "ARRAYOF_")
+ .replace('/', '_').replace(';', '$'));
}
return b.append(ACTION_SUFFIX).toString();
}
@@ -612,16 +638,16 @@ public abstract class Privilizer {
}
private boolean weave(CtClass type, CtMethod method) throws
ClassNotFoundException, CannotCompileException,
- NotFoundException, IOException, IllegalAccessException {
+ NotFoundException, IOException, IllegalAccessException {
final AccessLevel accessLevel = AccessLevel.of(method.getModifiers());
if (!permitMethodWeaving(accessLevel)) {
throw new IllegalAccessException("Method " + type.getName() + "#"
+ toString(method)
- + " must have maximum access level '" + getTargetAccessLevel()
+ "' but is defined wider ('"
- + accessLevel + "')");
+ + " must have maximum access level '" +
getTargetAccessLevel() + "' but is defined wider ('"
+ + accessLevel + "')");
}
if (AccessLevel.PACKAGE.compareTo(accessLevel) > 0) {
warn("Possible security leak: granting privileges to %s method
%s.%s", accessLevel, type.getName(),
- toString(method));
+ toString(method));
}
final String implName = generateName(method.getName());
@@ -629,7 +655,7 @@ public abstract class Privilizer {
impl.setModifiers(AccessLevel.PRIVATE.merge(method.getModifiers()));
type.addMethod(impl);
debug("Copied %2$s %1$s.%3$s to %4$s %1$s.%5$s", type.getName(),
accessLevel, toString(method),
- AccessLevel.PRIVATE, toString(impl));
+ AccessLevel.PRIVATE, toString(impl));
final Body body = new Body(this, "new body of %s", toString(method));
@@ -651,14 +677,16 @@ public abstract class Privilizer {
boolean firstParam;
if (Modifier.isStatic(impl.getModifiers())) {
firstParam = true;
- } else {
+ }
+ else {
body.append("$0");
firstParam = false;
}
for (int i = 1, sz = impl.getParameterTypes().length; i <= sz; i++) {
if (firstParam) {
firstParam = false;
- } else {
+ }
+ else {
body.append(", ");
}
body.append('$').append(Integer.toString(i));
@@ -674,7 +702,8 @@ public abstract class Privilizer {
if (policy.isConditional()) {
body.appendLine("return;");
}
- } else {
+ }
+ else {
final String cast = rt.isPrimitive() ? ((CtPrimitiveType)
rt).getWrapperName() : rt.getName();
// don't worry about wrapper NPEs because we should be simply
// passing back an autoboxed value, then unboxing again
@@ -701,8 +730,8 @@ public abstract class Privilizer {
body.endBlock();
}
body.appendLine(
- "throw %1$s instanceof RuntimeException ? (RuntimeException)
%1$s : new RuntimeException(%1$s);",
- wrapped);
+ "throw %1$s instanceof RuntimeException ?
(RuntimeException) %1$s : new RuntimeException(%1$s);",
+ wrapped);
body.endBlock();
}