use of com.newrelic.agent.instrumentation.context.InstrumentationContext in project newrelic-java-agent by newrelic.
the class InstrumentingClassLoader method transform.
@Override
protected byte[] transform(String className) throws Exception {
byte[] classBytes = WeaveUtils.getClassBytesFromClassLoaderResource(className, this);
if (classBytes == null) {
return null;
}
final InstrumentationContext context = new InstrumentationContext(classBytes, null, null);
new ClassReader(classBytes).accept(new ScalaTraitMatcher().newClassMatchVisitor(null, null, null, null, context), ClassReader.SKIP_FRAMES);
// weave
byte[] weaved = weave(className, classBytes, context.getSkipMethods(), new ClassWeavedListener() {
@Override
public void classWeaved(PackageWeaveResult weaveResult, ClassLoader classloader, ClassCache cache) {
if (weaveResult.weavedClass()) {
final String packageName = weaveResult.getValidationResult().getWeavePackage().getName();
for (String originalName : weaveResult.getWeavedMethods().keySet()) {
for (Method method : weaveResult.getWeavedMethods().get(originalName)) {
context.addWeavedMethod(method, packageName);
}
ClassWeaverService.addTraceInformation(InstrumentingClassLoader.this.tracedWeaveInstrumentationDetails, packageName, context, weaveResult.getComposite(), originalName);
}
try {
Map<String, byte[]> annotationProxyClasses = weaveResult.getAnnotationProxyClasses();
if (!annotationProxyClasses.isEmpty()) {
// Special case for annotation weaving in order to support dynamic annotation proxies. We
// need to add the dynamic proxy classes that we created to the current classloader here
NewClassAppender.appendClasses(classloader, annotationProxyClasses);
}
} catch (Exception e) {
Agent.LOG.log(Level.FINE, e, "Unable to add annotation proxy classes");
}
}
}
});
// trace
if (weaved != null) {
classBytes = weaved;
}
ClassReader reader = new ClassReader(classBytes);
if (weaved == null) {
// process trace annotations for non-weaved code
reader.accept(new SimpleTraceMatchVisitor(null, context), ClassReader.EXPAND_FRAMES);
}
if (!context.isTracerMatch()) {
if (weaved != null) {
// printClass(className, weaved);
return weaved;
}
return null;
}
NoticeSqlVisitor noticeSqlVisitor = new NoticeSqlVisitor(WeaveUtils.ASM_API_LEVEL);
// find the noticeSql calls
reader.accept(noticeSqlVisitor, ClassReader.SKIP_FRAMES);
String internalClassName = className.replace('.', '/');
ClassWriter writer = new PatchedClassWriter(ClassWriter.COMPUTE_FRAMES, context.getClassResolver(this));
ClassVisitor cv = writer;
cv = new TraceClassVisitor(cv, internalClassName, context, noticeSqlVisitor.getNoticeSqlMethods());
cv = new ClassVisitor(WeaveUtils.ASM_API_LEVEL, cv) {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
if (version < 49 || version > 100) {
// Some weird Apache classes have really large versions.
version = WeaveUtils.RUNTIME_MAX_SUPPORTED_CLASS_VERSION;
}
super.visit(version, access, name, signature, superName, interfaces);
}
};
reader.accept(cv, ClassReader.EXPAND_FRAMES);
byte[] result = writer.toByteArray();
return result;
}
use of com.newrelic.agent.instrumentation.context.InstrumentationContext in project newrelic-java-agent by newrelic.
the class AgentPostprocessors method postprocess.
@Override
public ClassVisitor postprocess(String className, ClassVisitor cv, Set<String> utilityClassesInternalNames, WeavePackage weavePackage, boolean isUtilityClass) {
cv = wrapApiCallsForSupportability(cv);
if (isUtilityClass) {
InstrumentationContext context = new InstrumentationContext(null, null, null);
Set<TracedWeaveInstrumentationTracker> tracedWeaveInstrumentationTrackers = tracedWeaveInstrumentationDetails.get(weavePackage.getName());
if (tracedWeaveInstrumentationTrackers != null) {
for (TracedWeaveInstrumentationTracker tracedWeaveInstrumentationTracker : tracedWeaveInstrumentationTrackers) {
tracedWeaveInstrumentationTracker.addToInstrumentationContext(context, tracedWeaveInstrumentationTracker.getMethod());
}
}
cv = new TraceClassVisitor(cv, className, context, Collections.<Method>emptySet());
}
return cv;
}
use of com.newrelic.agent.instrumentation.context.InstrumentationContext in project newrelic-java-agent by newrelic.
the class ApiImplementationUpdateTest method testMatcherMissingMethods.
@Test
public void testMatcherMissingMethods() throws Exception {
ArgumentCaptor<ClassMatchVisitorFactory> arg = ArgumentCaptor.forClass(ClassMatchVisitorFactory.class);
InstrumentationContext iInstrumentationContext = Mockito.mock(InstrumentationContext.class);
// remove required methods from Request implementation class
Class<?> clazz = RequestImpl.class;
Set<Method> methodsToRemove = new HashSet<>();
methodsToRemove.add(new Method("getHeaderType", "()Lcom/newrelic/api/agent/HeaderType;"));
byte[] classBytes = removeMethods(clazz, methodsToRemove);
// verify missing methods
RequireMethodsAdapter adapter = getRequireMethodsAdapter(clazz, Request.class, REQUEST_METHODS);
expectMissingMethods(adapter, classBytes);
ApiImplementationUpdate transformer = new ApiImplementationUpdate();
ClassMatchVisitorFactory matcher = transformer.getMatcher();
ClassReader reader = new ClassReader(new ByteArrayInputStream(classBytes));
ClassVisitor visitor = matcher.newClassMatchVisitor(clazz.getClassLoader(), null, reader, null, iInstrumentationContext);
reader.accept(visitor, ClassReader.SKIP_CODE);
Mockito.verify(iInstrumentationContext, Mockito.only()).putMatch(arg.capture(), Mockito.<Match>anyObject());
Assert.assertSame(matcher, arg.getValue());
}
use of com.newrelic.agent.instrumentation.context.InstrumentationContext in project newrelic-java-agent by newrelic.
the class ApiImplementationUpdateTest method testMatcher.
@Test
public void testMatcher() throws Exception {
InstrumentationContext iInstrumentationContext = Mockito.mock(InstrumentationContext.class);
Class<?> clazz = RequestImpl.class;
Set<Method> methodsToRemove = new HashSet<>();
byte[] classBytes = removeMethods(clazz, methodsToRemove);
// verify no missing methods
RequireMethodsAdapter adapter = getRequireMethodsAdapter(clazz, Request.class, REQUEST_METHODS);
expectNoMissingMethods(adapter, classBytes);
ApiImplementationUpdate transformer = new ApiImplementationUpdate();
ClassMatchVisitorFactory matcher = transformer.getMatcher();
ClassReader reader = new ClassReader(new ByteArrayInputStream(classBytes));
ClassVisitor visitor = matcher.newClassMatchVisitor(clazz.getClassLoader(), null, reader, null, iInstrumentationContext);
reader.accept(visitor, ClassReader.SKIP_CODE);
Mockito.verify(iInstrumentationContext, Mockito.never()).putMatch(Mockito.<ClassMatchVisitorFactory>anyObject(), Mockito.<Match>anyObject());
}
use of com.newrelic.agent.instrumentation.context.InstrumentationContext in project newrelic-java-agent by newrelic.
the class OptimizedClassMatcherTest method testReturnTypeMatch.
@Test
public void testReturnTypeMatch() throws IOException {
ClassMatchVisitorFactory matcher = OptimizedClassMatcherBuilder.newBuilder().addClassMethodMatcher(new DefaultClassAndMethodMatcher(new AllClassesMatcher(), new ExactReturnTypeMethodMatcher(Type.getType(List.class)))).build();
InstrumentationContext instrumentationContext = getInstrumentationContext(matcher, Arrays.class);
Assert.assertFalse(instrumentationContext.getMatches().isEmpty());
Match match = instrumentationContext.getMatches().values().iterator().next();
Assert.assertNotNull(match);
Assert.assertEquals(1, match.getMethods().size());
Assert.assertTrue(match.getMethods().contains(new Method("asList", "([Ljava/lang/Object;)Ljava/util/List;")));
Assert.assertEquals(1, match.getClassMatches().size());
}
Aggregations