/** * Creates a visitor for attaching type variables. * * @param declaringType The declaring type which is filled in for {@link TargetType} in its erased form. * @param typeVariableSource The source which is used for locating type variables. */ protected ForAttachment(TypeDefinition declaringType, TypeVariableSource typeVariableSource) { this(declaringType.asErasure(), typeVariableSource); }
if (typeDefinition.represents(boolean.class) || typeDefinition.represents(byte.class) || typeDefinition.represents(short.class) || typeDefinition.represents(char.class) || typeDefinition.represents(int.class)) { return Trivial.INSTANCE; } else if (typeDefinition.represents(long.class)) { return LONG; } else if (typeDefinition.represents(float.class)) { return FLOAT; } else if (typeDefinition.represents(double.class)) { return DOUBLE; } else if (typeDefinition.represents(boolean[].class)) { return BOOLEAN_ARRAY; } else if (typeDefinition.represents(byte[].class)) { return BYTE_ARRAY; } else if (typeDefinition.represents(short[].class)) { return SHORT_ARRAY; } else if (typeDefinition.represents(char[].class)) { return CHARACTER_ARRAY; } else if (typeDefinition.represents(int[].class)) { return INTEGER_ARRAY; } else if (typeDefinition.represents(long[].class)) { return LONG_ARRAY; } else if (typeDefinition.represents(float[].class)) { return FLOAT_ARRAY; } else if (typeDefinition.represents(double[].class)) { return DOUBLE_ARRAY; } else if (typeDefinition.isArray()) {
/** * {@inheritDoc} */ public boolean matches(T target) { return matcher.matches(target.getDeclaredFields()); }
/** * Returns a method return corresponding to a given type. * * @param typeDefinition The type to be returned. * @return The stack manipulation representing the method return. */ public static StackManipulation of(TypeDefinition typeDefinition) { if (typeDefinition.isPrimitive()) { if (typeDefinition.represents(long.class)) { return LONG; } else if (typeDefinition.represents(double.class)) { return DOUBLE; } else if (typeDefinition.represents(float.class)) { return FLOAT; } else if (typeDefinition.represents(void.class)) { return VOID; } else { return INTEGER; } } else { return REFERENCE; } }
/** * Creates a suitable array creator for the given component type. * * @param componentType The component type of the array to be created. * @return A suitable array creator. */ private static ArrayCreator makeArrayCreatorFor(TypeDefinition componentType) { if (!componentType.isPrimitive()) { return new ArrayCreator.ForReferenceType(componentType.asErasure()); } else if (componentType.represents(boolean.class)) { return ArrayCreator.ForPrimitiveType.BOOLEAN; } else if (componentType.represents(byte.class)) { return ArrayCreator.ForPrimitiveType.BYTE; } else if (componentType.represents(short.class)) { return ArrayCreator.ForPrimitiveType.SHORT; } else if (componentType.represents(char.class)) { return ArrayCreator.ForPrimitiveType.CHARACTER; } else if (componentType.represents(int.class)) { return ArrayCreator.ForPrimitiveType.INTEGER; } else if (componentType.represents(long.class)) { return ArrayCreator.ForPrimitiveType.LONG; } else if (componentType.represents(float.class)) { return ArrayCreator.ForPrimitiveType.FLOAT; } else if (componentType.represents(double.class)) { return ArrayCreator.ForPrimitiveType.DOUBLE; } else { throw new IllegalArgumentException("Cannot create array of type " + componentType); } }
/** * Creates a casting to the given, non-primitive type. * * @param typeDefinition The type to which a value should be casted. * @return A stack manipulation that represents the casting. */ public static StackManipulation to(TypeDefinition typeDefinition) { if (typeDefinition.isPrimitive()) { throw new IllegalArgumentException("Cannot cast to primitive type: " + typeDefinition); } return new TypeCasting(typeDefinition.asErasure()); }
private static Collection<AnnotatedFieldDescription> collectInheritPersistentFields( TypeDefinition managedCtClass, ByteBuddyEnhancementContext enhancementContext) { if ( managedCtClass == null || managedCtClass.represents( Object.class ) ) { return Collections.emptyList(); } TypeDefinition managedCtSuperclass = managedCtClass.getSuperClass(); if ( !enhancementContext.isMappedSuperclassClass( managedCtSuperclass.asErasure() ) ) { return collectInheritPersistentFields( managedCtSuperclass, enhancementContext ); } log.debugf( "Found @MappedSuperclass %s to collectPersistenceFields", managedCtSuperclass ); List<AnnotatedFieldDescription> persistentFieldList = new ArrayList<>(); for ( FieldDescription ctField : managedCtSuperclass.getDeclaredFields() ) { if ( ctField.getName().startsWith( "$$_hibernate_" ) || "this$0".equals( ctField.getName() ) ) { continue; } AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( enhancementContext, ctField ); if ( !ctField.isStatic() && enhancementContext.isPersistentField( annotatedField ) ) { persistentFieldList.add( annotatedField ); } } persistentFieldList.addAll( collectInheritPersistentFields( managedCtSuperclass, enhancementContext ) ); return persistentFieldList; }
@Override protected HashCodeMethod hashCodeMethod(TypeDescription instrumentedType) { TypeDefinition typeDefinition = instrumentedType.getSuperClass(); while (typeDefinition != null && !typeDefinition.represents(Object.class)) { if (typeDefinition.asErasure().getDeclaredAnnotations().isAnnotationPresent(Enhance.class)) { return HashCodeMethod.usingSuperClassOffset(); } MethodList<?> hashCode = typeDefinition.getDeclaredMethods().filter(isHashCode()); if (!hashCode.isEmpty()) { return hashCode.getOnly().isAbstract() ? HashCodeMethod.usingDefaultOffset() : HashCodeMethod.usingSuperClassOffset(); } typeDefinition = typeDefinition.getSuperClass(); } return HashCodeMethod.usingDefaultOffset(); }
@Override protected boolean resolve(TypeDefinition typeDefinition) { return typeDefinition.represents(String.class); } },
methodExit.getAdviceType(), methodEnter.getNamedTypes()); List<TypeDescription> initialTypes = CompoundList.of(methodExit.getAdviceType().represents(void.class) ? Collections.<TypeDescription>emptyList() : Collections.singletonList(methodExit.getAdviceType().asErasure()), argumentHandler.getNamedTypes()); List<TypeDescription> preMethodTypes = methodEnter.getAdviceType().represents(void.class) ? Collections.<TypeDescription>emptyList() : Collections.singletonList(methodEnter.getAdviceType().asErasure()); methodSizeHandler = MethodSizeHandler.Default.of(instrumentedMethod, initialTypes,
/** * {@inheritDoc} */ public boolean matches(T target) { Set<TypeDescription> previous = new HashSet<TypeDescription>(); for (TypeDefinition typeDefinition : target) { if (!previous.add(typeDefinition.asErasure())) { // Main type can be an interface. return false; // Avoids a life-lock when encountering a recursive type-definition. } else if (matcher.matches(typeDefinition.asGenericType())) { return true; } LinkedList<TypeDefinition> interfaceTypes = new LinkedList<TypeDefinition>(typeDefinition.getInterfaces()); while (!interfaceTypes.isEmpty()) { TypeDefinition interfaceType = interfaceTypes.removeFirst(); if (previous.add(interfaceType.asErasure())) { if (matcher.matches(interfaceType.asGenericType())) { return true; } else { interfaceTypes.addAll(interfaceType.getInterfaces()); } } } } return false; }
/** * Matches a method against a list of types. * * @param target The method that is matched as a target. * @param typeDefinitions The type definitions to check if they declare a method with the same signature as {@code target}. * @param duplicates A set containing duplicate interfaces that do not need to be revisited. * @return {@code true} if any type defines a method with the same signature as the {@code target} method. */ private boolean matches(MethodDescription target, List<? extends TypeDefinition> typeDefinitions, Set<TypeDescription> duplicates) { for (TypeDefinition anInterface : typeDefinitions) { if (duplicates.add(anInterface.asErasure()) && (matches(target, anInterface) || matches(target, anInterface.getInterfaces(), duplicates))) { return true; } } return false; }
@Override public boolean equals(Object other) { if (this == other) { return true; } else if (!(other instanceof TypeDefinition)) { return false; } TypeDefinition typeDefinition = (TypeDefinition) other; return typeDefinition.getSort().isNonGeneric() && getName().equals(typeDefinition.asErasure().getName()); }
if (typeDefinition.isPrimitive()) { throw new IllegalArgumentException("Expected reference type instead of " + typeDefinition); } else if (typeDefinition.represents(Boolean.class)) { return ExplicitlyTypedUnboxingResponsible.BOOLEAN; } else if (typeDefinition.represents(Byte.class)) { return ExplicitlyTypedUnboxingResponsible.BYTE; } else if (typeDefinition.represents(Short.class)) { return ExplicitlyTypedUnboxingResponsible.SHORT; } else if (typeDefinition.represents(Character.class)) { return ExplicitlyTypedUnboxingResponsible.CHARACTER; } else if (typeDefinition.represents(Integer.class)) { return ExplicitlyTypedUnboxingResponsible.INTEGER; } else if (typeDefinition.represents(Long.class)) { return ExplicitlyTypedUnboxingResponsible.LONG; } else if (typeDefinition.represents(Float.class)) { return ExplicitlyTypedUnboxingResponsible.FLOAT; } else if (typeDefinition.represents(Double.class)) { return ExplicitlyTypedUnboxingResponsible.DOUBLE; } else { return new ImplicitlyTypedUnboxingResponsible(typeDefinition.asGenericType());
@Override public Target resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Advice.ArgumentHandler argumentHandler, Sort sort) { final String returnType = instrumentedMethod.getReturnType().asErasure().getSimpleName(); final String className = instrumentedMethod.getDeclaringType().getTypeName(); final String signature = String.format("%s %s.%s(%s)", returnType, className, instrumentedMethod.getName(), getSignature(instrumentedMethod)); return Target.ForStackManipulation.of(signature); } };
/** * Analyzes the given type description without checking if it is already presented in the key store. * * @param typeDefinition The type to analyze. * @param snapshots A map containing snapshots of key stores for previously analyzed types. * @param relevanceMatcher A matcher for filtering methods that should be included in the graph. * @return A key store describing the provided type. */ protected Key.Store<T> doAnalyze(TypeDefinition typeDefinition, Map<TypeDefinition, Key.Store<T>> snapshots, ElementMatcher<? super MethodDescription> relevanceMatcher) { Key.Store<T> store = analyzeNullable(typeDefinition.getSuperClass(), snapshots, relevanceMatcher); Key.Store<T> interfaceStore = new Key.Store<T>(); for (TypeDescription.Generic interfaceType : typeDefinition.getInterfaces()) { interfaceStore = interfaceStore.combineWith(analyze(interfaceType.accept(visitor), interfaceType, snapshots, relevanceMatcher)); } return store.inject(interfaceStore).registerTopLevel(typeDefinition.getDeclaredMethods().filter(relevanceMatcher), harmonizer); }
/** * {@inheritDoc} */ public void initialize() { for (Map.Entry<Integer, TypeDefinition> typeDefinition : resolveInitializationTypes(argumentHandler).entrySet()) { if (typeDefinition.getValue().represents(boolean.class) || typeDefinition.getValue().represents(byte.class) || typeDefinition.getValue().represents(short.class) || typeDefinition.getValue().represents(char.class) || typeDefinition.getValue().represents(int.class)) { methodVisitor.visitInsn(Opcodes.ICONST_0); methodVisitor.visitVarInsn(Opcodes.ISTORE, typeDefinition.getKey()); } else if (typeDefinition.getValue().represents(long.class)) { methodVisitor.visitInsn(Opcodes.LCONST_0); methodVisitor.visitVarInsn(Opcodes.LSTORE, typeDefinition.getKey()); } else if (typeDefinition.getValue().represents(float.class)) { methodVisitor.visitInsn(Opcodes.FCONST_0); methodVisitor.visitVarInsn(Opcodes.FSTORE, typeDefinition.getKey()); } else if (typeDefinition.getValue().represents(double.class)) { methodVisitor.visitInsn(Opcodes.DCONST_0); methodVisitor.visitVarInsn(Opcodes.DSTORE, typeDefinition.getKey()); } else { methodVisitor.visitInsn(Opcodes.ACONST_NULL); methodVisitor.visitVarInsn(Opcodes.ASTORE, typeDefinition.getKey()); } methodSizeHandler.requireStackSize(typeDefinition.getValue().getStackSize().getSize()); } }
/** * {@inheritDoc} */ public TerminationHandler make(TypeDescription instrumentedType) { TypeDefinition current = instrumentedType; do { FieldList<?> candidates = current.getDeclaredFields().filter(isAccessibleTo(instrumentedType).and(matcher)); if (candidates.size() == 1) { return new FieldSetting(candidates.getOnly()); } else if (candidates.size() == 2) { throw new IllegalStateException(matcher + " is ambigous and resolved: " + candidates); } current = current.getSuperClass(); } while (current != null); throw new IllegalStateException(matcher + " does not locate any accessible fields for " + instrumentedType); } }
/** * {@inheritDoc} */ public boolean matches(T target) { return matcher.matches(target.getDeclaredMethods()); }
/** * {@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); }