use of io.quarkus.gizmo.ClassCreator in project quarkus-github-app by quarkiverse.
the class GitHubAppProcessor method generateMultiplexers.
/**
* Multiplexers listen to the async events emitted by the dispatcher.
* <p>
* They are subclasses of the application classes listening to GitHub events through our annotations.
* <p>
* They are useful for several purposes:
* <ul>
* <li>A single application method can listen to multiple event types: the event types are qualifiers and CDI wouldn't allow
* that (only events matching all the qualifiers would be received by the application method). That's why this class is
* called a multiplexer: it will generate one method per event type and each generated method will delegate to the original
* method.</li>
* <li>The multiplexer also handles the resolution of config files.</li>
* <li>We can inject a properly configured instance of GitHub or DynamicGraphQLClient into the method.</li>
* </ul>
*/
private static void generateMultiplexers(ClassOutput beanClassOutput, DispatchingConfiguration dispatchingConfiguration, BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
for (Entry<DotName, TreeSet<EventDispatchingMethod>> eventDispatchingMethodsEntry : dispatchingConfiguration.getMethods().entrySet()) {
DotName declaringClassName = eventDispatchingMethodsEntry.getKey();
TreeSet<EventDispatchingMethod> eventDispatchingMethods = eventDispatchingMethodsEntry.getValue();
ClassInfo declaringClass = eventDispatchingMethods.iterator().next().getMethod().declaringClass();
reflectiveClasses.produce(new ReflectiveClassBuildItem(true, true, declaringClassName.toString()));
String multiplexerClassName = declaringClassName + "_Multiplexer";
reflectiveClasses.produce(new ReflectiveClassBuildItem(true, true, multiplexerClassName));
ClassCreator multiplexerClassCreator = ClassCreator.builder().classOutput(beanClassOutput).className(multiplexerClassName).superClass(declaringClassName.toString()).build();
multiplexerClassCreator.addAnnotation(Multiplexer.class);
if (!BuiltinScope.isDeclaredOn(declaringClass)) {
multiplexerClassCreator.addAnnotation(Singleton.class);
}
for (AnnotationInstance classAnnotation : declaringClass.classAnnotations()) {
multiplexerClassCreator.addAnnotation(classAnnotation);
}
// Copy the constructors
for (MethodInfo originalConstructor : declaringClass.constructors()) {
MethodCreator constructorCreator = multiplexerClassCreator.getMethodCreator(MethodDescriptor.ofConstructor(multiplexerClassName, originalConstructor.parameters().stream().map(t -> t.name().toString()).toArray(String[]::new)));
List<AnnotationInstance> originalMethodAnnotations = originalConstructor.annotations().stream().filter(ai -> ai.target().kind() == Kind.METHOD).collect(Collectors.toList());
for (AnnotationInstance originalMethodAnnotation : originalMethodAnnotations) {
constructorCreator.addAnnotation(originalMethodAnnotation);
}
Map<Short, List<AnnotationInstance>> originalConstructorParameterAnnotationMapping = originalConstructor.annotations().stream().filter(ai -> ai.target().kind() == Kind.METHOD_PARAMETER).collect(Collectors.groupingBy(ai -> ai.target().asMethodParameter().position()));
List<ResultHandle> parametersRh = new ArrayList<>();
for (short i = 0; i < originalConstructor.parameters().size(); i++) {
parametersRh.add(constructorCreator.getMethodParam(i));
AnnotatedElement parameterAnnotations = constructorCreator.getParameterAnnotations(i);
List<AnnotationInstance> originalConstructorParameterAnnotations = originalConstructorParameterAnnotationMapping.getOrDefault(i, Collections.emptyList());
for (AnnotationInstance originalConstructorParameterAnnotation : originalConstructorParameterAnnotations) {
parameterAnnotations.addAnnotation(originalConstructorParameterAnnotation);
}
}
constructorCreator.invokeSpecialMethod(MethodDescriptor.of(originalConstructor), constructorCreator.getThis(), parametersRh.toArray(ResultHandle[]::new));
constructorCreator.returnValue(null);
}
// Generate the multiplexed event dispatching methods
for (EventDispatchingMethod eventDispatchingMethod : eventDispatchingMethods) {
AnnotationInstance eventSubscriberInstance = eventDispatchingMethod.getEventSubscriberInstance();
MethodInfo originalMethod = eventDispatchingMethod.getMethod();
Map<Short, List<AnnotationInstance>> originalMethodParameterAnnotationMapping = originalMethod.annotations().stream().filter(ai -> ai.target().kind() == Kind.METHOD_PARAMETER).collect(Collectors.groupingBy(ai -> ai.target().asMethodParameter().position()));
// if the method already has an @Observes or @ObservesAsync annotation
if (originalMethod.hasAnnotation(DotNames.OBSERVES) || originalMethod.hasAnnotation(DotNames.OBSERVES_ASYNC)) {
LOG.warn("Methods listening to GitHub events may not be annotated with @Observes or @ObservesAsync. Offending method: " + originalMethod.declaringClass().name() + "#" + originalMethod);
}
List<String> parameterTypes = new ArrayList<>();
List<Type> originalMethodParameterTypes = originalMethod.parameters();
// detect the parameter that is a payload
short payloadParameterPosition = 0;
for (short i = 0; i < originalMethodParameterTypes.size(); i++) {
List<AnnotationInstance> parameterAnnotations = originalMethodParameterAnnotationMapping.getOrDefault(i, Collections.emptyList());
if (parameterAnnotations.stream().anyMatch(ai -> ai.name().equals(eventSubscriberInstance.name()))) {
payloadParameterPosition = i;
break;
}
}
short j = 0;
Map<Short, Short> parameterMapping = new HashMap<>();
for (short i = 0; i < originalMethodParameterTypes.size(); i++) {
List<AnnotationInstance> originalMethodAnnotations = originalMethodParameterAnnotationMapping.getOrDefault(i, Collections.emptyList());
if (originalMethodAnnotations.stream().anyMatch(ai -> CONFIG_FILE.equals(ai.name())) || GITHUB.equals(originalMethodParameterTypes.get(i).name()) || DYNAMIC_GRAPHQL_CLIENT.equals(originalMethodParameterTypes.get(i).name())) {
// if the parameter is annotated with @ConfigFile or is of type GitHub or DynamicGraphQLClient, we skip it
continue;
}
String parameterType;
if (i == payloadParameterPosition) {
parameterType = MultiplexedEvent.class.getName();
} else {
parameterType = originalMethodParameterTypes.get(i).name().toString();
}
parameterTypes.add(parameterType);
parameterMapping.put(i, j);
j++;
}
if (originalMethod.hasAnnotation(CONFIG_FILE)) {
parameterTypes.add(ConfigFileReader.class.getName());
}
MethodCreator methodCreator = multiplexerClassCreator.getMethodCreator(originalMethod.name() + "_" + HashUtil.sha1(eventSubscriberInstance.toString()), originalMethod.returnType().name().toString(), parameterTypes.toArray());
for (Type exceptionType : originalMethod.exceptions()) {
methodCreator.addException(exceptionType.name().toString());
}
ResultHandle[] parameterValues = new ResultHandle[originalMethod.parameters().size()];
// copy annotations except for @ConfigFile
for (short i = 0; i < originalMethodParameterTypes.size(); i++) {
List<AnnotationInstance> parameterAnnotations = originalMethodParameterAnnotationMapping.getOrDefault(i, Collections.emptyList());
if (parameterAnnotations.isEmpty()) {
continue;
}
// @ConfigFile elements are not in the mapping
Short generatedParameterIndex = parameterMapping.get(i);
if (generatedParameterIndex == null) {
continue;
}
AnnotatedElement generatedParameterAnnotations = methodCreator.getParameterAnnotations(generatedParameterIndex);
if (parameterAnnotations.stream().anyMatch(ai -> ai.name().equals(eventSubscriberInstance.name()))) {
generatedParameterAnnotations.addAnnotation(DotNames.OBSERVES_ASYNC.toString());
generatedParameterAnnotations.addAnnotation(eventSubscriberInstance);
} else {
for (AnnotationInstance annotationInstance : parameterAnnotations) {
generatedParameterAnnotations.addAnnotation(annotationInstance);
}
}
}
ResultHandle payloadRh = methodCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(MultiplexedEvent.class, "getPayload", GHEventPayload.class), methodCreator.getMethodParam(parameterMapping.get(payloadParameterPosition)));
// generate the code of the method
for (short originalMethodParameterIndex = 0; originalMethodParameterIndex < originalMethodParameterTypes.size(); originalMethodParameterIndex++) {
List<AnnotationInstance> parameterAnnotations = originalMethodParameterAnnotationMapping.getOrDefault(originalMethodParameterIndex, Collections.emptyList());
Short multiplexerMethodParameterIndex = parameterMapping.get(originalMethodParameterIndex);
if (originalMethodParameterIndex == payloadParameterPosition) {
parameterValues[originalMethodParameterIndex] = payloadRh;
} else if (GITHUB.equals(originalMethodParameterTypes.get(originalMethodParameterIndex).name())) {
parameterValues[originalMethodParameterIndex] = methodCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(MultiplexedEvent.class, "getGitHub", GitHub.class), methodCreator.getMethodParam(parameterMapping.get(payloadParameterPosition)));
} else if (DYNAMIC_GRAPHQL_CLIENT.equals(originalMethodParameterTypes.get(originalMethodParameterIndex).name())) {
parameterValues[originalMethodParameterIndex] = methodCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(MultiplexedEvent.class, "getGitHubGraphQLClient", DynamicGraphQLClient.class), methodCreator.getMethodParam(parameterMapping.get(payloadParameterPosition)));
} else if (parameterAnnotations.stream().anyMatch(ai -> ai.name().equals(CONFIG_FILE))) {
AnnotationInstance configFileAnnotationInstance = parameterAnnotations.stream().filter(ai -> ai.name().equals(CONFIG_FILE)).findFirst().get();
String configObjectType = originalMethodParameterTypes.get(originalMethodParameterIndex).name().toString();
boolean isOptional = false;
if (Optional.class.getName().equals(configObjectType)) {
if (originalMethodParameterTypes.get(originalMethodParameterIndex).kind() != Type.Kind.PARAMETERIZED_TYPE) {
throw new IllegalStateException("Optional is used but not parameterized for method " + originalMethod.declaringClass().name() + "#" + originalMethod);
}
isOptional = true;
configObjectType = originalMethodParameterTypes.get(originalMethodParameterIndex).asParameterizedType().arguments().get(0).name().toString();
}
// it's a config file, we will use the ConfigFileReader (last parameter of the method) and inject the result
ResultHandle configFileReaderRh = methodCreator.getMethodParam(parameterTypes.size() - 1);
ResultHandle ghRepositoryRh = methodCreator.invokeStaticMethod(MethodDescriptor.ofMethod(PayloadHelper.class, "getRepository", GHRepository.class, GHEventPayload.class), payloadRh);
ResultHandle configObject = methodCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(ConfigFileReader.class, "getConfigObject", Object.class, GHRepository.class, String.class, Class.class), configFileReaderRh, ghRepositoryRh, methodCreator.load(configFileAnnotationInstance.value().asString()), methodCreator.loadClass(configObjectType));
configObject = methodCreator.checkCast(configObject, configObjectType);
if (isOptional) {
configObject = methodCreator.invokeStaticMethod(MethodDescriptor.ofMethod(Optional.class, "ofNullable", Optional.class, Object.class), configObject);
}
parameterValues[originalMethodParameterIndex] = configObject;
} else {
parameterValues[originalMethodParameterIndex] = methodCreator.getMethodParam(multiplexerMethodParameterIndex);
}
}
ResultHandle returnValue = methodCreator.invokeVirtualMethod(originalMethod, methodCreator.getThis(), parameterValues);
methodCreator.returnValue(returnValue);
}
multiplexerClassCreator.close();
}
}
use of io.quarkus.gizmo.ClassCreator in project quarkus-github-app by quarkiverse.
the class GitHubAppProcessor method generateDispatcher.
/**
* The role of the dispatcher is to receive the CDI events emitted by the reactive route.
* <p>
* It parses the raw payload into the appropriate {@link GHEventPayload} and then emit
* an async CDI event with a MultiplexedEvent containing the payload instance,
* the GitHub instance and the DynamicGraphQLClient instance if needed.
* <p>
* It only generates code for the GitHub events actually listened to by the application.
*/
private static void generateDispatcher(ClassOutput beanClassOutput, CombinedIndexBuildItem combinedIndex, LaunchModeBuildItem launchMode, DispatchingConfiguration dispatchingConfiguration, BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
String dispatcherClassName = GitHubEvent.class.getName() + "DispatcherImpl";
reflectiveClasses.produce(new ReflectiveClassBuildItem(true, true, dispatcherClassName));
ClassCreator dispatcherClassCreator = ClassCreator.builder().classOutput(beanClassOutput).className(dispatcherClassName).build();
dispatcherClassCreator.addAnnotation(Singleton.class);
FieldCreator eventFieldCreator = dispatcherClassCreator.getFieldCreator(EVENT_EMITTER_FIELD, Event.class);
eventFieldCreator.addAnnotation(Inject.class);
eventFieldCreator.setModifiers(Modifier.PROTECTED);
FieldCreator gitHubServiceFieldCreator = dispatcherClassCreator.getFieldCreator(GITHUB_SERVICE_FIELD, GitHubService.class);
gitHubServiceFieldCreator.addAnnotation(Inject.class);
gitHubServiceFieldCreator.setModifiers(Modifier.PROTECTED);
MethodCreator dispatchMethodCreator = dispatcherClassCreator.getMethodCreator("dispatch", void.class, GitHubEvent.class);
dispatchMethodCreator.setModifiers(Modifier.PUBLIC);
dispatchMethodCreator.getParameterAnnotations(0).addAnnotation(DotNames.OBSERVES.toString());
ResultHandle gitHubEventRh = dispatchMethodCreator.getMethodParam(0);
ResultHandle installationIdRh = dispatchMethodCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(GitHubEvent.class, "getInstallationId", Long.class), gitHubEventRh);
ResultHandle dispatchedEventRh = dispatchMethodCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(GitHubEvent.class, "getEvent", String.class), gitHubEventRh);
ResultHandle dispatchedActionRh = dispatchMethodCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(GitHubEvent.class, "getAction", String.class), gitHubEventRh);
ResultHandle dispatchedPayloadRh = dispatchMethodCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(GitHubEvent.class, "getPayload", String.class), gitHubEventRh);
TryBlock tryBlock = dispatchMethodCreator.tryBlock();
ResultHandle gitHubRh = tryBlock.invokeVirtualMethod(MethodDescriptor.ofMethod(GitHubService.class, "getInstallationClient", GitHub.class, Long.class), tryBlock.readInstanceField(FieldDescriptor.of(dispatcherClassCreator.getClassName(), GITHUB_SERVICE_FIELD, GitHubService.class), tryBlock.getThis()), installationIdRh);
ResultHandle gitHubGraphQLClientRh = tryBlock.loadNull();
if (dispatchingConfiguration.requiresGraphQLClient()) {
gitHubGraphQLClientRh = tryBlock.invokeVirtualMethod(MethodDescriptor.ofMethod(GitHubService.class, "getInstallationGraphQLClient", DynamicGraphQLClient.class, Long.class), tryBlock.readInstanceField(FieldDescriptor.of(dispatcherClassCreator.getClassName(), GITHUB_SERVICE_FIELD, GitHubService.class), tryBlock.getThis()), installationIdRh);
}
for (EventDispatchingConfiguration eventDispatchingConfiguration : dispatchingConfiguration.getEventConfigurations().values()) {
ResultHandle eventRh = tryBlock.load(eventDispatchingConfiguration.getEvent());
String payloadType = eventDispatchingConfiguration.getPayloadType();
BytecodeCreator eventMatchesCreator = tryBlock.ifTrue(tryBlock.invokeVirtualMethod(MethodDescriptors.OBJECT_EQUALS, eventRh, dispatchedEventRh)).trueBranch();
ResultHandle payloadInstanceRh = eventMatchesCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(GitHub.class, "parseEventPayload", GHEventPayload.class, Reader.class, Class.class), gitHubRh, eventMatchesCreator.newInstance(MethodDescriptor.ofConstructor(StringReader.class, String.class), dispatchedPayloadRh), eventMatchesCreator.loadClass(payloadType));
ResultHandle multiplexedEventRh = eventMatchesCreator.newInstance(MethodDescriptor.ofConstructor(MultiplexedEvent.class, GHEventPayload.class, GitHub.class, DynamicGraphQLClient.class), payloadInstanceRh, gitHubRh, gitHubGraphQLClientRh);
for (Entry<String, EventAnnotation> eventAnnotationEntry : eventDispatchingConfiguration.getEventAnnotations().entrySet()) {
String action = eventAnnotationEntry.getKey();
EventAnnotation eventAnnotation = eventAnnotationEntry.getValue();
Class<?>[] literalParameterTypes = new Class<?>[eventAnnotation.getValues().size()];
Arrays.fill(literalParameterTypes, String.class);
List<ResultHandle> literalParameters = new ArrayList<>();
ResultHandle annotationLiteralRh = eventMatchesCreator.newInstance(MethodDescriptor.ofConstructor(getLiteralClassName(eventAnnotation.getName()), (Object[]) literalParameterTypes), literalParameters.toArray(ResultHandle[]::new));
ResultHandle annotationLiteralArrayRh = eventMatchesCreator.newArray(Annotation.class, 1);
eventMatchesCreator.writeArrayValue(annotationLiteralArrayRh, 0, annotationLiteralRh);
if (Actions.ALL.equals(action)) {
fireAsyncAction(eventMatchesCreator, launchMode.getLaunchMode(), dispatcherClassCreator.getClassName(), gitHubEventRh, multiplexedEventRh, annotationLiteralArrayRh);
} else {
BytecodeCreator actionMatchesCreator = eventMatchesCreator.ifTrue(eventMatchesCreator.invokeVirtualMethod(MethodDescriptors.OBJECT_EQUALS, eventMatchesCreator.load(action), dispatchedActionRh)).trueBranch();
fireAsyncAction(actionMatchesCreator, launchMode.getLaunchMode(), dispatcherClassCreator.getClassName(), gitHubEventRh, multiplexedEventRh, annotationLiteralArrayRh);
}
}
}
CatchBlockCreator catchBlockCreator = tryBlock.addCatch(Throwable.class);
catchBlockCreator.invokeVirtualMethod(MethodDescriptor.ofMethod(ErrorHandlerBridgeFunction.class, "apply", Void.class, Throwable.class), catchBlockCreator.newInstance(MethodDescriptor.ofConstructor(ErrorHandlerBridgeFunction.class, GitHubEvent.class), gitHubEventRh), catchBlockCreator.getCaughtException());
dispatchMethodCreator.returnValue(null);
dispatcherClassCreator.close();
}
use of io.quarkus.gizmo.ClassCreator in project quarkus-github-app by quarkiverse.
the class GitHubAppProcessor method generateAnnotationLiterals.
private static void generateAnnotationLiterals(ClassOutput classOutput, DispatchingConfiguration dispatchingConfiguration) {
for (EventDispatchingConfiguration eventDispatchingConfiguration : dispatchingConfiguration.getEventConfigurations().values()) {
for (EventAnnotationLiteral eventAnnotationLiteral : eventDispatchingConfiguration.getEventAnnotationLiterals()) {
String literalClassName = getLiteralClassName(eventAnnotationLiteral.getName());
String signature = String.format("Ljavax/enterprise/util/AnnotationLiteral<L%1$s;>;L%1$s;", eventAnnotationLiteral.getName().toString().replace('.', '/'));
ClassCreator literalClassCreator = ClassCreator.builder().classOutput(classOutput).className(literalClassName).signature(signature).superClass(AnnotationLiteral.class).interfaces(eventAnnotationLiteral.getName().toString()).build();
Class<?>[] parameterTypes = new Class<?>[eventAnnotationLiteral.getAttributes().size()];
Arrays.fill(parameterTypes, String.class);
MethodCreator constructorCreator = literalClassCreator.getMethodCreator("<init>", "V", (Object[]) parameterTypes);
constructorCreator.invokeSpecialMethod(MethodDescriptor.ofConstructor(AnnotationLiteral.class), constructorCreator.getThis());
for (int i = 0; i < eventAnnotationLiteral.getAttributes().size(); i++) {
constructorCreator.writeInstanceField(FieldDescriptor.of(literalClassName, eventAnnotationLiteral.getAttributes().get(i), String.class), constructorCreator.getThis(), constructorCreator.getMethodParam(i));
constructorCreator.setModifiers(Modifier.PUBLIC);
}
constructorCreator.returnValue(null);
for (String attribute : eventAnnotationLiteral.getAttributes()) {
// we only support String for now
literalClassCreator.getFieldCreator(attribute, String.class).setModifiers(Modifier.PRIVATE);
MethodCreator getterCreator = literalClassCreator.getMethodCreator(attribute, String.class);
getterCreator.setModifiers(Modifier.PUBLIC);
getterCreator.returnValue(getterCreator.readInstanceField(FieldDescriptor.of(literalClassName, attribute, String.class), getterCreator.getThis()));
}
literalClassCreator.close();
}
}
}
use of io.quarkus.gizmo.ClassCreator in project quarkus-github-action by quarkiverse.
the class GitHubActionProcessor method generateActionMain.
/**
* This method generates the <code>@QuarkusMain</code> class.
* <p>
* It emits the GitHub events as CDI events that will then be caught by the multiplexers.
*/
private static void generateActionMain(ClassOutput beanClassOutput, CombinedIndexBuildItem combinedIndex, LaunchModeBuildItem launchMode, DispatchingConfiguration dispatchingConfiguration, BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
String gitHubEventHandlerClassName = GitHubEventHandler.class.getName() + "Impl";
reflectiveClasses.produce(new ReflectiveClassBuildItem(true, true, gitHubEventHandlerClassName));
ClassCreator gitHubEventHandlerClassCreator = ClassCreator.builder().classOutput(beanClassOutput).className(gitHubEventHandlerClassName).interfaces(GitHubEventHandler.class).build();
gitHubEventHandlerClassCreator.addAnnotation(Singleton.class);
FieldCreator eventFieldCreator = gitHubEventHandlerClassCreator.getFieldCreator(EVENT_EMITTER_FIELD, Event.class);
eventFieldCreator.addAnnotation(Inject.class);
eventFieldCreator.setModifiers(Modifier.PROTECTED);
MethodCreator handleMethodCreator = gitHubEventHandlerClassCreator.getMethodCreator("handle", void.class, GitHubEvent.class);
handleMethodCreator.setModifiers(Modifier.PUBLIC);
ResultHandle gitHubEventRh = handleMethodCreator.getMethodParam(0);
ResultHandle dispatchedNameRh = handleMethodCreator.invokeVirtualMethod(GITHUB_EVENT_GET_NAME, gitHubEventRh);
ResultHandle dispatchedEventRh = handleMethodCreator.invokeVirtualMethod(GITHUB_EVENT_GET_EVENT, gitHubEventRh);
ResultHandle dispatchedActionRh = handleMethodCreator.invokeVirtualMethod(GITHUB_EVENT_GET_EVENT_ACTION, gitHubEventRh);
for (Entry<String, Map<String, ActionDispatchingConfiguration>> actionConfigurationEntry : dispatchingConfiguration.getActionConfigurations().entrySet()) {
String name = actionConfigurationEntry.getKey();
Map<String, ActionDispatchingConfiguration> actionConfiguration = actionConfigurationEntry.getValue();
BytecodeCreator nameMatchesCreator = handleMethodCreator.ifTrue(handleMethodCreator.invokeVirtualMethod(MethodDescriptors.OBJECT_EQUALS, handleMethodCreator.load(name), dispatchedNameRh)).trueBranch();
ResultHandle actionAnnotationLiteralRh = nameMatchesCreator.newInstance(MethodDescriptor.ofConstructor(ActionLiteral.class, String.class), new ResultHandle[] { nameMatchesCreator.load(name) });
for (Entry<String, ActionDispatchingConfiguration> eventConfigurationEntry : actionConfiguration.entrySet()) {
String event = eventConfigurationEntry.getKey();
ActionDispatchingConfiguration eventDispatchingConfiguration = eventConfigurationEntry.getValue();
if (EventDefinition.ALL.equals(event)) {
ResultHandle annotationLiteralArrayRh = nameMatchesCreator.newArray(Annotation.class, 1);
nameMatchesCreator.writeArrayValue(annotationLiteralArrayRh, 0, actionAnnotationLiteralRh);
fireEvent(nameMatchesCreator, gitHubEventHandlerClassCreator.getClassName(), gitHubEventRh, annotationLiteralArrayRh);
continue;
}
BytecodeCreator eventMatchesCreator = nameMatchesCreator.ifTrue(nameMatchesCreator.invokeVirtualMethod(MethodDescriptors.OBJECT_EQUALS, nameMatchesCreator.load(event), dispatchedEventRh)).trueBranch();
for (Entry<String, EventAnnotation> eventAnnotationEntry : eventDispatchingConfiguration.getEventAnnotations().entrySet()) {
String action = eventAnnotationEntry.getKey();
EventAnnotation eventAnnotation = eventAnnotationEntry.getValue();
Class<?>[] literalParameterTypes = new Class<?>[eventAnnotation.getValues().size()];
Arrays.fill(literalParameterTypes, String.class);
List<ResultHandle> literalParameters = new ArrayList<>();
ResultHandle eventAnnotationLiteralRh = eventMatchesCreator.newInstance(MethodDescriptor.ofConstructor(getLiteralClassName(eventAnnotation.getName()), (Object[]) literalParameterTypes), literalParameters.toArray(ResultHandle[]::new));
ResultHandle annotationLiteralArrayRh = eventMatchesCreator.newArray(Annotation.class, 2);
eventMatchesCreator.writeArrayValue(annotationLiteralArrayRh, 0, actionAnnotationLiteralRh);
eventMatchesCreator.writeArrayValue(annotationLiteralArrayRh, 1, eventAnnotationLiteralRh);
if (Actions.ALL.equals(action)) {
fireEvent(eventMatchesCreator, gitHubEventHandlerClassCreator.getClassName(), gitHubEventRh, annotationLiteralArrayRh);
} else {
BytecodeCreator actionMatchesCreator = eventMatchesCreator.ifTrue(eventMatchesCreator.invokeVirtualMethod(MethodDescriptors.OBJECT_EQUALS, eventMatchesCreator.load(action), dispatchedActionRh)).trueBranch();
fireEvent(actionMatchesCreator, gitHubEventHandlerClassCreator.getClassName(), gitHubEventRh, annotationLiteralArrayRh);
}
}
}
}
handleMethodCreator.returnValue(null);
gitHubEventHandlerClassCreator.close();
}
use of io.quarkus.gizmo.ClassCreator in project quarkus-github-action by quarkiverse.
the class GitHubActionProcessor method generateAnnotationLiterals.
private static void generateAnnotationLiterals(ClassOutput classOutput, DispatchingConfiguration dispatchingConfiguration) {
for (ActionDispatchingConfiguration eventDispatchingConfiguration : dispatchingConfiguration.getActionDispatchingConfigurations()) {
for (EventAnnotationLiteral eventAnnotationLiteral : eventDispatchingConfiguration.getEventAnnotationLiterals()) {
String literalClassName = getLiteralClassName(eventAnnotationLiteral.getName());
String signature = String.format("Ljavax/enterprise/util/AnnotationLiteral<L%1$s;>;L%1$s;", eventAnnotationLiteral.getName().toString().replace('.', '/'));
ClassCreator literalClassCreator = ClassCreator.builder().classOutput(classOutput).className(literalClassName).signature(signature).superClass(AnnotationLiteral.class).interfaces(eventAnnotationLiteral.getName().toString()).build();
Class<?>[] parameterTypes = new Class<?>[eventAnnotationLiteral.getAttributes().size()];
Arrays.fill(parameterTypes, String.class);
MethodCreator constructorCreator = literalClassCreator.getMethodCreator("<init>", "V", (Object[]) parameterTypes);
constructorCreator.invokeSpecialMethod(MethodDescriptor.ofConstructor(AnnotationLiteral.class), constructorCreator.getThis());
for (int i = 0; i < eventAnnotationLiteral.getAttributes().size(); i++) {
constructorCreator.writeInstanceField(FieldDescriptor.of(literalClassName, eventAnnotationLiteral.getAttributes().get(i), String.class), constructorCreator.getThis(), constructorCreator.getMethodParam(i));
constructorCreator.setModifiers(Modifier.PUBLIC);
}
constructorCreator.returnValue(null);
for (String attribute : eventAnnotationLiteral.getAttributes()) {
// we only support String for now
literalClassCreator.getFieldCreator(attribute, String.class).setModifiers(Modifier.PRIVATE);
MethodCreator getterCreator = literalClassCreator.getMethodCreator(attribute, String.class);
getterCreator.setModifiers(Modifier.PUBLIC);
getterCreator.returnValue(getterCreator.readInstanceField(FieldDescriptor.of(literalClassName, attribute, String.class), getterCreator.getThis()));
}
literalClassCreator.close();
}
}
}
Aggregations