@Override public int hashCode() { int result = instrumentedType.hashCode(); result = 31 * result + loadedTypeInitializer.hashCode(); result = 31 * result + typeInitializer.hashCode(); result = 31 * result + implementations.hashCode(); return result; }
@Override public boolean equals(Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; Compiled compiled = (Compiled) other; return instrumentedType.equals(compiled.instrumentedType) && loadedTypeInitializer.equals(compiled.loadedTypeInitializer) && typeInitializer.equals(compiled.typeInitializer) && implementations.equals(compiled.implementations); }
@Override public boolean equals(Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; Prepared prepared = (Prepared) other; return implementations.equals(prepared.implementations) && loadedTypeInitializer.equals(prepared.loadedTypeInitializer) && typeInitializer.equals(prepared.typeInitializer) && instrumentedType.equals(prepared.instrumentedType) && methodGraph.equals(prepared.methodGraph); }
@Override public MethodRegistry.Compiled compile( Implementation.Target.Factory implementationTargetFactory) { Map<Handler, Handler.Compiled> compilationCache = new HashMap<Handler, Handler.Compiled>(implementations.size()); Map<MethodAttributeAppender.Factory, MethodAttributeAppender> attributeAppenderCache = new HashMap<MethodAttributeAppender.Factory, MethodAttributeAppender>( implementations.size()); LinkedHashMap<MethodDescription, Compiled.Entry> entries = new LinkedHashMap<MethodDescription, Compiled.Entry>(implementations.size()); Implementation.Target implementationTarget = implementationTargetFactory.make(instrumentedType, methodGraph); for (Map.Entry<MethodDescription, Entry> entry : implementations.entrySet()) { Handler.Compiled cachedHandler = compilationCache.get(entry.getValue().getHandler()); if (cachedHandler == null) { cachedHandler = entry.getValue().getHandler().compile(implementationTarget); compilationCache.put(entry.getValue().getHandler(), cachedHandler); } MethodAttributeAppender cachedAttributeAppender = attributeAppenderCache.get(entry.getValue().getAppenderFactory()); if (cachedAttributeAppender == null) { cachedAttributeAppender = entry.getValue().getAppenderFactory().make(instrumentedType); attributeAppenderCache.put( entry.getValue().getAppenderFactory(), cachedAttributeAppender); } entries.put( entry.getKey(), new Compiled.Entry( cachedHandler, cachedAttributeAppender, entry.getValue().getMethodDescription(), entry.getValue().resolveBridgeTypes())); } return new Compiled(instrumentedType, loadedTypeInitializer, typeInitializer, entries); }
@Override public MethodList<?> getInstrumentedMethods() { return new MethodList.Explicit<MethodDescription>( new ArrayList<MethodDescription>(implementations.keySet())) .filter(not(isTypeInitializer())); }
@Override public MethodRegistry.Prepared prepare( InstrumentedType instrumentedType, MethodGraph.Compiler methodGraphCompiler, LatentMethodMatcher methodFilter) { LinkedHashMap<MethodDescription, Prepared.Entry> implementations = new LinkedHashMap<MethodDescription, Prepared.Entry>(); Set<Handler> handlers = new HashSet<Handler>(entries.size()); MethodList<?> helperMethods = instrumentedType.getDeclaredMethods(); for (Entry entry : entries) { if (handlers.add(entry.getHandler())) { instrumentedType = entry.getHandler().prepare(instrumentedType); ElementMatcher<? super MethodDescription> handledMethods = noneOf(helperMethods); helperMethods = instrumentedType.getDeclaredMethods(); for (MethodDescription helperMethod : helperMethods.filter(handledMethods)) { implementations.put(helperMethod, entry.asSupplementaryEntry(helperMethod)); } } } MethodGraph.Linked methodGraph = methodGraphCompiler.compile(instrumentedType); // Casting required for Java 6 compiler. ElementMatcher<? super MethodDescription> relevanceMatcher = (ElementMatcher<? super MethodDescription>) not(anyOf(implementations.keySet())).and(methodFilter.resolve(instrumentedType)); for (MethodGraph.Node node : methodGraph.listNodes()) { MethodDescription methodDescription = node.getRepresentative(); boolean visibilityBridge = instrumentedType.isPublic() && !instrumentedType.isInterface(); if (relevanceMatcher.matches(methodDescription)) { for (Entry entry : entries) { if (entry.resolve(instrumentedType).matches(methodDescription)) { implementations.put( methodDescription, entry.asPreparedEntry( instrumentedType, methodDescription, node.getMethodTypes())); visibilityBridge = false; break; } } } if (visibilityBridge && methodDescription.isPublic() && !(methodDescription.isAbstract() || methodDescription.isFinal()) && !node.getSort().isMadeVisible() && methodDescription.getDeclaringType().asErasure().isPackagePrivate()) { // Visibility bridges are required for public types that inherit a public method from a // package-private type. // Checking the last condition contradicts any method that is defined by the instrumented // type itself. implementations.put( methodDescription, Prepared.Entry.forVisibilityBridge(methodDescription, node.getMethodTypes())); } } MethodDescription typeInitializer = new MethodDescription.Latent.TypeInitializer(instrumentedType); for (Entry entry : entries) { if (entry.resolve(instrumentedType).matches(typeInitializer)) { implementations.put( typeInitializer, entry.asPreparedEntry( instrumentedType, typeInitializer, Collections.<MethodDescription.TypeToken>emptySet())); break; } } return new Prepared( implementations, instrumentedType.getLoadedTypeInitializer(), instrumentedType.getTypeInitializer(), instrumentedType.asErasure(), methodGraph); }
@Override public Record target(MethodDescription methodDescription) { Entry entry = implementations.get(methodDescription); return entry == null ? Record.ForNonDefinedMethod.INSTANCE : entry.bind(instrumentedType); }