Search in sources :

Example 1 with BeanInfo

use of io.quarkus.arc.processor.BeanInfo in project quarkus by quarkusio.

the class SpringScheduledProcessor method collectScheduledMethods.

@BuildStep
void collectScheduledMethods(BeanRegistrationPhaseBuildItem beanRegistrationPhase, BuildProducer<ScheduledBusinessMethodItem> scheduledBusinessMethods) {
    AnnotationStore annotationStore = beanRegistrationPhase.getContext().get(BuildExtension.Key.ANNOTATION_STORE);
    for (BeanInfo bean : beanRegistrationPhase.getContext().beans().classBeans()) {
        ClassInfo classInfo = bean.getTarget().get().asClass();
        for (MethodInfo method : classInfo.methods()) {
            List<AnnotationInstance> schedules = null;
            AnnotationInstance scheduledAnnotation = annotationStore.getAnnotation(method, SPRING_SCHEDULED);
            if (scheduledAnnotation != null) {
                schedules = Collections.singletonList(scheduledAnnotation);
            } else {
                AnnotationInstance schedulesAnnotation = annotationStore.getAnnotation(method, SPRING_SCHEDULES);
                if (schedulesAnnotation != null) {
                    schedules = new ArrayList<>();
                    for (AnnotationInstance scheduledInstance : schedulesAnnotation.value().asNestedArray()) {
                        schedules.add(AnnotationInstance.create(scheduledInstance.name(), schedulesAnnotation.target(), scheduledInstance.values()));
                    }
                }
            }
            processSpringScheduledAnnotation(scheduledBusinessMethods, bean, method, schedules);
        }
    }
}
Also used : BeanInfo(io.quarkus.arc.processor.BeanInfo) MethodInfo(org.jboss.jandex.MethodInfo) AnnotationStore(io.quarkus.arc.processor.AnnotationStore) AnnotationInstance(org.jboss.jandex.AnnotationInstance) ClassInfo(org.jboss.jandex.ClassInfo) BuildStep(io.quarkus.deployment.annotations.BuildStep)

Example 2 with BeanInfo

use of io.quarkus.arc.processor.BeanInfo in project quarkus by quarkusio.

the class SmallRyeReactiveMessagingProcessor method build.

