Search in sources :

Example 1 with ConstructorElement

use of io.micronaut.inject.ast.ConstructorElement in project micronaut-core by micronaut-projects.

the class BeanIntrospectionWriter method invokeBeanConstructor.

private void invokeBeanConstructor(GeneratorAdapter writer, MethodElement constructor, BiConsumer<GeneratorAdapter, MethodElement> argumentsPusher) {
    boolean isConstructor = constructor instanceof ConstructorElement;
    boolean isCompanion = constructor != defaultConstructor && constructor.getDeclaringType().getSimpleName().endsWith("$Companion");
    List<ParameterElement> constructorArguments = Arrays.asList(constructor.getParameters());
    Collection<Type> argumentTypes = constructorArguments.stream().map(pe -> JavaModelUtils.getTypeReference(pe.getType())).collect(Collectors.toList());
    if (isConstructor) {
        writer.newInstance(beanType);
        writer.dup();
    } else if (isCompanion) {
        writer.getStatic(beanType, "Companion", JavaModelUtils.getTypeReference(constructor.getDeclaringType()));
    }
    argumentsPusher.accept(writer, constructor);
    if (isConstructor) {
        final String constructorDescriptor = getConstructorDescriptor(constructorArguments);
        writer.invokeConstructor(beanType, new Method("<init>", constructorDescriptor));
    } else if (constructor.isStatic()) {
        final String methodDescriptor = getMethodDescriptor(beanType, argumentTypes);
        Method method = new Method(constructor.getName(), methodDescriptor);
        if (classElement.isInterface()) {
            writer.visitMethodInsn(Opcodes.INVOKESTATIC, beanType.getInternalName(), method.getName(), method.getDescriptor(), true);
        } else {
            writer.invokeStatic(beanType, method);
        }
    } else if (isCompanion) {
        writer.invokeVirtual(JavaModelUtils.getTypeReference(constructor.getDeclaringType()), new Method(constructor.getName(), getMethodDescriptor(beanType, argumentTypes)));
    }
}
Also used : ConstructorElement(io.micronaut.inject.ast.ConstructorElement) ElementQuery(io.micronaut.inject.ast.ElementQuery) Arrays(java.util.Arrays) ArrayUtils(io.micronaut.core.util.ArrayUtils) FieldElement(io.micronaut.inject.ast.FieldElement) Internal(io.micronaut.core.annotation.Internal) BeanIntrospectionReference(io.micronaut.core.beans.BeanIntrospectionReference) Type(org.objectweb.asm.Type) Map(java.util.Map) NameUtils(io.micronaut.core.naming.NameUtils) AbstractBeanIntrospectionReference(io.micronaut.core.beans.AbstractBeanIntrospectionReference) AbstractAnnotationMetadataWriter(io.micronaut.inject.writer.AbstractAnnotationMetadataWriter) AnnotationMetadataWriter(io.micronaut.inject.annotation.AnnotationMetadataWriter) AnnotationMetadataHierarchy(io.micronaut.inject.annotation.AnnotationMetadataHierarchy) Collection(java.util.Collection) Set(java.util.Set) NotNull(javax.validation.constraints.NotNull) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Introspected(io.micronaut.core.annotation.Introspected) List(java.util.List) MethodElement(io.micronaut.inject.ast.MethodElement) JavaModelUtils(io.micronaut.inject.processing.JavaModelUtils) ClassWriter(org.objectweb.asm.ClassWriter) AbstractInitializableBeanIntrospection(io.micronaut.inject.beans.AbstractInitializableBeanIntrospection) Label(org.objectweb.asm.Label) ClassElement(io.micronaut.inject.ast.ClassElement) HashMap(java.util.HashMap) StringSwitchWriter(io.micronaut.inject.writer.StringSwitchWriter) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Method(org.objectweb.asm.commons.Method) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) TypedElement(io.micronaut.inject.ast.TypedElement) Nullable(io.micronaut.core.annotation.Nullable) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) BiConsumer(java.util.function.BiConsumer) Argument(io.micronaut.core.type.Argument) ClassWriterOutputVisitor(io.micronaut.inject.writer.ClassWriterOutputVisitor) LinkedHashSet(java.util.LinkedHashSet) OutputStream(java.io.OutputStream) Opcodes(org.objectweb.asm.Opcodes) IOException(java.io.IOException) ReflectionUtils(io.micronaut.core.reflect.ReflectionUtils) NonNull(io.micronaut.core.annotation.NonNull) DispatchWriter(io.micronaut.inject.writer.DispatchWriter) BeanIntrospection(io.micronaut.core.beans.BeanIntrospection) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Collections(java.util.Collections) Type(org.objectweb.asm.Type) ParameterElement(io.micronaut.inject.ast.ParameterElement) Method(org.objectweb.asm.commons.Method)

Example 2 with ConstructorElement

use of io.micronaut.inject.ast.ConstructorElement in project micronaut-core by micronaut-projects.

the class AbstractBeanDefinitionBuilder method produceBeans.

