Skip to content

Commit

Permalink
Adapted changed Java 9 APIs for class file transformer and changed re…
Browse files Browse the repository at this point in the history
…ndering of parameterized types.
  • Loading branch information
raphw committed Sep 13, 2016
1 parent 0626ab2 commit 81ffe1e
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 19 deletions.
Expand Up @@ -6580,18 +6580,21 @@ public byte[] transform(ClassLoader classLoader,
* allows to process module information which is available since Java 9.
*
* @param rawModule The instrumented class's Java {@code java.lang.reflect.Module}.
* @param classLoader The type's class loader or {@code null} if the type is loaded by the bootstrap loader.
* @param internalTypeName The internal name of the instrumented class.
* @param classBeingRedefined The loaded {@link Class} being redefined or {@code null} if no such class exists.
* @param protectionDomain The instrumented type's protection domain.
* @param binaryRepresentation The class file of the instrumented class in its current state.
* @return The transformed class file or an empty byte array if this transformer does not apply an instrumentation.
*/
protected byte[] transform(Object rawModule,
ClassLoader classLoader,
String internalTypeName,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] binaryRepresentation) {
return AccessController.doPrivileged(new Java9CapableVmDispatcher(rawModule,
classLoader,
internalTypeName,
classBeingRedefined,
protectionDomain,
Expand Down Expand Up @@ -6910,6 +6913,7 @@ public Factory run() {
.method(named("transform").and(takesArgument(0, JavaType.MODULE.load())))
.intercept(MethodCall.invoke(ExecutingTransformer.class.getDeclaredMethod("transform",
Object.class,
ClassLoader.class,
String.class,
Class.class,
ProtectionDomain.class,
Expand Down Expand Up @@ -7058,6 +7062,11 @@ protected class Java9CapableVmDispatcher implements PrivilegedAction<byte[]> {
*/
private final Object rawModule;

/**
* The type's class loader or {@code null} if the type is loaded by the bootstrap loader.
*/
private final ClassLoader classLoader;

/**
* The type's internal name or {@code null} if no such name exists.
*/
Expand All @@ -7083,17 +7092,20 @@ protected class Java9CapableVmDispatcher implements PrivilegedAction<byte[]> {
* Creates a new legacy dispatcher.
*
* @param rawModule The type's {@code java.lang.reflect.Module}.
* @param classLoader The type's class loader or {@code null} if the type is loaded by the bootstrap loader.
* @param internalTypeName The type's internal name or {@code null} if no such name exists.
* @param classBeingRedefined The class being redefined or {@code null} if no such class exists.
* @param protectionDomain The type's protection domain.
* @param binaryRepresentation The type's binary representation.
*/
protected Java9CapableVmDispatcher(Object rawModule,
ClassLoader classLoader,
String internalTypeName,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] binaryRepresentation) {
this.rawModule = rawModule;
this.classLoader = classLoader;
this.internalTypeName = internalTypeName;
this.classBeingRedefined = classBeingRedefined;
this.protectionDomain = protectionDomain;
Expand All @@ -7102,9 +7114,8 @@ protected Java9CapableVmDispatcher(Object rawModule,

@Override
public byte[] run() {
JavaModule module = JavaModule.of(rawModule);
return transform(module,
module.getClassLoader(),
return transform(JavaModule.of(rawModule),
classLoader,
internalTypeName,
classBeingRedefined,
protectionDomain,
Expand All @@ -7126,6 +7137,7 @@ public boolean equals(Object object) {
if (object == null || getClass() != object.getClass()) return false;
Java9CapableVmDispatcher that = (Java9CapableVmDispatcher) object;
return rawModule.equals(that.rawModule)
&& (classLoader != null ? classLoader.equals(that.classLoader) : that.classLoader == null)
&& (internalTypeName != null ? internalTypeName.equals(that.internalTypeName) : that.internalTypeName == null)
&& (classBeingRedefined != null ? classBeingRedefined.equals(that.classBeingRedefined) : that.classBeingRedefined == null)
&& protectionDomain.equals(that.protectionDomain)
Expand All @@ -7136,6 +7148,7 @@ public boolean equals(Object object) {
@Override
public int hashCode() {
int result = rawModule.hashCode();
result = 31 * result + (classLoader != null ? classLoader.hashCode() : 0);
result = 31 * result + (internalTypeName != null ? internalTypeName.hashCode() : 0);
result = 31 * result + (classBeingRedefined != null ? classBeingRedefined.hashCode() : 0);
result = 31 * result + protectionDomain.hashCode();
Expand All @@ -7149,6 +7162,7 @@ public String toString() {
return "AgentBuilder.Default.ExecutingTransformer.Java9CapableVmDispatcher{" +
"outer=" + ExecutingTransformer.this +
", rawModule=" + rawModule +
", classLoader=" + classLoader +
", internalTypeName='" + internalTypeName + '\'' +
", classBeingRedefined=" + classBeingRedefined +
", protectionDomain=" + protectionDomain +
Expand Down
@@ -1,6 +1,7 @@
package net.bytebuddy.description.type;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.ByteCodeElement;
import net.bytebuddy.description.ModifierReviewable;
import net.bytebuddy.description.TypeVariableSource;
Expand Down Expand Up @@ -5016,17 +5017,13 @@ public String toString() {
StringBuilder stringBuilder = new StringBuilder();
Generic ownerType = getOwnerType();
if (ownerType != null) {
stringBuilder.append(ownerType.getTypeName());
stringBuilder.append(".");
stringBuilder.append(ownerType.getSort().isParameterized()
? asErasure().getName().replace(ownerType.asErasure().getName() + "$", "")
: asErasure().getName());
RenderingDelegate.CURRENT.apply(stringBuilder.append(ownerType.getTypeName()), asErasure(), ownerType);
} else {
stringBuilder.append(asErasure().getName());
}
TypeList.Generic actualTypeArguments = getTypeArguments();
if (!actualTypeArguments.isEmpty()) {
stringBuilder.append("<");
stringBuilder.append('<');
boolean multiple = false;
for (Generic typeArgument : actualTypeArguments) {
if (multiple) {
Expand All @@ -5035,11 +5032,69 @@ public String toString() {
stringBuilder.append(typeArgument.getTypeName());
multiple = true;
}
stringBuilder.append(">");
stringBuilder.append('>');
}
return stringBuilder.toString();
}

/**
* A rendering delegate for resolving a parameterized type's {@link Object#toString()} representation.
*/
protected enum RenderingDelegate {

/**
* A rendering delegate for any VM prior to Java 9 where types are concatenated using a {@code .} character
* and where the fully qualified names are appended to non-parameterized types.
*/
LEGACY_VM {
@Override
protected void apply(StringBuilder stringBuilder, TypeDescription typeDescription, Generic ownerType) {
stringBuilder.append('.');
stringBuilder.append(ownerType.getSort().isParameterized()
? typeDescription.getName().substring(ownerType.asErasure().getName().length() + 1) // TODO: Correct?
: typeDescription.getName());
}
},

/**
* A rendering delegate for any VM supporting Java 9 or newer where a type's simple name is appended.
*/
JAVA_9_CAPABLE_VM {
@Override
protected void apply(StringBuilder stringBuilder, TypeDescription typeDescription, Generic ownerType) {
stringBuilder.append('$').append(typeDescription.getSimpleName());
}
};

/**
* A rendering delegate for the current VM.
*/
protected static final RenderingDelegate CURRENT;

/*
* Resolves the current VM's rendering delegate.
*/
static {
CURRENT = ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V6).isAtLeast(ClassFileVersion.JAVA_V9)
? RenderingDelegate.JAVA_9_CAPABLE_VM
: RenderingDelegate.LEGACY_VM;
}

/**
* Applies this rendering delegate.
*
* @param stringBuilder The string builder which is used for creating a parameterized type's string representation.
* @param typeDescription The rendered type's erasure.
* @param ownerType The rendered type's owner type.
*/
protected abstract void apply(StringBuilder stringBuilder, TypeDescription typeDescription, Generic ownerType);

@Override
public String toString() {
return "TypeDescription.Generic.OfParameterizedType.RenderingDelegate." + name();
}
}

/**
* Description of a loaded parameterized type.
*/
Expand Down
Expand Up @@ -1386,8 +1386,8 @@ private static byte[] transform(ClassFileTransformer classFileTransformer,
ProtectionDomain protectionDomain,
byte[] binaryRepresentation) throws Exception {
try {
return (byte[]) ClassFileTransformer.class.getDeclaredMethod("transform", Class.forName("java.lang.reflect.Module"), String.class, Class.class, ProtectionDomain.class, byte[].class)
.invoke(classFileTransformer, javaModule.unwrap(), typeName, type, protectionDomain, binaryRepresentation);
return (byte[]) ClassFileTransformer.class.getDeclaredMethod("transform", Class.forName("java.lang.reflect.Module"), ClassLoader.class, String.class, Class.class, ProtectionDomain.class, byte[].class)
.invoke(classFileTransformer, javaModule.unwrap(), classLoader, typeName, type, protectionDomain, binaryRepresentation);
} catch (Exception ignored) {
return classFileTransformer.transform(classLoader, typeName, type, protectionDomain, binaryRepresentation);
}
Expand Down
Expand Up @@ -5,7 +5,7 @@
import net.bytebuddy.utility.JavaModule;
import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;

Expand Down
Expand Up @@ -10,8 +10,8 @@
import org.junit.rules.TestRule;
import org.mockito.Mock;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.*;

public class AgentBuilderTransformerForBuildPluginTest {
Expand Down
Expand Up @@ -13,8 +13,8 @@
import org.junit.rules.TestRule;
import org.mockito.Mock;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.*;

public class AgentBuilderTypeStrategyForBuildEntryPointTest {
Expand Down
Expand Up @@ -10,8 +10,8 @@
import java.util.Collection;

import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

@RunWith(Parameterized.class)
public class AdviceSizeConversionTest {
Expand Down
Expand Up @@ -15,7 +15,7 @@

import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

Expand Down
@@ -0,0 +1,71 @@
package net.bytebuddy.description.type;

import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.test.utility.MockitoRule;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.mockito.Mock;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

public class TypeDescriptionGenericOfParameterizedTypeRenderingDelegateTest {

private static final String FOO = "foo", BAR = "bar";

@Rule
public TestRule mockitoRule = new MockitoRule(this);

@Mock
private TypeDescription typeDescription, erasure;

@Mock
private TypeDescription.Generic ownerType;

@Before
public void setUp() throws Exception {
when(typeDescription.getName()).thenReturn(FOO + "." + BAR);
when(typeDescription.getSimpleName()).thenReturn(BAR);
when(ownerType.asErasure()).thenReturn(erasure);
when(erasure.getName()).thenReturn(FOO);
}

@Test
public void testJava9Capable() throws Exception {
StringBuilder stringBuilder = new StringBuilder();
TypeDescription.Generic.OfParameterizedType.RenderingDelegate.JAVA_9_CAPABLE_VM.apply(stringBuilder, typeDescription, ownerType);
assertThat(stringBuilder.toString(), is("$" + BAR));
}

@Test
public void testLegacyParameterized() throws Exception {
when(ownerType.getSort()).thenReturn(TypeDefinition.Sort.PARAMETERIZED);
StringBuilder stringBuilder = new StringBuilder();
TypeDescription.Generic.OfParameterizedType.RenderingDelegate.LEGACY_VM.apply(stringBuilder, typeDescription, ownerType);
assertThat(stringBuilder.toString(), is("." + BAR));
}

@Test
public void testLegacyNonParameterized() throws Exception {
when(ownerType.getSort()).thenReturn(TypeDefinition.Sort.NON_GENERIC);
StringBuilder stringBuilder = new StringBuilder();
TypeDescription.Generic.OfParameterizedType.RenderingDelegate.LEGACY_VM.apply(stringBuilder, typeDescription, ownerType);
assertThat(stringBuilder.toString(), is("." + FOO + "." + BAR));
}

@Test
public void testCurrent() throws Exception {
assertThat(TypeDescription.Generic.OfParameterizedType.RenderingDelegate.CURRENT, is(ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V9)
? TypeDescription.Generic.OfParameterizedType.RenderingDelegate.JAVA_9_CAPABLE_VM
: TypeDescription.Generic.OfParameterizedType.RenderingDelegate.LEGACY_VM));
}

@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(TypeDescription.Generic.OfParameterizedType.RenderingDelegate.class).apply();
}
}
Expand Up @@ -62,7 +62,7 @@ public void testNonLocatable() throws Exception {
public void testReadTypeBootstrapClassLoader() throws Exception {
ClassFileLocator.Resolution resolution = ClassFileLocator.ForClassLoader.read(Object.class);
assertThat(resolution.isResolved(), is(true));
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(Object.class.getName().replace('.', '/') + ".class");
InputStream inputStream = Object.class.getResourceAsStream(Object.class.getSimpleName() + ".class");
try {
assertThat(resolution.resolve(), is(StreamDrainer.DEFAULT.drain(inputStream)));
} finally {
Expand Down
Expand Up @@ -12,8 +12,8 @@
import java.util.HashMap;
import java.util.Map;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.*;

public class ClassFileLocatorPackageDiscriminatingTest {
Expand Down

0 comments on commit 81ffe1e

Please sign in to comment.