@BuildStep
@Record(STATIC_INIT)
public void build(SmallRyeReactiveMessagingRecorder recorder, RecorderContext recorderContext, BuildProducer<SyntheticBeanBuildItem> syntheticBeans, List<MediatorBuildItem> mediatorMethods, List<InjectedEmitterBuildItem> emitterFields, List<InjectedChannelBuildItem> channelFields, BuildProducer<GeneratedClassBuildItem> generatedClass, BuildProducer<ReflectiveClassBuildItem> reflectiveClass, ReactiveMessagingConfiguration conf) {
    ClassOutput classOutput = new GeneratedClassGizmoAdaptor(generatedClass, true);
    List<QuarkusMediatorConfiguration> mediatorConfigurations = new ArrayList<>(mediatorMethods.size());
    List<WorkerConfiguration> workerConfigurations = new ArrayList<>();
    List<EmitterConfiguration> emittersConfigurations = new ArrayList<>();
    List<ChannelConfiguration> channelConfigurations = new ArrayList<>();
    /*
         * Go through the collected MediatorMethods and build up the corresponding MediaConfiguration
         * This includes generating an invoker for each method
         * The configuration will then be captured and used at static init time to push data into smallrye
         */
    for (MediatorBuildItem mediatorMethod : mediatorMethods) {
        MethodInfo methodInfo = mediatorMethod.getMethod();
        BeanInfo bean = mediatorMethod.getBean();
        if (methodInfo.hasAnnotation(BLOCKING) || methodInfo.hasAnnotation(SMALLRYE_BLOCKING) || methodInfo.hasAnnotation(TRANSACTIONAL)) {
            // Just in case both annotation are used, use @Blocking value.
            String poolName = Blocking.DEFAULT_WORKER_POOL;
            // If the method is annotated with the SmallRye Reactive Messaging @Blocking, extract the worker pool name if any
            if (methodInfo.hasAnnotation(ReactiveMessagingDotNames.BLOCKING)) {
                AnnotationInstance blocking = methodInfo.annotation(ReactiveMessagingDotNames.BLOCKING);
                poolName = blocking.value() == null ? Blocking.DEFAULT_WORKER_POOL : blocking.value().asString();
            }
            workerConfigurations.add(new WorkerConfiguration(methodInfo.declaringClass().toString(), methodInfo.name(), poolName));
        }
        try {
            boolean isSuspendMethod = isSuspendMethod(methodInfo);
            QuarkusMediatorConfiguration mediatorConfiguration = QuarkusMediatorConfigurationUtil.create(methodInfo, isSuspendMethod, bean, recorderContext, Thread.currentThread().getContextClassLoader(), conf.strict);
            mediatorConfigurations.add(mediatorConfiguration);
            String generatedInvokerName = generateInvoker(bean, methodInfo, isSuspendMethod, mediatorConfiguration, classOutput);
            /*
                 * We need to register the invoker's constructor for reflection since it will be called inside smallrye.
                 * We could potentially lift this restriction with some extra CDI bean generation, but it's probably not worth
                 * it
                 */
            reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, generatedInvokerName));
            mediatorConfiguration.setInvokerClass((Class<? extends Invoker>) recorderContext.classProxy(generatedInvokerName));
        } catch (IllegalArgumentException e) {
            // needed to pass the TCK
            throw new DeploymentException(e);
        }
    }
    for (InjectedEmitterBuildItem it : emitterFields) {
        emittersConfigurations.add(it.getEmitterConfig());
    }
    for (InjectedChannelBuildItem it : channelFields) {
        channelConfigurations.add(it.getChannelConfig());
    }
    syntheticBeans.produce(SyntheticBeanBuildItem.configure(SmallRyeReactiveMessagingContext.class).supplier(recorder.createContext(mediatorConfigurations, workerConfigurations, emittersConfigurations, channelConfigurations)).done());
}
Also used : InjectedChannelBuildItem(io.quarkus.smallrye.reactivemessaging.deployment.items.InjectedChannelBuildItem) BeanInfo(io.quarkus.arc.processor.BeanInfo) ArrayList(java.util.ArrayList) ChannelConfiguration(io.smallrye.reactive.messaging.providers.extension.ChannelConfiguration) GeneratedClassGizmoAdaptor(io.quarkus.deployment.GeneratedClassGizmoAdaptor) EmitterConfiguration(io.smallrye.reactive.messaging.EmitterConfiguration) MediatorBuildItem(io.quarkus.smallrye.reactivemessaging.deployment.items.MediatorBuildItem) QuarkusMediatorConfiguration(io.quarkus.smallrye.reactivemessaging.runtime.QuarkusMediatorConfiguration) WorkerConfiguration(io.quarkus.smallrye.reactivemessaging.runtime.WorkerConfiguration) ClassOutput(io.quarkus.gizmo.ClassOutput) InjectedEmitterBuildItem(io.quarkus.smallrye.reactivemessaging.deployment.items.InjectedEmitterBuildItem) MethodInfo(org.jboss.jandex.MethodInfo) DeploymentException(javax.enterprise.inject.spi.DeploymentException) SmallRyeReactiveMessagingContext(io.quarkus.smallrye.reactivemessaging.runtime.SmallRyeReactiveMessagingRecorder.SmallRyeReactiveMessagingContext) AnnotationInstance(org.jboss.jandex.AnnotationInstance) ReflectiveClassBuildItem(io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem) BuildStep(io.quarkus.deployment.annotations.BuildStep) Record(io.quarkus.deployment.annotations.Record)

Example 3 with BeanInfo

use of io.quarkus.arc.processor.BeanInfo in project quarkus by quarkusio.

the class WiringProcessor method extractComponents.