@Override
public <E extends MemberElement> BeanElementBuilder produceBeans(ElementQuery<E> methodsOrFields, Consumer<BeanElementBuilder> childBeanBuilder) {
    methodsOrFields = methodsOrFields.onlyConcrete().onlyInstance().modifiers((modifiers) -> modifiers.contains(ElementModifier.PUBLIC));
    final List<E> enclosedElements = this.beanType.getEnclosedElements(methodsOrFields);
    for (E enclosedElement : enclosedElements) {
        if (enclosedElement instanceof FieldElement) {
            FieldElement fe = (FieldElement) enclosedElement;
            final ClassElement type = fe.getGenericField().getType();
            if (type.isPublic() && !type.isPrimitive()) {
                return addChildBean(fe, childBeanBuilder);
            }
        }
        if (enclosedElement instanceof MethodElement && !(enclosedElement instanceof ConstructorElement)) {
            MethodElement me = (MethodElement) enclosedElement;
            final ClassElement type = me.getGenericReturnType().getType();
            if (type.isPublic() && !type.isPrimitive()) {
                return addChildBean(me, childBeanBuilder);
            }
        }
    }
    return this;
}
Also used : ElementQuery(io.micronaut.inject.ast.ElementQuery) Arrays(java.util.Arrays) ArrayUtils(io.micronaut.core.util.ArrayUtils) FieldElement(io.micronaut.inject.ast.FieldElement) BeanFieldElement(io.micronaut.inject.ast.beans.BeanFieldElement) ClassElement(io.micronaut.inject.ast.ClassElement) HashMap(java.util.HashMap) Internal(io.micronaut.core.annotation.Internal) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) BeanMethodElement(io.micronaut.inject.ast.beans.BeanMethodElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) PreDestroy(javax.annotation.PreDestroy) ElementFactory(io.micronaut.inject.ast.ElementFactory) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Nullable(io.micronaut.core.annotation.Nullable) Map(java.util.Map) ElementModifier(io.micronaut.inject.ast.ElementModifier) AnnotationClassValue(io.micronaut.core.annotation.AnnotationClassValue) Property(io.micronaut.context.annotation.Property) Element(io.micronaut.inject.ast.Element) Iterator(java.util.Iterator) Predicate(java.util.function.Predicate) Set(java.util.Set) IOException(java.io.IOException) Value(io.micronaut.context.annotation.Value) BeanParameterElement(io.micronaut.inject.ast.beans.BeanParameterElement) MemberElement(io.micronaut.inject.ast.MemberElement) Bean(io.micronaut.context.annotation.Bean) Consumer(java.util.function.Consumer) NonNull(io.micronaut.core.annotation.NonNull) VisitorContext(io.micronaut.inject.visitor.VisitorContext) List(java.util.List) BeanConstructorElement(io.micronaut.inject.ast.beans.BeanConstructorElement) AnnotationValueBuilder(io.micronaut.core.annotation.AnnotationValueBuilder) BeanElementBuilder(io.micronaut.inject.ast.beans.BeanElementBuilder) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) MethodElement(io.micronaut.inject.ast.MethodElement) ConfigurationMetadataBuilder(io.micronaut.inject.configuration.ConfigurationMetadataBuilder) Annotation(java.lang.annotation.Annotation) PostConstruct(javax.annotation.PostConstruct) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Comparator(java.util.Comparator) Collections(java.util.Collections) MutableAnnotationMetadata(io.micronaut.inject.annotation.MutableAnnotationMetadata) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) BeanConstructorElement(io.micronaut.inject.ast.beans.BeanConstructorElement) FieldElement(io.micronaut.inject.ast.FieldElement) BeanFieldElement(io.micronaut.inject.ast.beans.BeanFieldElement) BeanMethodElement(io.micronaut.inject.ast.beans.BeanMethodElement) MethodElement(io.micronaut.inject.ast.MethodElement) ClassElement(io.micronaut.inject.ast.ClassElement)

Example 3 with ConstructorElement

use of io.micronaut.inject.ast.ConstructorElement in project micronaut-core by micronaut-projects.

the class JavaClassElement method getEnclosedElements.

