/** * Matches a {@link ByteCodeElement} that is visible to a given {@link java.lang.Class}. * * @param type The type that a matched byte code element is expected to be visible to. * @param <T> The type of the matched object. * @return A matcher for a byte code element to be visible to a given {@code type}. */ public static <T extends ByteCodeElement> ElementMatcher.Junction<T> isVisibleTo(Class<?> type) { return isVisibleTo(TypeDescription.ForLoadedType.of(type)); }
/** * {@inheritDoc} */ public MethodGraph.Linked compile(TypeDefinition typeDefinition, TypeDescription viewPoint) { Map<TypeDefinition, Key.Store<T>> snapshots = new HashMap<TypeDefinition, Key.Store<T>>(); Key.Store<?> rootStore = doAnalyze(typeDefinition, snapshots, isVirtual().and(isVisibleTo(viewPoint))); TypeDescription.Generic superClass = typeDefinition.getSuperClass(); List<TypeDescription.Generic> interfaceTypes = typeDefinition.getInterfaces(); Map<TypeDescription, MethodGraph> interfaceGraphs = new HashMap<TypeDescription, MethodGraph>(); for (TypeDescription.Generic interfaceType : interfaceTypes) { interfaceGraphs.put(interfaceType.asErasure(), snapshots.get(interfaceType).asGraph(merger)); } return new Linked.Delegation(rootStore.asGraph(merger), superClass == null ? Empty.INSTANCE : snapshots.get(superClass).asGraph(merger), interfaceGraphs); }
/** * {@inheritDoc} */ public Linked compile(TypeDefinition typeDefinition, TypeDescription viewPoint) { LinkedHashMap<MethodDescription.SignatureToken, Node> nodes = new LinkedHashMap<MethodDescription.SignatureToken, Node>(); for (MethodDescription methodDescription : typeDefinition.getDeclaredMethods().filter(isVirtual().and(not(isBridge())).and(isVisibleTo(viewPoint)))) { nodes.put(methodDescription.asSignatureToken(), new Node.Simple(methodDescription)); } return new Linked.Delegation(new MethodGraph.Simple(nodes), Empty.INSTANCE, Collections.<TypeDescription, MethodGraph>emptyMap()); } }
/** * {@inheritDoc} */ public Resolution locate(String name) { FieldList<?> candidates = locate(named(name).and(isVisibleTo(accessingType))); return candidates.size() == 1 ? new Resolution.Simple(candidates.getOnly()) : Resolution.Illegal.INSTANCE; }
@Override protected List<MethodDescription.Token> doExtractConstructors(TypeDescription instrumentedType) { TypeDescription.Generic superClass = instrumentedType.getSuperClass(); MethodList<?> defaultConstructors = superClass == null ? new MethodList.Empty<MethodDescription.InGenericShape>() : superClass.getDeclaredMethods().filter(isConstructor().and(takesArguments(0)).<MethodDescription>and(isVisibleTo(instrumentedType))); if (defaultConstructors.size() == 1) { return Collections.singletonList(new MethodDescription.Token(Opcodes.ACC_PUBLIC)); } else { throw new IllegalArgumentException(instrumentedType.getSuperClass() + " declares no constructor that is visible to " + instrumentedType); } }
/** * {@inheritDoc} */ public MethodDescription resolve(TypeDescription targetType, ByteCodeElement target, TypeList.Generic parameters, TypeDescription.Generic result) { if (parameters.isEmpty()) { throw new IllegalStateException("Cannot substitute parameterless instruction with " + target); } else if (parameters.get(0).isPrimitive() || parameters.get(0).isArray()) { throw new IllegalStateException("Cannot invoke method on primitive or array type for " + target); } TypeDefinition typeDefinition = parameters.get(0); List<MethodDescription> candidates = CompoundList.<MethodDescription>of(methodGraphCompiler.compile(typeDefinition, instrumentedType) .listNodes() .asMethodList() .filter(matcher), typeDefinition.getDeclaredMethods().filter(isPrivate().<MethodDescription>and(isVisibleTo(instrumentedType)).and(matcher))); if (candidates.size() == 1) { return candidates.get(0); } else { throw new IllegalStateException("Not exactly one method that matches " + matcher + ": " + candidates); } } }
@Override protected List<MethodDescription.Token> doExtractConstructors(TypeDescription instrumentedType) { TypeDescription.Generic superClass = instrumentedType.getSuperClass(); return (superClass == null ? new MethodList.Empty<MethodDescription.InGenericShape>() : superClass.getDeclaredMethods().filter(isConstructor().and(isVisibleTo(instrumentedType)))).asTokenList(is(instrumentedType)); }
/** * {@inheritDoc} */ public Resolution locate(String name, TypeDescription type) { FieldList<?> candidates = locate(named(name).and(fieldType(type)).and(isVisibleTo(accessingType))); return candidates.size() == 1 ? new Resolution.Simple(candidates.getOnly()) : Resolution.Illegal.INSTANCE; }
/** * {@inheritDoc} */ public FieldDescription resolve(TypeDescription targetType, ByteCodeElement target, TypeList.Generic parameters, TypeDescription.Generic result) { if (parameters.isEmpty()) { throw new IllegalStateException("Cannot substitute parameterless instruction with " + target); } else if (parameters.get(0).isPrimitive() || parameters.get(0).isArray()) { throw new IllegalStateException("Cannot access field on primitive or array type for " + target); } TypeDefinition current = parameters.get(0); do { FieldList<?> fields = current.getDeclaredFields().filter(not(isStatic()).<FieldDescription>and(isVisibleTo(instrumentedType)).and(matcher)); if (fields.size() == 1) { return fields.getOnly(); } else if (fields.size() > 1) { throw new IllegalStateException("Ambiguous field location of " + fields); } current = current.getSuperClass(); } while (current != null); throw new IllegalStateException("Cannot locate field matching " + matcher + " on " + targetType); } }
@Override protected List<MethodDescription.Token> doExtractConstructors(TypeDescription instrumentedType) { TypeDescription.Generic superClass = instrumentedType.getSuperClass(); return (superClass == null ? new MethodList.Empty<MethodDescription.InGenericShape>() : superClass.getDeclaredMethods().filter(isConstructor().and(isVisibleTo(instrumentedType)))).asTokenList(is(instrumentedType)); }
/** * {@inheritDoc} */ public ElementMatcher<? super MethodDescription> resolve(TypeDescription typeDescription) { // Casting is required by JDK 6. return (ElementMatcher<? super MethodDescription>) isVirtual().and(not(isFinal())) .and(isVisibleTo(typeDescription)) .and(not(ignoredMethods.resolve(typeDescription))) .or(isDeclaredBy(typeDescription)); } }
/** * Resolves a special method invocation for a constructor invocation. * * @param token A token describing the constructor to be invoked. * @return A special method invocation for a constructor representing the given method token, if available. */ private Implementation.SpecialMethodInvocation invokeConstructor(MethodDescription.SignatureToken token) { TypeDescription.Generic superClass = instrumentedType.getSuperClass(); MethodList<?> candidates = superClass == null ? new MethodList.Empty<MethodDescription.InGenericShape>() : superClass.getDeclaredMethods().filter(hasSignature(token).and(isVisibleTo(instrumentedType))); return candidates.size() == 1 ? Implementation.SpecialMethodInvocation.Simple.of(candidates.getOnly(), instrumentedType.getSuperClass().asErasure()) : Implementation.SpecialMethodInvocation.Illegal.INSTANCE; }
.and(returns(isVisibleTo(instrumentedType))) .and(hasParameters(whereNone(hasType(not(isVisibleTo(instrumentedType)))))) .and(ignoredMethods.resolve(instrumentedType)); List<MethodDescription> methods = new ArrayList<MethodDescription>();
/** * {@inheritDoc} */ public MethodGraph.Linked compile(TypeDefinition typeDefinition, TypeDescription viewPoint) { LinkedHashMap<MethodDescription.SignatureToken, MethodGraph.Node> nodes = new LinkedHashMap<MethodDescription.SignatureToken, MethodGraph.Node>(); for (MethodDescription methodDescription : typeDefinition.getDeclaredMethods() .filter( // ignores all methods which refer to unknown types failSafe( isVirtual() .and(not(isBridge())) .and(isVisibleTo(viewPoint)) .and(hasParameters(whereNone(hasType(not(isVisibleTo(viewPoint)))))) ) ) ) { nodes.put(methodDescription.asSignatureToken(), new MethodGraph.Node.Simple(methodDescription)); } return new MethodGraph.Linked.Delegation(new MethodGraph.Simple(nodes), MethodGraph.Empty.INSTANCE, Collections.<TypeDescription, MethodGraph>emptyMap()); } }