use of com.newrelic.weave.PreparedMatch in project newrelic-java-agent by newrelic.
the class PackageValidationResult method buildResults.
private void buildResults(ClassCache classCache, ClassNode originalClassNode, String weaveClassName, ClassNode weaveNode, Map<String, PreparedMatch> results, boolean isBaseMatch, Set<String> requiredClassAnnotations, Set<String> requiredMethodAnnotations, ClassNode errorHandler, Map<String, byte[]> annotationProxyClasses) throws IOException {
ClassMatch match = ClassMatch.match(originalClassNode, weaveNode, isBaseMatch, requiredClassAnnotations, requiredMethodAnnotations, classCache);
NewFieldValidator.validate(match, violations);
// exit sooner to prevent further processing (avoids NPE when no default constructor exists)
if (match.isFatalWeaveViolation()) {
violations.addAll(match.getViolations());
return;
}
PreparedMatch prepared = PreparedMatch.prepare(match, errorHandler, this.getWeavePackage().getExtensionTemplate(), true);
results.put(weaveClassName, prepared);
if (null != prepared.getExtension()) {
ClassNode extension = prepared.getExtension().generateExtensionClass();
utilClasses.put(extension.name, extension);
}
for (String newInnerClassName : prepared.getNewInnerClasses()) {
if (utilClasses.containsKey(newInnerClassName)) {
ClassNode newInnerClassNode = utilClasses.get(newInnerClassName);
match.validateNewInnerClass(newInnerClassNode);
newInnerClassNode = prepared.prepareNewInnerClass(newInnerClassNode);
utilClasses.remove(newInnerClassName);
String newInnerClassRenamed = prepared.nameNewInnerClass(newInnerClassName);
utilClasses.put(newInnerClassRenamed, newInnerClassNode);
}
}
for (Map.Entry<String, ClassNode> annotationProxyClass : prepared.getAnnotationProxyClasses().entrySet()) {
annotationProxyClasses.put(annotationProxyClass.getKey(), WeaveUtils.convertToClassBytes(annotationProxyClass.getValue(), classCache));
}
violations.addAll(match.getViolations());
}
use of com.newrelic.weave.PreparedMatch in project newrelic-java-agent by newrelic.
the class PackageValidationResult method getSuperWeaves.
private List<PreparedMatch> getSuperWeaves(String superName) {
List<PreparedMatch> superMatches = new ArrayList<>();
String currentName = superName;
while (null != currentName) {
PreparedMatch superMatch = exactMatches.get(currentName);
if (null == superMatch) {
break;
}
superMatches.add(superMatch);
currentName = superMatch.getWeaveSuperName();
}
currentName = superName;
while (null != currentName) {
PreparedMatch superMatch = baseMatches.get(currentName);
if (null == superMatch) {
break;
}
superMatches.add(superMatch);
currentName = superMatch.getWeaveSuperName();
}
return superMatches;
}
use of com.newrelic.weave.PreparedMatch in project newrelic-java-agent by newrelic.
the class PackageValidationResult method rewriteAllNewFieldCalls.
/**
* Rewrite all weave+util bytes to replace ops on newfields with extension class operations. See
* {@link MethodProcessors#rewriteNewFieldCalls(String, Map, Set, Set, List, List)} for details.
*/
private void rewriteAllNewFieldCalls() {
List<PreparedExtension> preparedExtensions = new ArrayList<>();
Collection<PreparedMatch> allMatches = new HashSet<>(exactMatches.size() + baseMatches.size());
allMatches.addAll(exactMatches.values());
allMatches.addAll(baseMatches.values());
for (PreparedMatch pmatch : allMatches) {
if (null != pmatch.getExtension()) {
preparedExtensions.add(pmatch.getExtension());
}
}
if (preparedExtensions.size() > 0) {
// rewrite weaves
for (PreparedMatch pmatch : allMatches) {
MethodProcessors.rewriteNewFieldCalls(pmatch.getWeaveName(), pmatch.getPreparedMatchedMethods(), pmatch.getNewFields(), pmatch.getMatchedFields(), preparedExtensions, getSuperWeaves(pmatch.getWeaveSuperName()));
}
// rewrite util classes
for (Map.Entry<String, ClassNode> entry : utilClasses.entrySet()) {
ClassNode utilNode = entry.getValue();
Set<String> matchedFields;
if (null == utilNode.fields) {
matchedFields = new HashSet<>(0);
} else {
matchedFields = new HashSet<>(utilNode.fields.size());
for (FieldNode field : utilNode.fields) {
matchedFields.add(field.name);
}
}
Map<Method, MethodNode> methodMap;
if (null == utilNode.methods) {
methodMap = new HashMap<>(0);
} else {
methodMap = new HashMap<>(utilNode.methods.size());
for (MethodNode methodNode : utilNode.methods) {
methodMap.put(new Method(methodNode.name, methodNode.desc), methodNode);
}
}
MethodProcessors.rewriteNewFieldCalls(utilNode.name, methodMap, new HashSet<String>(0), matchedFields, preparedExtensions, getSuperWeaves(utilNode.superName));
utilNode.methods = new ArrayList<>(methodMap.values());
}
}
}
use of com.newrelic.weave.PreparedMatch in project newrelic-java-agent by newrelic.
the class PackageValidationResult method getAnnotationMatchComposite.
private ClassNode getAnnotationMatchComposite(ClassNode targetNode, ClassNode weaveNode, ClassNode composite, Map<String, List<Method>> weavedMethods, ClassCache cache, Map<String, byte[]> annotationProxyClasses, Map<Method, Collection<String>> skipMethods) {
try {
boolean isInterfaceMatch = WeaveUtils.isWeaveWithAnnotationInterfaceMatch(weaveNode);
Map<String, PreparedMatch> results = new HashMap<>();
buildResults(cache, targetNode, weaveNode.name, weaveNode, results, isInterfaceMatch, weavePackage.getRequiredAnnotationClassesForAnnotationWeave(weaveNode.name), weavePackage.getRequiredAnnotationClassesForMethodAnnotationWeave(weaveNode.name), errorHandler, annotationProxyClasses);
if (!violations.isEmpty()) {
return composite;
}
for (Map.Entry<String, PreparedMatch> result : results.entrySet()) {
PreparedMatch prepared = result.getValue();
if (prepared != null) {
ClassWeave classWeave = ClassWeave.weave(prepared, composite, weavePackage, skipMethods);
composite = classWeave.getComposite();
// Key is only used for logging at the moment.
final String key = prepared.getWeaveName();
if (weavedMethods.containsKey(key)) {
weavedMethods.get(key).addAll(classWeave.getWeavedMethods());
} else {
weavedMethods.put(key, classWeave.getWeavedMethods());
}
}
}
} catch (Exception ignored) {
}
return composite;
}
use of com.newrelic.weave.PreparedMatch in project newrelic-java-agent by newrelic.
the class PackageValidationResult method weave.
/**
* Weave the target class and return a {@link PackageWeaveResult}.
*/
public PackageWeaveResult weave(String className, String[] superNames, String[] interfaceNames, ClassNode targetNode, ClassCache cache, Map<Method, Collection<String>> skipMethods) {
ClassNode composite = targetNode;
final Map<String, List<Method>> weavedMethods = new HashMap<>();
// Locks during weaving are due to the non-thread safe nature of {@link ClassNode}.
// first apply exact matches
{
PreparedMatch exactMatch = exactMatches.get(className);
if (null != exactMatch) {
ClassWeave classWeave;
classWeave = ClassWeave.weave(exactMatch, composite, weavePackage, skipMethods);
composite = classWeave.getComposite();
final String key = exactMatch.getOriginalName();
if (weavedMethods.containsKey(key)) {
weavedMethods.get(key).addAll(classWeave.getWeavedMethods());
} else {
weavedMethods.put(key, classWeave.getWeavedMethods());
}
}
}
{
// matcher for abstract class
PreparedMatch exactMatch = baseMatches.get(className);
if (null != exactMatch) {
ClassWeave classWeave;
classWeave = ClassWeave.weave(exactMatch, composite, weavePackage, skipMethods);
composite = classWeave.getComposite();
final String key = exactMatch.getOriginalName();
if (weavedMethods.containsKey(key)) {
weavedMethods.get(key).addAll(classWeave.getWeavedMethods());
} else {
weavedMethods.put(key, classWeave.getWeavedMethods());
}
}
}
// then apply super classes
for (int i = 0; i < superNames.length; ++i) {
PreparedMatch baseMatch = baseMatches.get(superNames[i]);
if (null != baseMatch) {
ClassWeave classWeave;
classWeave = ClassWeave.weave(baseMatch, composite, weavePackage, skipMethods);
composite = classWeave.getComposite();
final String key = baseMatch.getOriginalName();
if (weavedMethods.containsKey(key)) {
weavedMethods.get(key).addAll(classWeave.getWeavedMethods());
} else {
weavedMethods.put(key, classWeave.getWeavedMethods());
}
}
}
// then apply interfaces
for (int i = 0; i < interfaceNames.length; ++i) {
PreparedMatch baseMatch = baseMatches.get(interfaceNames[i]);
if (null != baseMatch) {
ClassWeave classWeave;
classWeave = ClassWeave.weave(baseMatch, composite, weavePackage, skipMethods);
composite = classWeave.getComposite();
final String key = baseMatch.getOriginalName();
if (weavedMethods.containsKey(key)) {
weavedMethods.get(key).addAll(classWeave.getWeavedMethods());
} else {
weavedMethods.put(key, classWeave.getWeavedMethods());
}
}
}
final Map<String, byte[]> annotationProxyClasses = new HashMap<>();
// class annotation matches
if (!allAnnotationClasses.isEmpty()) {
Set<String> targetAnnotationsClasses = getAnnotationClasses(targetNode);
Set<String> targetInterfacesAnnotationClasses = Collections.emptySet();
if (!baseAnnotationClasses.isEmpty()) {
targetInterfacesAnnotationClasses = getAllInterfaceAnnotationClasses(targetNode, cache);
}
// check for exact annotation matches
for (Map.Entry<String, ClassNode> entry : allAnnotationClasses.entrySet()) {
if (targetAnnotationsClasses.contains(entry.getKey())) {
composite = getAnnotationMatchComposite(targetNode, entry.getValue(), composite, weavedMethods, cache, annotationProxyClasses, skipMethods);
}
}
// check for base annotation matches
for (Map.Entry<String, ClassNode> entry : baseAnnotationClasses.entrySet()) {
if (targetInterfacesAnnotationClasses.contains(entry.getKey())) {
composite = getAnnotationMatchComposite(targetNode, entry.getValue(), composite, weavedMethods, cache, annotationProxyClasses, skipMethods);
}
}
}
// method annotation matches
if (!allMethodAnnotationClasses.isEmpty()) {
Set<String> targetMethodAnnotationsClasses = getMethodAnnotationClasses(targetNode);
for (Map.Entry<String, ClassNode> entry : allMethodAnnotationClasses.entrySet()) {
if (targetMethodAnnotationsClasses.contains(entry.getKey())) {
composite = getAnnotationMatchComposite(targetNode, entry.getValue(), composite, weavedMethods, cache, annotationProxyClasses, skipMethods);
// due to having multiple matching annotations that have the same underlying weave code.
break;
}
}
}
if (weavePackage != null) {
// Run any postprocessors that were passed in. It's important that we do this before the inliner runs below
ClassNode result = new SynchronizedClassNode(WeaveUtils.ASM_API_LEVEL);
ClassVisitor postprocessChain = weavePackage.getConfig().getPostprocessor().postprocess(className, result, Collections.<String>emptySet(), weavePackage, false);
composite.accept(postprocessChain);
composite = result;
}
return new PackageWeaveResult(this, className, composite, weavedMethods, annotationProxyClasses);
}
Aggregations