@Override
public <T extends io.micronaut.inject.ast.Element> List<T> getEnclosedElements(@NonNull ElementQuery<T> query) {
    Objects.requireNonNull(query, "Query cannot be null");
    ElementQuery.Result<T> result = query.result();
    ElementKind kind = getElementKind(result.getElementType());
    List<T> resultingElements = new ArrayList<>();
    List<Element> enclosedElements = new ArrayList<>(getDeclaredEnclosedElements());
    boolean onlyDeclared = result.isOnlyDeclared();
    boolean onlyAbstract = result.isOnlyAbstract();
    boolean onlyConcrete = result.isOnlyConcrete();
    boolean onlyInstance = result.isOnlyInstance();
    if (!onlyDeclared) {
        Elements elements = visitorContext.getElements();
        TypeMirror superclass = classElement.getSuperclass();
        // traverse the super class true and add elements that are not overridden
        while (superclass instanceof DeclaredType) {
            DeclaredType dt = (DeclaredType) superclass;
            TypeElement element = (TypeElement) dt.asElement();
            // reached non-accessible class like Object, Enum, Record etc.
            if (element.getQualifiedName().toString().startsWith("java.lang.")) {
                break;
            }
            List<? extends Element> superElements = element.getEnclosedElements();
            List<Element> elementsToAdd = new ArrayList<>(superElements.size());
            superElements: for (Element superElement : superElements) {
                ElementKind superKind = superElement.getKind();
                if (superKind == kind) {
                    for (Element enclosedElement : enclosedElements) {
                        if (elements.hides(enclosedElement, superElement)) {
                            continue superElements;
                        } else if (enclosedElement.getKind() == ElementKind.METHOD && superElement.getKind() == ElementKind.METHOD) {
                            final ExecutableElement methodCandidate = (ExecutableElement) superElement;
                            if (elements.overrides((ExecutableElement) enclosedElement, methodCandidate, this.classElement)) {
                                continue superElements;
                            }
                        }
                    }
                    // dependency injection method resolution requires extended overrides checks
                    if (result.isOnlyInjected() && superElement.getKind() == ElementKind.METHOD) {
                        final ExecutableElement methodCandidate = (ExecutableElement) superElement;
                        // check for extended override
                        final String thisClassName = this.classElement.getQualifiedName().toString();
                        final String declaringClassName = element.getQualifiedName().toString();
                        boolean isParent = !declaringClassName.equals(thisClassName);
                        final ModelUtils javaModelUtils = visitorContext.getModelUtils();
                        final ExecutableElement overridingMethod = javaModelUtils.overridingOrHidingMethod(methodCandidate, this.classElement, false).orElse(methodCandidate);
                        TypeElement overridingClass = javaModelUtils.classElementFor(overridingMethod);
                        boolean overridden = isParent && overridingClass != null && !overridingClass.getQualifiedName().toString().equals(declaringClassName);
                        boolean isPackagePrivate = javaModelUtils.isPackagePrivate(methodCandidate);
                        boolean isPrivate = methodCandidate.getModifiers().contains(Modifier.PRIVATE);
                        if (overridden && !(isPrivate || isPackagePrivate)) {
                            // bail out if the method has been overridden, since it will have already been handled
                            continue;
                        }
                        if (isParent && overridden) {
                            boolean overriddenInjected = overridden && visitorContext.getAnnotationUtils().getAnnotationMetadata(overridingMethod).hasDeclaredAnnotation(AnnotationUtil.INJECT);
                            String packageOfOverridingClass = visitorContext.getElements().getPackageOf(overridingMethod).getQualifiedName().toString();
                            String packageOfDeclaringClass = visitorContext.getElements().getPackageOf(element).getQualifiedName().toString();
                            boolean isPackagePrivateAndPackagesDiffer = overridden && isPackagePrivate && !packageOfOverridingClass.equals(packageOfDeclaringClass);
                            if (!overriddenInjected && !isPackagePrivateAndPackagesDiffer && !isPrivate) {
                                // and is not annotated with @Inject
                                continue;
                            }
                        }
                    }
                    if (onlyAbstract && !superElement.getModifiers().contains(Modifier.ABSTRACT)) {
                        continue;
                    } else if (onlyConcrete && superElement.getModifiers().contains(Modifier.ABSTRACT)) {
                        continue;
                    } else if (onlyInstance && superElement.getModifiers().contains(Modifier.STATIC)) {
                        continue;
                    }
                    elementsToAdd.add(superElement);
                }
            }
            enclosedElements.addAll(elementsToAdd);
            superclass = element.getSuperclass();
        }
        if (kind == ElementKind.METHOD) {
            // if the element kind is interfaces then we need to go through interfaces as well
            Set<TypeElement> allInterfaces = visitorContext.getModelUtils().getAllInterfaces(this.classElement);
            List<Element> elementsToAdd = new ArrayList<>(allInterfaces.size());
            for (TypeElement itfe : allInterfaces) {
                List<? extends Element> interfaceElements = itfe.getEnclosedElements();
                interfaceElements: for (Element interfaceElement : interfaceElements) {
                    if (interfaceElement.getKind() == ElementKind.METHOD) {
                        ExecutableElement ee = (ExecutableElement) interfaceElement;
                        if (onlyAbstract && ee.getModifiers().contains(Modifier.DEFAULT)) {
                            continue;
                        } else if (onlyConcrete && !ee.getModifiers().contains(Modifier.DEFAULT)) {
                            continue;
                        }
                        for (Element enclosedElement : enclosedElements) {
                            if (enclosedElement.getKind() == ElementKind.METHOD) {
                                if (elements.overrides((ExecutableElement) enclosedElement, ee, this.classElement)) {
                                    continue interfaceElements;
                                }
                            }
                        }
                        elementsToAdd.add(interfaceElement);
                    }
                }
            }
            enclosedElements.addAll(elementsToAdd);
            elementsToAdd.clear();
        }
    }
    boolean onlyAccessible = result.isOnlyAccessible();
    if (kind == ElementKind.METHOD) {
        if (onlyAbstract) {
            if (isInterface()) {
                enclosedElements.removeIf((e) -> e.getModifiers().contains(Modifier.DEFAULT));
            } else {
                enclosedElements.removeIf((e) -> !e.getModifiers().contains(Modifier.ABSTRACT));
            }
        } else if (onlyConcrete) {
            if (isInterface()) {
                enclosedElements.removeIf((e) -> !e.getModifiers().contains(Modifier.DEFAULT));
            } else {
                enclosedElements.removeIf((e) -> e.getModifiers().contains(Modifier.ABSTRACT));
            }
        }
    }
    if (onlyInstance) {
        enclosedElements.removeIf((e) -> e.getModifiers().contains(Modifier.STATIC));
    }
    List<Predicate<Set<ElementModifier>>> modifierPredicates = result.getModifierPredicates();
    List<Predicate<String>> namePredicates = result.getNamePredicates();
    List<Predicate<AnnotationMetadata>> annotationPredicates = result.getAnnotationPredicates();
    final List<Predicate<ClassElement>> typePredicates = result.getTypePredicates();
    boolean hasNamePredicates = !namePredicates.isEmpty();
    boolean hasModifierPredicates = !modifierPredicates.isEmpty();
    boolean hasAnnotationPredicates = !annotationPredicates.isEmpty();
    boolean hasTypePredicates = !typePredicates.isEmpty();
    final JavaElementFactory elementFactory = visitorContext.getElementFactory();
    elementLoop: for (Element enclosedElement : enclosedElements) {
        ElementKind enclosedElementKind = enclosedElement.getKind();
        if (enclosedElementKind == kind || (enclosedElementKind == ElementKind.ENUM && kind == ElementKind.CLASS)) {
            String elementName = enclosedElement.getSimpleName().toString();
            if (onlyAccessible) {
                // exclude private members
                if (enclosedElement.getModifiers().contains(Modifier.PRIVATE)) {
                    continue;
                } else if (elementName.startsWith("$")) {
                    // exclude synthetic members or bridge methods that start with $
                    continue;
                } else {
                    Element enclosingElement = enclosedElement.getEnclosingElement();
                    final ClassElement onlyAccessibleFrom = result.getOnlyAccessibleFromType().orElse(this);
                    Object accessibleFrom = onlyAccessibleFrom.getNativeType();
                    // we need to check if it package private and within a different package so it can be excluded
                    if (enclosingElement != accessibleFrom && visitorContext.getModelUtils().isPackagePrivate(enclosedElement)) {
                        if (enclosingElement instanceof TypeElement) {
                            Name qualifiedName = ((TypeElement) enclosingElement).getQualifiedName();
                            String packageName = NameUtils.getPackageName(qualifiedName.toString());
                            if (!packageName.equals(onlyAccessibleFrom.getPackageName())) {
                                continue;
                            }
                        }
                    }
                }
            }
            if (hasModifierPredicates) {
                Set<ElementModifier> modifiers = enclosedElement.getModifiers().stream().map(m -> ElementModifier.valueOf(m.name())).collect(Collectors.toSet());
                for (Predicate<Set<ElementModifier>> modifierPredicate : modifierPredicates) {
                    if (!modifierPredicate.test(modifiers)) {
                        continue elementLoop;
                    }
                }
            }
            if (hasNamePredicates) {
                for (Predicate<String> namePredicate : namePredicates) {
                    if (!namePredicate.test(elementName)) {
                        continue elementLoop;
                    }
                }
            }
            final AnnotationMetadata metadata = visitorContext.getAnnotationUtils().getAnnotationMetadata(enclosedElement);
            if (hasAnnotationPredicates) {
                for (Predicate<AnnotationMetadata> annotationPredicate : annotationPredicates) {
                    if (!annotationPredicate.test(metadata)) {
                        continue elementLoop;
                    }
                }
            }
            T element;
            switch(enclosedElementKind) {
                case METHOD:
                    final ExecutableElement executableElement = (ExecutableElement) enclosedElement;
                    // noinspection unchecked
                    element = (T) elementFactory.newMethodElement(this, executableElement, metadata, genericTypeInfo);
                    break;
                case FIELD:
                    // noinspection unchecked
                    element = (T) elementFactory.newFieldElement(this, (VariableElement) enclosedElement, metadata);
                    break;
                case CONSTRUCTOR:
                    // noinspection unchecked
                    element = (T) elementFactory.newConstructorElement(this, (ExecutableElement) enclosedElement, metadata);
                    break;
                case CLASS:
                case ENUM:
                    // noinspection unchecked
                    element = (T) elementFactory.newClassElement((TypeElement) enclosedElement, metadata);
                    break;
                default:
                    element = null;
            }
            if (element != null) {
                if (hasTypePredicates) {
                    for (Predicate<ClassElement> typePredicate : typePredicates) {
                        ClassElement classElement;
                        if (element instanceof ConstructorElement) {
                            classElement = this;
                        } else if (element instanceof MethodElement) {
                            classElement = ((MethodElement) element).getGenericReturnType();
                        } else if (element instanceof ClassElement) {
                            classElement = (ClassElement) element;
                        } else {
                            classElement = ((FieldElement) element).getGenericField();
                        }
                        if (!typePredicate.test(classElement)) {
                            continue elementLoop;
                        }
                    }
                }
                List<Predicate<T>> elementPredicates = result.getElementPredicates();
                if (!elementPredicates.isEmpty()) {
                    for (Predicate<T> elementPredicate : elementPredicates) {
                        if (!elementPredicate.test(element)) {
                            continue elementLoop;
                        }
                    }
                }
                resultingElements.add(element);
            }
        }
    }
    return Collections.unmodifiableList(resultingElements);
}
Also used : ElementKind(javax.lang.model.element.ElementKind) ElementQuery(io.micronaut.inject.ast.ElementQuery) PackageElement(io.micronaut.inject.ast.PackageElement) AnnotationUtils(io.micronaut.annotation.processing.AnnotationUtils) Modifier(javax.lang.model.element.Modifier) FieldElement(io.micronaut.inject.ast.FieldElement) TypeElement(javax.lang.model.element.TypeElement) Internal(io.micronaut.core.annotation.Internal) WildcardElement(io.micronaut.inject.ast.WildcardElement) Elements(javax.lang.model.util.Elements) PublicMethodVisitor(io.micronaut.annotation.processing.PublicMethodVisitor) Map(java.util.Map) NameUtils(io.micronaut.core.naming.NameUtils) ClassUtils(io.micronaut.core.reflect.ClassUtils) GenericPlaceholderElement(io.micronaut.inject.ast.GenericPlaceholderElement) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Set(java.util.Set) AccessorsStyle(io.micronaut.core.annotation.AccessorsStyle) Element(javax.lang.model.element.Element) Types(javax.lang.model.util.Types) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) StringUtils(io.micronaut.core.util.StringUtils) SuperclassAwareTypeVisitor(io.micronaut.annotation.processing.SuperclassAwareTypeVisitor) List(java.util.List) AnnotationUtil(io.micronaut.core.annotation.AnnotationUtil) ModelUtils(io.micronaut.annotation.processing.ModelUtils) MethodElement(io.micronaut.inject.ast.MethodElement) TypeVariable(javax.lang.model.type.TypeVariable) Optional(java.util.Optional) JavaModelUtils(io.micronaut.inject.processing.JavaModelUtils) VariableElement(javax.lang.model.element.VariableElement) ClassElement(io.micronaut.inject.ast.ClassElement) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) PropertyElement(io.micronaut.inject.ast.PropertyElement) ArrayableClassElement(io.micronaut.inject.ast.ArrayableClassElement) DeclaredType(javax.lang.model.type.DeclaredType) ElementModifier(io.micronaut.inject.ast.ElementModifier) Name(javax.lang.model.element.Name) ElementKind(javax.lang.model.element.ElementKind) Iterator(java.util.Iterator) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeParameterElement(javax.lang.model.element.TypeParameterElement) NonNull(io.micronaut.core.annotation.NonNull) TypeMirror(javax.lang.model.type.TypeMirror) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Collections(java.util.Collections) Set(java.util.Set) PackageElement(io.micronaut.inject.ast.PackageElement) FieldElement(io.micronaut.inject.ast.FieldElement) TypeElement(javax.lang.model.element.TypeElement) WildcardElement(io.micronaut.inject.ast.WildcardElement) GenericPlaceholderElement(io.micronaut.inject.ast.GenericPlaceholderElement) Element(javax.lang.model.element.Element) MethodElement(io.micronaut.inject.ast.MethodElement) VariableElement(javax.lang.model.element.VariableElement) ClassElement(io.micronaut.inject.ast.ClassElement) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) PropertyElement(io.micronaut.inject.ast.PropertyElement) ArrayableClassElement(io.micronaut.inject.ast.ArrayableClassElement) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeParameterElement(javax.lang.model.element.TypeParameterElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) MethodElement(io.micronaut.inject.ast.MethodElement) FieldElement(io.micronaut.inject.ast.FieldElement) ClassElement(io.micronaut.inject.ast.ClassElement) ArrayableClassElement(io.micronaut.inject.ast.ArrayableClassElement) VariableElement(javax.lang.model.element.VariableElement) Elements(javax.lang.model.util.Elements) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Predicate(java.util.function.Predicate) Name(javax.lang.model.element.Name) ElementQuery(io.micronaut.inject.ast.ElementQuery) TypeMirror(javax.lang.model.type.TypeMirror) ModelUtils(io.micronaut.annotation.processing.ModelUtils) JavaModelUtils(io.micronaut.inject.processing.JavaModelUtils) List(java.util.List) ArrayList(java.util.ArrayList) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) TypeElement(javax.lang.model.element.TypeElement) ElementModifier(io.micronaut.inject.ast.ElementModifier) DeclaredType(javax.lang.model.type.DeclaredType)

