use of com.newrelic.weave.utils.ClassInformation in project newrelic-java-agent by newrelic.
the class Reference method addMethodsAndFields.
/**
* Fetch all methods and fields of a class node including those inherited from supertypes+interfaces. The results
* will be stored in the passed in methods and fields lists.
*
* @param classCache Cache to use to fetch supertype resources
* @param classNode The node to scan
* @param methods classNode's methods will be appended to this list.
* @param fields classNode's fields will be appended to this list.
*/
private static void addMethodsAndFields(ClassCache classCache, ClassNode classNode, List<MethodNode> methods, List<FieldNode> fields) throws IOException {
ClassInformation classInfo = classCache.getClassInformation(classNode.name);
for (MemberInformation methodInfo : classInfo.getAllMethods(classCache)) {
MethodNode methodNode = new SynchronizedMethodNode();
methodNode.name = methodInfo.name;
methodNode.desc = methodInfo.desc;
methodNode.access = methodInfo.access;
methods.add(methodNode);
}
for (MemberInformation fieldInfo : classInfo.getAllFields(classCache)) {
fields.add(new SynchronizedFieldNode(WeaveUtils.ASM_API_LEVEL, fieldInfo.access, fieldInfo.name, fieldInfo.desc, null, null));
}
}
use of com.newrelic.weave.utils.ClassInformation in project newrelic-java-agent by newrelic.
the class WeavePackage method hasMatcher.
/**
* Returns true if this package contains at least one matcher for a class.
*/
public boolean hasMatcher(String className, String[] superNames, String[] interfaceNames, Set<String> classAnnotations, Set<String> methodAnnotations, ClassCache classCache) throws IOException {
if (this.exactWeaves.containsKey(className) || this.baseWeaves.containsKey(className))
return true;
for (int i = 0; i < superNames.length; ++i) {
if (this.baseWeaves.containsKey(superNames[i]))
return true;
}
for (int i = 0; i < interfaceNames.length; ++i) {
if (this.baseWeaves.containsKey(interfaceNames[i]))
return true;
}
// Check to see if any of the annotations on the class exist in the set of required Exact match annotations
Set<String> matchingAnnotations = Sets.intersection(allClassAnnotationWeaves.keySet(), classAnnotations);
if (!matchingAnnotations.isEmpty()) {
return true;
}
// If we have any base/interface annotation weaves check to see if the interfaces have the correct annotation(s)
if (!baseAnnotationWeaves.isEmpty()) {
Set<String> requiredBaseAnnotations = baseAnnotationWeaves.keySet();
for (String interfaceName : interfaceNames) {
ClassInformation classInformation = classCache.getClassInformation(interfaceName);
if (classHasRequiredAnnotations(classInformation, requiredBaseAnnotations)) {
return true;
}
}
}
// Check to see if any of the annotations on the methods exist in the set of required method annotations
Set<String> matchingMethodAnnotations = Sets.intersection(allMethodAnnotationWeaves.keySet(), methodAnnotations);
if (!matchingMethodAnnotations.isEmpty()) {
return true;
}
return false;
}
use of com.newrelic.weave.utils.ClassInformation in project newrelic-java-agent by newrelic.
the class WeavePackageManager method weave.
/**
* Weave all of the matched packages with the specified target bytes using the specified cache and listener.
*
* @param classloader classloader to resolve classes with
* @param cache {@link ClassCache} to find class metadata
* @param className target class name
* @param targetBytes target class bytes
* @param weaveListener listener containing callback if/when the composite is created
* @return composite class bytes, or <code>null</code> if no weaving occurred
*/
public byte[] weave(ClassLoader classloader, ClassCache cache, String className, byte[] targetBytes, Map<Method, Collection<String>> skipMethods, ClassWeavedListener weaveListener) throws IOException {
classloader = classLoaderSub(classloader);
if (preMatchWeaveMethods && !containsPossibleClassOrMethodMatch(className, targetBytes, requiredClasses, methodSignatures, cache)) {
// No potential method match was found, we are definitely not weaving this class so we should exit now
return null;
}
ClassInformation classInformation = cache.getClassInformation(className);
if (classInformation == null) {
return null;
}
String[] superNames = cache.getClassInformation(className).getAllSuperNames(cache).toArray(new String[0]);
String[] interfaceNames = cache.getClassInformation(className).getAllInterfaces(cache).toArray(new String[0]);
Set<String> classAnnotations = cache.getClassInformation(className).classAnnotationNames;
Set<String> methodAnnotations = cache.getClassInformation(className).methodAnnotationNames;
Set<PackageValidationResult> matchedPackageResults = this.match(classloader, cache, className, classAnnotations, methodAnnotations, superNames, interfaceNames);
if (matchedPackageResults.isEmpty()) {
return null;
}
ClassNode composite = WeaveUtils.convertToClassNode(targetBytes);
PackageWeaveResult finalResult = null;
for (PackageValidationResult weavePackageResult : matchedPackageResults) {
PackageWeaveResult result = weavePackageResult.weave(className, superNames, interfaceNames, composite, cache, skipMethods);
if (null != weaveListener) {
weaveListener.classWeaved(result, classloader, cache);
}
if (result.weavedClass()) {
composite = result.getComposite();
finalResult = result;
}
}
return null == finalResult ? null : finalResult.getCompositeBytes(cache);
}
use of com.newrelic.weave.utils.ClassInformation in project newrelic-java-agent by newrelic.
the class ClassWeaverService method transform.
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer, final InstrumentationContext context, Match match) throws IllegalClassFormatException {
if (!PointCutClassTransformer.isValidClassName(className)) {
return null;
}
ClassWeavedListener classWeavedCallback = new ClassWeavedListener() {
@Override
public void classWeaved(PackageWeaveResult weaveResult, ClassLoader classloader, ClassCache cache) {
List<WeaveViolation> violations = weaveResult.getValidationResult().getViolations();
if (!violations.isEmpty()) {
// This is due to the nature of annotation weaving happening at weave time instead of validation time
weaveViolationLogger.logWeaveViolations(weaveResult.getValidationResult(), classloader, false);
return;
}
final String packageName = weaveResult.getValidationResult().getWeavePackage().getName();
if (Agent.LOG.isFinerEnabled()) {
try {
if (Agent.LOG.isFinerEnabled()) {
ClassInformation weavedClass = cache.getClassInformation(weaveResult.getClassName());
Agent.LOG.log(Level.FINER, "{0} matched {1}", packageName, weavedClass.className);
for (String superName : weavedClass.getAllSuperNames(cache)) {
Agent.LOG.log(Level.FINER, "\ts: {0}", superName);
}
for (String interfaceName : weavedClass.getAllInterfaces(cache)) {
Agent.LOG.log(Level.FINER, "\ti: {0}", interfaceName);
}
}
} catch (IOException ioe) {
Agent.LOG.log(Level.FINEST, ioe, "exception while getting supertype info");
}
}
if (weaveResult.weavedClass()) {
try {
Map<String, byte[]> annotationProxyClasses = weaveResult.getAnnotationProxyClasses();
if (!annotationProxyClasses.isEmpty()) {
// the dynamic proxy classes that we created to the current classloader at this point
if (BootstrapLoader.PLACEHOLDER == classloader) {
NewClassAppender.appendClassesToBootstrapClassLoader(instrumentation, annotationProxyClasses);
} else {
NewClassAppender.appendClasses(classloader, annotationProxyClasses);
}
}
} catch (Exception e) {
Agent.LOG.log(Level.FINE, e, "Unable to add annotation proxy classes");
}
String weaveClassStat = MessageFormat.format(MetricNames.SUPPORTABILITY_WEAVE_CLASS, packageName, weaveResult.getClassName());
ServiceFactory.getStatsService().doStatsWork(StatsWorks.getRecordMetricWork(weaveClassStat, 1), weaveClassStat);
for (String originalName : weaveResult.getWeavedMethods().keySet()) {
Agent.LOG.log(Level.FINE, "{0}: weaved target {1}-{2}", packageName, classloader, weaveResult.getClassName());
for (Method method : weaveResult.getWeavedMethods().get(originalName)) {
Agent.LOG.log(Level.FINE, "\t{0}.{1}:{2}", originalName, method.getName(), method.getDescriptor());
context.addWeavedMethod(method, packageName);
}
addTraceInformation(ClassWeaverService.this.tracedWeaveInstrumentationDetails, packageName, context, weaveResult.getComposite(), originalName);
}
} else {
Agent.LOG.log(Level.FINER, "{0} matched class {1} but no methods were weaved.", packageName, weaveResult.getClassName());
}
}
};
try {
return weavePackageManager.weave(loader, getClassCache(loader), className, classfileBuffer, context.getSkipMethods(), classWeavedCallback);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
use of com.newrelic.weave.utils.ClassInformation in project newrelic-java-agent by newrelic.
the class ClassMatch method requiredMethodAnnotationInInterface.
private boolean requiredMethodAnnotationInInterface(MethodNode originalMethod, Set<String> methodRequiredAnnotations, ClassCache cache) {
try {
for (String interfaceName : original.interfaces) {
ClassInformation interfaceInformation = cache.getClassInformation(interfaceName);
for (ClassInformation.MemberInformation method : interfaceInformation.methods) {
if (method.name.equals(originalMethod.name) && method.desc.equals(originalMethod.desc)) {
Set<AnnotationNode> annotations = method.annotations;
Set<String> annotationClasses = new HashSet<>();
for (AnnotationNode annotation : annotations) {
annotationClasses.add(Type.getType(annotation.desc).getClassName());
}
if (WeaveUtils.hasRequiredAnnotations(annotationClasses, methodRequiredAnnotations)) {
return true;
}
}
}
}
} catch (IOException ignored) {
}
return false;
}
Aggregations