use of io.quarkus.arc.deployment.BeanArchiveIndexBuildItem in project quarkus by quarkusio.
the class MetricsFromExtensionTestCase method buildCustomizer.
protected static Consumer<BuildChainBuilder> buildCustomizer() {
return new Consumer<BuildChainBuilder>() {
// This represents the extension.
@Override
public void accept(BuildChainBuilder builder) {
builder.addBuildStep(context -> {
BeanArchiveIndexBuildItem indexBuildItem = context.consume(BeanArchiveIndexBuildItem.class);
for (ClassInfo clazz : indexBuildItem.getIndex().getKnownClasses()) {
for (MethodInfo method : clazz.methods()) {
if (method.name().startsWith("countMePlease")) {
Metadata metricMetadata = Metadata.builder().withType(MetricType.COUNTER).withName(clazz.name().toString() + "." + method.name()).build();
MetricBuildItem buildItem = new MetricBuildItem.Builder().metadata(metricMetadata).enabled(true).build();
context.produce(buildItem);
} else if (method.name().startsWith("countMeInBaseScope")) {
Metadata metricMetadata = Metadata.builder().withType(MetricType.COUNTER).withName(clazz.name().toString() + "." + method.name()).build();
MetricBuildItem buildItem = new MetricBuildItem.Builder().metadata(metricMetadata).registryType(MetricRegistry.Type.BASE).enabled(true).build();
context.produce(buildItem);
}
}
}
}).consumes(BeanArchiveIndexBuildItem.class).produces(MetricBuildItem.class).build();
}
};
}
use of io.quarkus.arc.deployment.BeanArchiveIndexBuildItem in project quarkus by quarkusio.
the class FunctionScannerBuildStep method scanFunctions.
@BuildStep
public void scanFunctions(BeanArchiveIndexBuildItem beanArchiveIndexBuildItem, BuildProducer<BytecodeTransformerBuildItem> transformers, BuildProducer<AnnotationsTransformerBuildItem> annotationsTransformer, BuildProducer<UnremovableBeanBuildItem> unremovableBeans, BuildProducer<ReflectiveClassBuildItem> reflectiveClass, BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchy, BuildProducer<FunctionBuildItem> functions) {
IndexView index = beanArchiveIndexBuildItem.getIndex();
Collection<AnnotationInstance> funqs = index.getAnnotations(FUNQ);
Set<ClassInfo> classes = new HashSet<>();
Set<String> classNames = new HashSet<>();
for (AnnotationInstance funqMethod : funqs) {
MethodInfo method = funqMethod.target().asMethod();
String className = method.declaringClass().name().toString();
classNames.add(className);
classes.add(method.declaringClass());
String methodName = method.name();
String functionName = null;
if (funqMethod.value() != null) {
functionName = funqMethod.value().asString();
}
if (functionName != null && functionName.isEmpty())
functionName = null;
functions.produce(new FunctionBuildItem(className, methodName, functionName));
String source = FunctionScannerBuildStep.class.getSimpleName() + " > " + method.declaringClass() + "[" + method + "]";
Type returnType = method.returnType();
if (returnType.kind() != Type.Kind.VOID) {
reflectiveHierarchy.produce(new ReflectiveHierarchyBuildItem.Builder().type(returnType).index(index).ignoreTypePredicate(IGNORE_TYPE_FOR_REFLECTION_PREDICATE).ignoreFieldPredicate(IGNORE_FIELD_FOR_REFLECTION_PREDICATE).ignoreMethodPredicate(IGNORE_METHOD_FOR_REFLECTION_PREDICATE).source(source).build());
}
for (short i = 0; i < method.parameters().size(); i++) {
Type parameterType = method.parameters().get(i);
if (!hasAnnotation(method, i, CONTEXT)) {
reflectiveHierarchy.produce(new ReflectiveHierarchyBuildItem.Builder().type(parameterType).index(index).ignoreTypePredicate(IGNORE_TYPE_FOR_REFLECTION_PREDICATE).ignoreFieldPredicate(IGNORE_FIELD_FOR_REFLECTION_PREDICATE).ignoreMethodPredicate(IGNORE_METHOD_FOR_REFLECTION_PREDICATE).source(source).build());
}
}
}
Set<ClassInfo> withoutDefaultCtor = new HashSet<>();
for (ClassInfo clazz : classes) {
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, clazz.name().toString()));
if (!clazz.hasNoArgsConstructor()) {
withoutDefaultCtor.add(clazz);
}
}
unremovableBeans.produce(new UnremovableBeanBuildItem(b -> classNames.contains(b.getBeanClass().toString())));
generateDefaultConstructors(transformers, withoutDefaultCtor);
// we need to use an annotation transformer here instead of an AdditionalBeanBuildItem because
// the use of the latter along with the BeanArchiveIndexBuildItem results in build cycles
annotationsTransformer.produce(new AnnotationsTransformerBuildItem(new AnnotationsTransformer() {
@Override
public boolean appliesTo(AnnotationTarget.Kind kind) {
return kind == AnnotationTarget.Kind.CLASS;
}
@Override
public void transform(TransformationContext transformationContext) {
ClassInfo clazz = transformationContext.getTarget().asClass();
if (!classes.contains(clazz))
return;
if (BuiltinScope.isDeclaredOn(clazz)) {
// nothing to do as the presence of a scope will automatically qualify the class as a bean
return;
}
Transformation transformation = transformationContext.transform();
transformation.add(BuiltinScope.DEPENDENT.getName());
if (clazz.classAnnotation(DotNames.TYPED) == null) {
// Add @Typed(MySubresource.class)
transformation.add(createTypedAnnotationInstance(clazz));
}
transformation.done();
}
}));
}
use of io.quarkus.arc.deployment.BeanArchiveIndexBuildItem in project quarkus by quarkusio.
the class ResteasyCommonProcessor method setupProviders.
@BuildStep
JaxrsProvidersToRegisterBuildItem setupProviders(BuildProducer<ReflectiveClassBuildItem> reflectiveClass, CombinedIndexBuildItem indexBuildItem, BeanArchiveIndexBuildItem beanArchiveIndexBuildItem, BuildProducer<UnremovableBeanBuildItem> unremovableBeans, List<ResteasyJaxrsProviderBuildItem> contributedProviderBuildItems, List<RestClientBuildItem> restClients, ResteasyConfigBuildItem resteasyConfig, Capabilities capabilities) throws Exception {
Set<String> contributedProviders = new HashSet<>();
for (ResteasyJaxrsProviderBuildItem contributedProviderBuildItem : contributedProviderBuildItems) {
contributedProviders.add(contributedProviderBuildItem.getName());
}
Set<String> annotatedProviders = new HashSet<>();
for (AnnotationInstance i : indexBuildItem.getIndex().getAnnotations(ResteasyDotNames.PROVIDER)) {
if (i.target().kind() == AnnotationTarget.Kind.CLASS) {
annotatedProviders.add(i.target().asClass().name().toString());
}
checkProperConfigAccessInProvider(i);
}
contributedProviders.addAll(annotatedProviders);
Set<String> availableProviders = new HashSet<>(ServiceUtil.classNamesNamedIn(getClass().getClassLoader(), "META-INF/services/" + Providers.class.getName()));
// this one is added manually in RESTEasy's ResteasyDeploymentImpl
availableProviders.add(ServerFormUrlEncodedProvider.class.getName());
MediaTypeMap<String> categorizedReaders = new MediaTypeMap<>();
MediaTypeMap<String> categorizedWriters = new MediaTypeMap<>();
MediaTypeMap<String> categorizedContextResolvers = new MediaTypeMap<>();
Set<String> otherProviders = new HashSet<>();
categorizeProviders(availableProviders, categorizedReaders, categorizedWriters, categorizedContextResolvers, otherProviders);
// add the other providers detected
Set<String> providersToRegister = new HashSet<>(otherProviders);
if (!capabilities.isPresent(Capability.VERTX) && !capabilities.isCapabilityWithPrefixPresent(Capability.RESTEASY_JSON)) {
boolean needJsonSupport = restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.CONSUMES) || restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.PRODUCES) || restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.RESTEASY_SSE_ELEMENT_TYPE) || restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.RESTEASY_PART_TYPE);
if (needJsonSupport) {
LOGGER.warn("Quarkus detected the need of REST JSON support but you have not provided the necessary JSON " + "extension for this. You can visit https://quarkus.io/guides/rest-json for more " + "information on how to set one.");
}
}
if (!capabilities.isPresent(Capability.RESTEASY_MUTINY)) {
String needsMutinyClasses = mutinySupportNeeded(indexBuildItem);
if (needsMutinyClasses != null) {
LOGGER.warn("Quarkus detected the need for Mutiny reactive programming support, however the quarkus-resteasy-mutiny extension " + "was not present. Reactive REST endpoints in your application that return Uni or Multi " + "will not function as you expect until you add this extension. Endpoints that need Mutiny are: " + needsMutinyClasses);
}
}
// we add a couple of default providers
providersToRegister.add(StringTextStar.class.getName());
providersToRegister.addAll(categorizedWriters.getPossible(MediaType.APPLICATION_JSON_TYPE));
IndexView index = indexBuildItem.getIndex();
IndexView beansIndex = beanArchiveIndexBuildItem.getIndex();
// find the providers declared in our services
boolean useBuiltinProviders = collectDeclaredProviders(restClients, resteasyConfig, providersToRegister, categorizedReaders, categorizedWriters, categorizedContextResolvers, index, beansIndex);
if (useBuiltinProviders) {
providersToRegister = new HashSet<>(contributedProviders);
providersToRegister.addAll(availableProviders);
} else {
providersToRegister.addAll(contributedProviders);
}
if (providersToRegister.contains("org.jboss.resteasy.plugins.providers.jsonb.JsonBindingProvider")) {
// This abstract one is also accessed directly via reflection
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, "org.jboss.resteasy.plugins.providers.jsonb.AbstractJsonBindingProvider"));
}
JaxrsProvidersToRegisterBuildItem result = new JaxrsProvidersToRegisterBuildItem(providersToRegister, contributedProviders, annotatedProviders, useBuiltinProviders);
// Providers that are also beans are unremovable
unremovableBeans.produce(new UnremovableBeanBuildItem(b -> result.getProviders().contains(b.getBeanClass().toString())));
return result;
}
use of io.quarkus.arc.deployment.BeanArchiveIndexBuildItem in project quarkus by quarkusio.
the class MessageBundleProcessor method processBundles.
@BuildStep
List<MessageBundleBuildItem> processBundles(BeanArchiveIndexBuildItem beanArchiveIndex, ApplicationArchivesBuildItem applicationArchivesBuildItem, BuildProducer<GeneratedClassBuildItem> generatedClasses, BeanRegistrationPhaseBuildItem beanRegistration, BuildProducer<BeanConfiguratorBuildItem> configurators, BuildProducer<MessageBundleMethodBuildItem> messageTemplateMethods, BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles, LocalesBuildTimeConfig locales) throws IOException {
IndexView index = beanArchiveIndex.getIndex();
Map<String, ClassInfo> found = new HashMap<>();
List<MessageBundleBuildItem> bundles = new ArrayList<>();
List<DotName> localizedInterfaces = new ArrayList<>();
List<Path> messageFiles = findMessageFiles(applicationArchivesBuildItem, watchedFiles);
// First collect all interfaces annotated with @MessageBundle
for (AnnotationInstance bundleAnnotation : index.getAnnotations(Names.BUNDLE)) {
if (bundleAnnotation.target().kind() == Kind.CLASS) {
ClassInfo bundleClass = bundleAnnotation.target().asClass();
if (Modifier.isInterface(bundleClass.flags())) {
AnnotationValue nameValue = bundleAnnotation.value();
String name = nameValue != null ? nameValue.asString() : MessageBundle.DEFAULT_NAME;
if (!Namespaces.isValidNamespace(name)) {
throw new MessageBundleException(String.format("Message bundle name [%s] declared on %s must be a valid namespace - the value can only consist of alphanumeric characters and underscores", name, bundleClass));
}
if (found.containsKey(name)) {
throw new MessageBundleException(String.format("Message bundle interface name conflict - [%s] is used for both [%s] and [%s]", name, bundleClass, found.get(name)));
}
found.put(name, bundleClass);
// Find localizations for each interface
String defaultLocale = getDefaultLocale(bundleAnnotation, locales);
List<ClassInfo> localized = new ArrayList<>();
for (ClassInfo implementor : index.getKnownDirectImplementors(bundleClass.name())) {
if (Modifier.isInterface(implementor.flags())) {
localized.add(implementor);
}
}
Map<String, ClassInfo> localeToInterface = new HashMap<>();
for (ClassInfo localizedInterface : localized) {
String locale = localizedInterface.classAnnotation(Names.LOCALIZED).value().asString();
if (defaultLocale.equals(locale)) {
throw new MessageBundleException(String.format("Locale of [%s] conflicts with the locale [%s] of the default message bundle [%s]", localizedInterface, locale, bundleClass));
}
ClassInfo previous = localeToInterface.put(locale, localizedInterface);
if (previous != null) {
throw new MessageBundleException(String.format("Cannot register [%s] - a localized message bundle interface exists for locale [%s]: %s", localizedInterface, locale, previous));
}
localizedInterfaces.add(localizedInterface.name());
}
// Find localized files
Map<String, Path> localeToFile = new HashMap<>();
// Message templates not specified by a localized interface are looked up in a localized file (merge candidate)
Map<String, Path> localeToMergeCandidate = new HashMap<>();
for (Path messageFile : messageFiles) {
String fileName = messageFile.getFileName().toString();
if (fileName.startsWith(name)) {
// msg_en.txt -> en
String locale = fileName.substring(fileName.indexOf('_') + 1, fileName.indexOf('.'));
ClassInfo localizedInterface = localeToInterface.get(locale);
if (defaultLocale.equals(locale) || localizedInterface != null) {
// both file and interface exist for one locale, therefore we need to merge them
Path previous = localeToMergeCandidate.put(locale, messageFile);
if (previous != null) {
throw new MessageBundleException(String.format("Cannot register [%s] - a localized file already exists for locale [%s]: [%s]", fileName, locale, previous.getFileName().toString()));
}
} else {
localeToFile.put(locale, messageFile);
}
}
}
bundles.add(new MessageBundleBuildItem(name, bundleClass, localeToInterface, localeToFile, localeToMergeCandidate, defaultLocale));
} else {
throw new MessageBundleException("@MessageBundle must be declared on an interface: " + bundleClass);
}
}
}
// Detect interfaces annotated with @Localized that don't extend a message bundle interface
for (AnnotationInstance localizedAnnotation : index.getAnnotations(Names.LOCALIZED)) {
if (localizedAnnotation.target().kind() == Kind.CLASS) {
ClassInfo localized = localizedAnnotation.target().asClass();
if (Modifier.isInterface(localized.flags())) {
if (!localizedInterfaces.contains(localized.name())) {
throw new MessageBundleException("A localized message bundle interface must extend a message bundle interface: " + localized);
}
} else {
throw new MessageBundleException("@Localized must be declared on an interface: " + localized);
}
}
}
// Generate implementations
// name -> impl class
Map<String, String> generatedImplementations = generateImplementations(bundles, generatedClasses, messageTemplateMethods);
// Register synthetic beans
for (MessageBundleBuildItem bundle : bundles) {
ClassInfo bundleInterface = bundle.getDefaultBundleInterface();
beanRegistration.getContext().configure(bundleInterface.name()).addType(bundle.getDefaultBundleInterface().name()).addQualifier(DotNames.DEFAULT).addQualifier().annotation(Names.LOCALIZED).addValue("value", getDefaultLocale(bundleInterface.classAnnotation(Names.BUNDLE), locales)).done().unremovable().scope(Singleton.class).creator(mc -> {
// Just create a new instance of the generated class
mc.returnValue(mc.newInstance(MethodDescriptor.ofConstructor(generatedImplementations.get(bundleInterface.name().toString()))));
}).done();
// Localized interfaces
for (ClassInfo localizedInterface : bundle.getLocalizedInterfaces().values()) {
beanRegistration.getContext().configure(localizedInterface.name()).addType(bundle.getDefaultBundleInterface().name()).addQualifier(localizedInterface.classAnnotation(Names.LOCALIZED)).unremovable().scope(Singleton.class).creator(mc -> {
// Just create a new instance of the generated class
mc.returnValue(mc.newInstance(MethodDescriptor.ofConstructor(generatedImplementations.get(localizedInterface.name().toString()))));
}).done();
}
// Localized files
for (Entry<String, Path> entry : bundle.getLocalizedFiles().entrySet()) {
beanRegistration.getContext().configure(bundle.getDefaultBundleInterface().name()).addType(bundle.getDefaultBundleInterface().name()).addQualifier().annotation(Names.LOCALIZED).addValue("value", entry.getKey()).done().unremovable().scope(Singleton.class).creator(mc -> {
// Just create a new instance of the generated class
mc.returnValue(mc.newInstance(MethodDescriptor.ofConstructor(generatedImplementations.get(entry.getValue().toString()))));
}).done();
}
}
return bundles;
}
use of io.quarkus.arc.deployment.BeanArchiveIndexBuildItem in project quarkus by vaadin.
the class VaadinQuarkusProcessor method mapVaadinServletPaths.
@BuildStep
void mapVaadinServletPaths(final BeanArchiveIndexBuildItem beanArchiveIndex, final BuildProducer<ServletBuildItem> servletProducer) {
final IndexView indexView = beanArchiveIndex.getIndex();
// Collect all VaadinServlet instances and remove QuarkusVaadinServlet
// and VaadinServlet from the list.
final Collection<ClassInfo> vaadinServlets = indexView.getAllKnownSubclasses(DotName.createSimple(VaadinServlet.class.getName())).stream().filter(servlet -> !servlet.name().toString().equals(QuarkusVaadinServlet.class.getName()) && !servlet.name().toString().equals(VaadinServlet.class.getName())).collect(Collectors.toList());
// If no VaadinServlet instances found register QuarkusVaadinServlet
if (vaadinServlets.isEmpty()) {
servletProducer.produce(ServletBuildItem.builder(QuarkusVaadinServlet.class.getName(), QuarkusVaadinServlet.class.getName()).addMapping("/*").setAsyncSupported(true).build());
} else {
registerUserServlets(servletProducer, vaadinServlets);
}
}
Aggregations