Example 4 with ConstructorElement

use of io.micronaut.inject.ast.ConstructorElement in project micronaut-core by micronaut-projects.

the class BeanDefinitionWriter method isInterceptedLifeCycleByType.

private boolean isInterceptedLifeCycleByType(AnnotationMetadata annotationMetadata, String interceptType) {
    return isLifeCycleCache.computeIfAbsent(interceptType, s -> {
        if (this.beanTypeElement.isAssignable("io.micronaut.aop.Interceptor")) {
            // interceptor beans cannot have lifecycle methods intercepted
            return false;
        }
        final Element originatingElement = getOriginatingElements()[0];
        final boolean isFactoryMethod = (originatingElement instanceof MethodElement && !(originatingElement instanceof ConstructorElement));
        final boolean isProxyTarget = annotationMetadata.booleanValue(AnnotationUtil.ANN_AROUND, "proxyTarget").orElse(false) || isFactoryMethod;
        // for beans that are @Around(proxyTarget=false) only the generated AOP impl should be intercepted
        final boolean isAopType = StringUtils.isNotEmpty(interceptedType);
        final boolean isConstructorInterceptionCandidate = (isProxyTarget && !isAopType) || (isAopType && !isProxyTarget);
        final boolean hasAroundConstruct;
        final AnnotationValue<Annotation> interceptorBindings = annotationMetadata.getAnnotation(AnnotationUtil.ANN_INTERCEPTOR_BINDINGS);
        List<AnnotationValue<Annotation>> interceptorBindingAnnotations;
        if (interceptorBindings != null) {
            interceptorBindingAnnotations = interceptorBindings.getAnnotations(AnnotationMetadata.VALUE_MEMBER);
            hasAroundConstruct = interceptorBindingAnnotations.stream().anyMatch(av -> av.stringValue("kind").map(k -> k.equals(interceptType)).orElse(false));
        } else {
            interceptorBindingAnnotations = Collections.emptyList();
            hasAroundConstruct = false;
        }
        if (isConstructorInterceptionCandidate) {
            return hasAroundConstruct;
        } else if (hasAroundConstruct) {
            AnnotationMetadata typeMetadata = annotationMetadata;
            if (!isSuperFactory && typeMetadata instanceof AnnotationMetadataHierarchy) {
                typeMetadata = ((AnnotationMetadataHierarchy) typeMetadata).getRootMetadata();
                final AnnotationValue<Annotation> av = typeMetadata.getAnnotation(AnnotationUtil.ANN_INTERCEPTOR_BINDINGS);
                if (av != null) {
                    interceptorBindingAnnotations = av.getAnnotations(AnnotationMetadata.VALUE_MEMBER);
                } else {
                    interceptorBindingAnnotations = Collections.emptyList();
                }
            }
            // if no other AOP advice is applied
            return interceptorBindingAnnotations.stream().noneMatch(av -> av.stringValue("kind").map(k -> k.equals("AROUND")).orElse(false));
        } else {
            return false;
        }
    });
}
Also used : ConstructorElement(io.micronaut.inject.ast.ConstructorElement) Bindable(io.micronaut.core.bind.annotation.Bindable) Arrays(java.util.Arrays) DefaultBeanContext(io.micronaut.context.DefaultBeanContext) Internal(io.micronaut.core.annotation.Internal) VISITORS(io.micronaut.inject.visitor.BeanElementVisitor.VISITORS) InstantiationUtils(io.micronaut.core.reflect.InstantiationUtils) Duration(java.time.Duration) Map(java.util.Map) PropertyMetadata(io.micronaut.inject.configuration.PropertyMetadata) Property(io.micronaut.context.annotation.Property) AnnotationMetadataWriter(io.micronaut.inject.annotation.AnnotationMetadataWriter) AnnotationMetadataHierarchy(io.micronaut.inject.annotation.AnnotationMetadataHierarchy) Provided(io.micronaut.context.annotation.Provided) Singleton(jakarta.inject.Singleton) Set(java.util.Set) Bean(io.micronaut.context.annotation.Bean) Stream(java.util.stream.Stream) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) ProxyBeanDefinition(io.micronaut.inject.ProxyBeanDefinition) MethodElement(io.micronaut.inject.ast.MethodElement) SignatureVisitor(org.objectweb.asm.signature.SignatureVisitor) EachProperty(io.micronaut.context.annotation.EachProperty) BeanFactory(io.micronaut.inject.BeanFactory) MutableAnnotationMetadata(io.micronaut.inject.annotation.MutableAnnotationMetadata) JavaModelUtils(io.micronaut.inject.processing.JavaModelUtils) ClassWriter(org.objectweb.asm.ClassWriter) BeanRegistration(io.micronaut.context.BeanRegistration) Parameter(io.micronaut.context.annotation.Parameter) AnnotationMetadataProvider(io.micronaut.core.annotation.AnnotationMetadataProvider) AbstractExecutableMethod(io.micronaut.context.AbstractExecutableMethod) Qualifier(io.micronaut.context.Qualifier) Toggleable(io.micronaut.core.util.Toggleable) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) Constructor(java.lang.reflect.Constructor) TreeSet(java.util.TreeSet) ParameterElement(io.micronaut.inject.ast.ParameterElement) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) TypedElement(io.micronaut.inject.ast.TypedElement) ConfigurationProperties(io.micronaut.context.annotation.ConfigurationProperties) AbstractConstructorInjectionPoint(io.micronaut.context.AbstractConstructorInjectionPoint) Nullable(io.micronaut.core.annotation.Nullable) BeanElement(io.micronaut.inject.ast.beans.BeanElement) Argument(io.micronaut.core.type.Argument) IOException(java.io.IOException) VisitorContext(io.micronaut.inject.visitor.VisitorContext) AnnotationValueBuilder(io.micronaut.core.annotation.AnnotationValueBuilder) BeanDefinition(io.micronaut.inject.BeanDefinition) ValidatedBeanDefinition(io.micronaut.inject.ValidatedBeanDefinition) ElementQuery(io.micronaut.inject.ast.ElementQuery) BeanElementVisitor(io.micronaut.inject.visitor.BeanElementVisitor) MethodVisitor(org.objectweb.asm.MethodVisitor) BeanElementVisitorContext(io.micronaut.inject.visitor.BeanElementVisitorContext) BeanContext(io.micronaut.context.BeanContext) ArrayUtils(io.micronaut.core.util.ArrayUtils) FieldElement(io.micronaut.inject.ast.FieldElement) ConfigurationInject(io.micronaut.context.annotation.ConfigurationInject) Type(org.objectweb.asm.Type) ExecutableMethodsDefinition(io.micronaut.inject.ExecutableMethodsDefinition) DefaultScope(io.micronaut.context.annotation.DefaultScope) EachBean(io.micronaut.context.annotation.EachBean) ConfigurationBuilder(io.micronaut.context.annotation.ConfigurationBuilder) Locale(java.util.Locale) BeanResolutionContext(io.micronaut.context.BeanResolutionContext) NameUtils(io.micronaut.core.naming.NameUtils) AbstractInitializableBeanDefinition(io.micronaut.context.AbstractInitializableBeanDefinition) ClassVisitor(org.objectweb.asm.ClassVisitor) Method(java.lang.reflect.Method) AnyQualifier(io.micronaut.inject.qualifiers.AnyQualifier) ClassUtils(io.micronaut.core.reflect.ClassUtils) ConstructorInjectionPoint(io.micronaut.inject.ConstructorInjectionPoint) DefaultArgument(io.micronaut.core.type.DefaultArgument) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Qualifiers(io.micronaut.inject.qualifiers.Qualifiers) Collectors(java.util.stream.Collectors) DisposableBeanDefinition(io.micronaut.inject.DisposableBeanDefinition) StringUtils(io.micronaut.core.util.StringUtils) List(java.util.List) AnnotationUtil(io.micronaut.core.annotation.AnnotationUtil) BeanElementBuilder(io.micronaut.inject.ast.beans.BeanElementBuilder) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) NotNull(org.jetbrains.annotations.NotNull) BeanConstructor(io.micronaut.core.beans.BeanConstructor) Label(org.objectweb.asm.Label) ClassElement(io.micronaut.inject.ast.ClassElement) HashMap(java.util.HashMap) PrimitiveElement(io.micronaut.inject.ast.PrimitiveElement) ExecutableMethod(io.micronaut.inject.ExecutableMethod) HashSet(java.util.HashSet) Primary(io.micronaut.context.annotation.Primary) PropertyElement(io.micronaut.inject.ast.PropertyElement) Repeatable(java.lang.annotation.Repeatable) InitializingBeanDefinition(io.micronaut.inject.InitializingBeanDefinition) Any(io.micronaut.context.annotation.Any) ConfigurationReader(io.micronaut.context.annotation.ConfigurationReader) OutputStream(java.io.OutputStream) TypeVariableResolver(io.micronaut.core.type.TypeVariableResolver) Element(io.micronaut.inject.ast.Element) Iterator(java.util.Iterator) AdvisedBeanType(io.micronaut.inject.AdvisedBeanType) Value(io.micronaut.context.annotation.Value) MemberElement(io.micronaut.inject.ast.MemberElement) ReflectionUtils(io.micronaut.core.reflect.ReflectionUtils) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) NonNull(io.micronaut.core.annotation.NonNull) ParametrizedBeanFactory(io.micronaut.inject.ParametrizedBeanFactory) PropertySource(io.micronaut.context.annotation.PropertySource) CollectionUtils(io.micronaut.core.util.CollectionUtils) ConfigurationMetadataBuilder(io.micronaut.inject.configuration.ConfigurationMetadataBuilder) InjectScope(io.micronaut.context.annotation.InjectScope) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Comparator(java.util.Comparator) Collections(java.util.Collections) MethodElement(io.micronaut.inject.ast.MethodElement) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) TypedElement(io.micronaut.inject.ast.TypedElement) BeanElement(io.micronaut.inject.ast.beans.BeanElement) FieldElement(io.micronaut.inject.ast.FieldElement) ClassElement(io.micronaut.inject.ast.ClassElement) PrimitiveElement(io.micronaut.inject.ast.PrimitiveElement) PropertyElement(io.micronaut.inject.ast.PropertyElement) Element(io.micronaut.inject.ast.Element) MemberElement(io.micronaut.inject.ast.MemberElement) MethodElement(io.micronaut.inject.ast.MethodElement) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) AnnotationMetadataHierarchy(io.micronaut.inject.annotation.AnnotationMetadataHierarchy) Annotation(java.lang.annotation.Annotation) MutableAnnotationMetadata(io.micronaut.inject.annotation.MutableAnnotationMetadata) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata)

