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);
}
}
}
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());
}
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());
}
}
}
}
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;
}
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);
}
}
}
}
Aggregations