@BuildStep
void extractComponents(BeanDiscoveryFinishedBuildItem beanDiscoveryFinished, TransformedAnnotationsBuildItem transformedAnnotations, BuildProducer<ChannelBuildItem> appChannels, BuildProducer<MediatorBuildItem> mediatorMethods, BuildProducer<InjectedEmitterBuildItem> emitters, BuildProducer<InjectedChannelBuildItem> channels, BuildProducer<ValidationPhaseBuildItem.ValidationErrorBuildItem> validationErrors, BuildProducer<ConfigDescriptionBuildItem> configDescriptionBuildItemBuildProducer) {
    Map<String, AnnotationInstance> emitterFactories = new HashMap<>();
    // We need to collect all business methods annotated with @Incoming/@Outgoing first
    for (BeanInfo bean : beanDiscoveryFinished.beanStream().classBeans()) {
        // TODO: add support for inherited business methods
        // noinspection OptionalGetWithoutIsPresent
        AnnotationInstance emitterFactory = transformedAnnotations.getAnnotation(bean.getTarget().get(), ReactiveMessagingDotNames.EMITTER_FACTORY_FOR);
        if (emitterFactory != null) {
            emitterFactories.put(emitterFactory.value().asClass().name().toString(), emitterFactory);
        }
        for (MethodInfo method : bean.getTarget().get().asClass().methods()) {
            // @Incoming is repeatable
            AnnotationInstance incoming = transformedAnnotations.getAnnotation(method, ReactiveMessagingDotNames.INCOMING);
            AnnotationInstance incomings = transformedAnnotations.getAnnotation(method, ReactiveMessagingDotNames.INCOMINGS);
            AnnotationInstance outgoing = transformedAnnotations.getAnnotation(method, ReactiveMessagingDotNames.OUTGOING);
            AnnotationInstance blocking = transformedAnnotations.getAnnotation(method, BLOCKING);
            if (incoming != null || incomings != null || outgoing != null) {
                handleMethodAnnotatedWithIncoming(appChannels, validationErrors, configDescriptionBuildItemBuildProducer, method, incoming);
                handleMethodAnnotationWithIncomings(appChannels, validationErrors, configDescriptionBuildItemBuildProducer, method, incomings);
                handleMethodAnnotationWithOutgoing(appChannels, validationErrors, configDescriptionBuildItemBuildProducer, method, outgoing);
                if (WiringHelper.isSynthetic(method)) {
                    continue;
                }
                mediatorMethods.produce(new MediatorBuildItem(bean, method));
                LOGGER.debugf("Found mediator business method %s declared on %s", method, bean);
            } else if (blocking != null) {
                validationErrors.produce(new ValidationPhaseBuildItem.ValidationErrorBuildItem(new DeploymentException("@Blocking used on " + method + " which has no @Incoming or @Outgoing annotation")));
            }
        }
    }
    for (InjectionPointInfo injectionPoint : beanDiscoveryFinished.getInjectionPoints()) {
        Optional<AnnotationInstance> broadcast = WiringHelper.getAnnotation(transformedAnnotations, injectionPoint, ReactiveMessagingDotNames.BROADCAST);
        Optional<AnnotationInstance> channel = WiringHelper.getAnnotation(transformedAnnotations, injectionPoint, ReactiveMessagingDotNames.CHANNEL);
        Optional<AnnotationInstance> legacyChannel = WiringHelper.getAnnotation(transformedAnnotations, injectionPoint, ReactiveMessagingDotNames.LEGACY_CHANNEL);
        String injectionType = injectionPoint.getRequiredType().name().toString();
        AnnotationInstance emitterType = emitterFactories.get(injectionType);
        boolean isLegacyEmitter = injectionPoint.getRequiredType().name().equals(ReactiveMessagingDotNames.LEGACY_EMITTER);
        if (emitterType != null) {
            if (isLegacyEmitter) {
                // Deprecated Emitter from SmallRye (emitter, channel and on overflow have been added to the spec)
                handleEmitter(transformedAnnotations, appChannels, emitters, validationErrors, injectionPoint, emitterType, broadcast, legacyChannel, ReactiveMessagingDotNames.LEGACY_ON_OVERFLOW);
            } else {
                // New emitter from the spec, or Mutiny emitter
                handleEmitter(transformedAnnotations, appChannels, emitters, validationErrors, injectionPoint, emitterType, broadcast, channel, ReactiveMessagingDotNames.ON_OVERFLOW);
            }
        } else {
            if (channel.isPresent()) {
                handleChannelInjection(appChannels, channels, channel.get());
            }
            if (legacyChannel.isPresent()) {
                handleChannelInjection(appChannels, channels, legacyChannel.get());
            }
        }
    }
}
Also used : MediatorBuildItem(io.quarkus.smallrye.reactivemessaging.deployment.items.MediatorBuildItem) InjectionPointInfo(io.quarkus.arc.processor.InjectionPointInfo) HashMap(java.util.HashMap) BeanInfo(io.quarkus.arc.processor.BeanInfo) MethodInfo(org.jboss.jandex.MethodInfo) DeploymentException(javax.enterprise.inject.spi.DeploymentException) AnnotationInstance(org.jboss.jandex.AnnotationInstance) BuildStep(io.quarkus.deployment.annotations.BuildStep)

Example 4 with BeanInfo

use of io.quarkus.arc.processor.BeanInfo in project quarkus by quarkusio.

the class ArcTestContainer method init.