Example 5 with ConstructorElement

use of io.micronaut.inject.ast.ConstructorElement in project micronaut-core by micronaut-projects.

the class AbstractBeanDefinitionBuilder method build.

/**
 * Build the bean definition writer.
 * @return The writer, possibly null if it wasn't possible to build it
 */
@Nullable
public BeanDefinitionWriter build() {
    if (exposedTypes != null) {
        final AnnotationClassValue[] annotationClassValues = Arrays.stream(exposedTypes).map(ce -> new AnnotationClassValue<>(ce.getName())).toArray(AnnotationClassValue[]::new);
        annotate(Bean.class, (builder) -> builder.member("typed", annotationClassValues));
    }
    final BeanDefinitionWriter beanDefinitionWriter = createBeanDefinitionWriter();
    if (typeArguments != null) {
        beanDefinitionWriter.visitTypeArguments(this.typeArguments);
    }
    if (constructorElement == null) {
        constructorElement = initConstructor(beanType);
    }
    if (constructorElement == null) {
        visitorContext.fail("Cannot create associated bean with no accessible primary constructor. Consider supply the constructor with createWith(..)", originatingElement);
        return null;
    } else {
        beanDefinitionWriter.visitBeanDefinitionConstructor(constructorElement, !constructorElement.isPublic(), visitorContext);
    }
    Map<ClassElement, List<MemberElement>> sortedInjections = new LinkedHashMap<>();
    List<MemberElement> allInjected = new ArrayList<>();
    allInjected.addAll(injectedFields);
    allInjected.addAll(injectedMethods);
    allInjected.sort(SORTER);
    for (MemberElement memberElement : allInjected) {
        final List<MemberElement> list = sortedInjections.computeIfAbsent(memberElement.getDeclaringType(), classElement -> new ArrayList<>());
        list.add(memberElement);
    }
    for (List<MemberElement> members : sortedInjections.values()) {
        members.sort((o1, o2) -> {
            if (o1 instanceof FieldElement && o2 instanceof MethodElement) {
                return 1;
            } else if (o1 instanceof MethodElement && o1 instanceof FieldElement) {
                return -1;
            }
            return 0;
        });
    }
    for (List<MemberElement> list : sortedInjections.values()) {
        for (MemberElement memberElement : list) {
            if (memberElement instanceof FieldElement) {
                InternalBeanElementField ibf = (InternalBeanElementField) memberElement;
                ibf.<InternalBeanElementField>with((element) -> visitField(beanDefinitionWriter, element, element));
            } else {
                InternalBeanElementMethod ibm = (InternalBeanElementMethod) memberElement;
                ibm.<InternalBeanElementMethod>with((element) -> beanDefinitionWriter.visitMethodInjectionPoint(ibm.getDeclaringType(), ibm, ibm.isRequiresReflection(), visitorContext));
            }
        }
    }
    for (BeanMethodElement executableMethod : executableMethods) {
        beanDefinitionWriter.visitExecutableMethod(beanType, executableMethod, visitorContext);
    }
    for (BeanMethodElement postConstructMethod : postConstructMethods) {
        if (postConstructMethod.getDeclaringType().equals(beanType)) {
            beanDefinitionWriter.visitPostConstructMethod(beanType, postConstructMethod, ((InternalBeanElementMethod) postConstructMethod).isRequiresReflection(), visitorContext);
        }
    }
    for (BeanMethodElement preDestroyMethod : preDestroyMethods) {
        if (preDestroyMethod.getDeclaringType().equals(beanType)) {
            beanDefinitionWriter.visitPreDestroyMethod(beanType, preDestroyMethod, ((InternalBeanElementMethod) preDestroyMethod).isRequiresReflection(), visitorContext);
        }
    }
    beanDefinitionWriter.visitBeanDefinitionEnd();
    return beanDefinitionWriter;
}
Also used : ElementQuery(io.micronaut.inject.ast.ElementQuery) Arrays(java.util.Arrays) ArrayUtils(io.micronaut.core.util.ArrayUtils) FieldElement(io.micronaut.inject.ast.FieldElement) BeanFieldElement(io.micronaut.inject.ast.beans.BeanFieldElement) ClassElement(io.micronaut.inject.ast.ClassElement) HashMap(java.util.HashMap) Internal(io.micronaut.core.annotation.Internal) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) BeanMethodElement(io.micronaut.inject.ast.beans.BeanMethodElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) PreDestroy(javax.annotation.PreDestroy) ElementFactory(io.micronaut.inject.ast.ElementFactory) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Nullable(io.micronaut.core.annotation.Nullable) Map(java.util.Map) ElementModifier(io.micronaut.inject.ast.ElementModifier) AnnotationClassValue(io.micronaut.core.annotation.AnnotationClassValue) Property(io.micronaut.context.annotation.Property) Element(io.micronaut.inject.ast.Element) Iterator(java.util.Iterator) Predicate(java.util.function.Predicate) Set(java.util.Set) IOException(java.io.IOException) Value(io.micronaut.context.annotation.Value) BeanParameterElement(io.micronaut.inject.ast.beans.BeanParameterElement) MemberElement(io.micronaut.inject.ast.MemberElement) Bean(io.micronaut.context.annotation.Bean) Consumer(java.util.function.Consumer) NonNull(io.micronaut.core.annotation.NonNull) VisitorContext(io.micronaut.inject.visitor.VisitorContext) List(java.util.List) BeanConstructorElement(io.micronaut.inject.ast.beans.BeanConstructorElement) AnnotationValueBuilder(io.micronaut.core.annotation.AnnotationValueBuilder) BeanElementBuilder(io.micronaut.inject.ast.beans.BeanElementBuilder) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) MethodElement(io.micronaut.inject.ast.MethodElement) ConfigurationMetadataBuilder(io.micronaut.inject.configuration.ConfigurationMetadataBuilder) Annotation(java.lang.annotation.Annotation) PostConstruct(javax.annotation.PostConstruct) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Comparator(java.util.Comparator) Collections(java.util.Collections) MutableAnnotationMetadata(io.micronaut.inject.annotation.MutableAnnotationMetadata) ArrayList(java.util.ArrayList) FieldElement(io.micronaut.inject.ast.FieldElement) BeanFieldElement(io.micronaut.inject.ast.beans.BeanFieldElement) BeanMethodElement(io.micronaut.inject.ast.beans.BeanMethodElement) MethodElement(io.micronaut.inject.ast.MethodElement) ClassElement(io.micronaut.inject.ast.ClassElement) AnnotationClassValue(io.micronaut.core.annotation.AnnotationClassValue) LinkedHashMap(java.util.LinkedHashMap) BeanMethodElement(io.micronaut.inject.ast.beans.BeanMethodElement) ArrayList(java.util.ArrayList) List(java.util.List) MemberElement(io.micronaut.inject.ast.MemberElement) Nullable(io.micronaut.core.annotation.Nullable)

Aggregations

AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)5 Internal (io.micronaut.core.annotation.Internal)5 NonNull (io.micronaut.core.annotation.NonNull)5 ClassElement (io.micronaut.inject.ast.ClassElement)5 ConstructorElement (io.micronaut.inject.ast.ConstructorElement)5 ElementQuery (io.micronaut.inject.ast.ElementQuery)5 FieldElement (io.micronaut.inject.ast.FieldElement)5 MethodElement (io.micronaut.inject.ast.MethodElement)5 ArrayList (java.util.ArrayList)5 Collections (java.util.Collections)5 List (java.util.List)5 Map (java.util.Map)5 Set (java.util.Set)5 Nullable (io.micronaut.core.annotation.Nullable)4 ArrayUtils (io.micronaut.core.util.ArrayUtils)4 ParameterElement (io.micronaut.inject.ast.ParameterElement)4 IOException (java.io.IOException)4 Arrays (java.util.Arrays)4 Bean (io.micronaut.context.annotation.Bean)3 Property (io.micronaut.context.annotation.Property)3