private ClassLoader init(ExtensionContext context) {
    // retrieve test class from extension context
    Class<?> testClass = context.getRequiredTestClass();
    // Make sure Arc is down
    Arc.shutdown();
    // Build index
    Index beanArchiveIndex;
    try {
        beanArchiveIndex = index(beanClasses);
    } catch (IOException e) {
        throw new IllegalStateException("Failed to create index", e);
    }
    Index applicationIndex;
    if (additionalClasses.isEmpty()) {
        applicationIndex = null;
    } else {
        try {
            applicationIndex = index(additionalClasses);
        } catch (IOException e) {
            throw new IllegalStateException("Failed to create index", e);
        }
    }
    ClassLoader old = Thread.currentThread().getContextClassLoader();
    try {
        String arcContainerAbsolutePath = ArcTestContainer.class.getClassLoader().getResource(ArcTestContainer.class.getName().replace(".", "/") + ".class").getFile();
        int targetClassesIndex = arcContainerAbsolutePath.indexOf(TARGET_TEST_CLASSES);
        String testClassesRootPath = arcContainerAbsolutePath.substring(0, targetClassesIndex);
        File generatedSourcesDirectory = new File("target/generated-arc-sources");
        File testOutputDirectory = new File(testClassesRootPath + TARGET_TEST_CLASSES);
        File componentsProviderFile = new File(generatedSourcesDirectory + "/" + nameToPath(testClass.getPackage().getName()), ComponentsProvider.class.getSimpleName());
        File resourceReferenceProviderFile = new File(generatedSourcesDirectory + "/" + nameToPath(testClass.getPackage().getName()), ResourceReferenceProvider.class.getSimpleName());
        if (!resourceReferenceProviders.isEmpty()) {
            try {
                resourceReferenceProviderFile.getParentFile().mkdirs();
                Files.write(resourceReferenceProviderFile.toPath(), resourceReferenceProviders.stream().map(c -> c.getName()).collect(Collectors.toList()));
            } catch (IOException e) {
                throw new IllegalStateException("Error generating resource reference providers", e);
            }
        }
        BeanProcessor.Builder builder = BeanProcessor.builder().setName(testClass.getSimpleName()).setBeanArchiveIndex(BeanArchives.buildBeanArchiveIndex(getClass().getClassLoader(), new ConcurrentHashMap<>(), beanArchiveIndex)).setApplicationIndex(applicationIndex);
        if (!resourceAnnotations.isEmpty()) {
            builder.addResourceAnnotations(resourceAnnotations.stream().map(c -> DotName.createSimple(c.getName())).collect(Collectors.toList()));
        }
        beanRegistrars.forEach(builder::addBeanRegistrar);
        observerRegistrars.forEach(builder::addObserverRegistrar);
        contextRegistrars.forEach(builder::addContextRegistrar);
        qualifierRegistrars.forEach(builder::addQualifierRegistrar);
        interceptorBindingRegistrars.forEach(builder::addInterceptorBindingRegistrar);
        annotationsTransformers.forEach(builder::addAnnotationTransformer);
        injectionPointsTransformers.forEach(builder::addInjectionPointTransformer);
        observerTransformers.forEach(builder::addObserverTransformer);
        beanDeploymentValidators.forEach(builder::addBeanDeploymentValidator);
        builder.setOutput(new ResourceOutput() {

            @Override
            public void writeResource(Resource resource) throws IOException {
                switch(resource.getType()) {
                    case JAVA_CLASS:
                        resource.writeTo(testOutputDirectory);
                        break;
                    case SERVICE_PROVIDER:
                        if (resource.getName().endsWith(ComponentsProvider.class.getName())) {
                            componentsProviderFile.getParentFile().mkdirs();
                            try (FileOutputStream out = new FileOutputStream(componentsProviderFile)) {
                                out.write(resource.getData());
                            }
                        }
                        break;
                    default:
                        throw new IllegalArgumentException();
                }
            }
        });
        builder.setRemoveUnusedBeans(removeUnusedBeans);
        for (Predicate<BeanInfo> exclusion : exclusions) {
            builder.addRemovalExclusion(exclusion);
        }
        builder.setAlternativePriorities(alternativePriorities);
        BeanProcessor beanProcessor = builder.build();
        try {
            beanProcessor.process();
        } catch (IOException e) {
            throw new IllegalStateException("Error generating resources", e);
        }
        URLClassLoader testClassLoader = new URLClassLoader(new URL[] {}, old) {

            @Override
            public Enumeration<URL> getResources(String name) throws IOException {
                if (("META-INF/services/" + ComponentsProvider.class.getName()).equals(name)) {
                    // return URL that points to the correct test bean provider
                    return Collections.enumeration(Collections.singleton(componentsProviderFile.toURI().toURL()));
                } else if (("META-INF/services/" + ResourceReferenceProvider.class.getName()).equals(name) && !resourceReferenceProviders.isEmpty()) {
                    return Collections.enumeration(Collections.singleton(resourceReferenceProviderFile.toURI().toURL()));
                }
                return super.getResources(name);
            }
        };
        Thread.currentThread().setContextClassLoader(testClassLoader);
        // store the test class loader into extension store
        getRootExtensionStore(context).put(KEY_TEST_CLASSLOADER, testClassLoader);
        // Now we are ready to initialize Arc
        Arc.initialize();
    } catch (Throwable e) {
        if (shouldFail) {
            buildFailure.set(e);
        } else {
            throw e;
        }
    }
    return old;
}
Also used : ComponentsProvider(io.quarkus.arc.ComponentsProvider) BeanProcessor(io.quarkus.arc.processor.BeanProcessor) BeanInfo(io.quarkus.arc.processor.BeanInfo) Index(org.jboss.jandex.Index) IOException(java.io.IOException) ResourceReferenceProvider(io.quarkus.arc.ResourceReferenceProvider) URL(java.net.URL) ResourceOutput(io.quarkus.arc.processor.ResourceOutput) FileOutputStream(java.io.FileOutputStream) URLClassLoader(java.net.URLClassLoader) URLClassLoader(java.net.URLClassLoader) File(java.io.File)

Example 5 with BeanInfo

use of io.quarkus.arc.processor.BeanInfo in project quarkus by quarkusio.

the class VertxProcessor method collectEventConsumers.

@BuildStep
void collectEventConsumers(BeanRegistrationPhaseBuildItem beanRegistrationPhase, BuildProducer<EventConsumerBusinessMethodItem> messageConsumerBusinessMethods, BuildProducer<BeanConfiguratorBuildItem> errors) {
    // We need to collect all business methods annotated with @ConsumeEvent first
    AnnotationStore annotationStore = beanRegistrationPhase.getContext().get(BuildExtension.Key.ANNOTATION_STORE);
    for (BeanInfo bean : beanRegistrationPhase.getContext().beans().classBeans()) {
        for (MethodInfo method : bean.getTarget().get().asClass().methods()) {
            AnnotationInstance consumeEvent = annotationStore.getAnnotation(method, CONSUME_EVENT);
            if (consumeEvent != null) {
                // Validate method params and return type
                List<Type> params = method.parameters();
                if (params.size() != 1) {
                    throw new IllegalStateException(String.format("An event consumer business method must accept exactly one parameter: %s [method: %s, bean:%s]", params, method, bean));
                }
                if (method.returnType().kind() != Kind.VOID && VertxConstants.isMessage(params.get(0).name())) {
                    throw new IllegalStateException(String.format("An event consumer business method that accepts io.vertx.core.eventbus.Message or io.vertx.mutiny.core.eventbus.Message must return void [method: %s, bean:%s]", method, bean));
                }
                messageConsumerBusinessMethods.produce(new EventConsumerBusinessMethodItem(bean, method, consumeEvent));
                LOGGER.debugf("Found event consumer business method %s declared on %s", method, bean);
            }
        }
    }
}
Also used : Type(org.jboss.jandex.Type) BeanInfo(io.quarkus.arc.processor.BeanInfo) MethodInfo(org.jboss.jandex.MethodInfo) AnnotationStore(io.quarkus.arc.processor.AnnotationStore) AnnotationInstance(org.jboss.jandex.AnnotationInstance) BuildStep(io.quarkus.deployment.annotations.BuildStep)

Aggregations

BeanInfo (io.quarkus.arc.processor.BeanInfo)16 BuildStep (io.quarkus.deployment.annotations.BuildStep)12 AnnotationInstance (org.jboss.jandex.AnnotationInstance)8 MethodInfo (org.jboss.jandex.MethodInfo)7 ClassInfo (org.jboss.jandex.ClassInfo)5 Type (org.jboss.jandex.Type)4 ArrayList (java.util.ArrayList)3 Predicate (java.util.function.Predicate)3 AnnotationStore (io.quarkus.arc.processor.AnnotationStore)2 DecoratorInfo (io.quarkus.arc.processor.DecoratorInfo)2 InjectionPointInfo (io.quarkus.arc.processor.InjectionPointInfo)2 InterceptorInfo (io.quarkus.arc.processor.InterceptorInfo)2 BuildProducer (io.quarkus.deployment.annotations.BuildProducer)2 Record (io.quarkus.deployment.annotations.Record)2 ClassOutput (io.quarkus.gizmo.ClassOutput)2 ResultHandle (io.quarkus.gizmo.ResultHandle)2 MediatorBuildItem (io.quarkus.smallrye.reactivemessaging.deployment.items.MediatorBuildItem)2 HashSet (java.util.HashSet)2 Set (java.util.Set)2 DeploymentException (javax.enterprise.inject.spi.DeploymentException)2