Java Code Examples for org.jboss.jandex.MethodInfo#parameters()

The following examples show how to use org.jboss.jandex.MethodInfo#parameters() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ClientServiceFactory.java    From thorntail with Apache License 2.0 6 votes vote down vote up
static String buildMethodDef(MethodInfo method) {
    StringBuilder builder = new StringBuilder();

    // Method Parameters
    builder.append("(");
    for (org.jboss.jandex.Type type : method.parameters()) {
        builder.append(buildTypeDef(type.name().toString()));
    }
    builder.append(")");

    // Method Return Type
    if (method.returnType().kind().equals(org.jboss.jandex.Type.Kind.VOID)) {
        builder.append("V");
    } else {
        builder.append(buildTypeDef(method.returnType().name().toString()));
    }

    return builder.toString();
}
 
Example 2
Source File: AsmUtil.java    From quarkus with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the Java bytecode signature of a given Jandex MethodInfo using the given type argument mappings.
 * For example, given this method:
 * 
 * <pre>
 * {@code
 * public class Foo<T> {
 *  public <R> List<R> method(int a, T t){...} 
 * }
 * }
 * </pre>
 * 
 * This will return <tt>&lt;R:Ljava/lang/Object;>(ILjava/lang/Integer;)Ljava/util/List&lt;TR;>;</tt> if
 * your {@code typeArgMapper} contains {@code T=Ljava/lang/Integer;}.
 * 
 * @param method the method you want the signature for.
 * @param typeArgMapper a mapping between type argument names and their bytecode signature.
 * @return a bytecode signature for that method.
 */
public static String getSignature(MethodInfo method, Function<String, String> typeArgMapper) {
    List<Type> parameters = method.parameters();

    StringBuilder signature = new StringBuilder("");
    for (TypeVariable typeVariable : method.typeParameters()) {
        if (signature.length() == 0)
            signature.append("<");
        else
            signature.append(",");
        signature.append(typeVariable.identifier()).append(":");
        // FIXME: only use the first bound
        toSignature(signature, typeVariable.bounds().get(0), typeArgMapper, false);
    }
    if (signature.length() > 0)
        signature.append(">");
    signature.append("(");
    for (Type type : parameters) {
        toSignature(signature, type, typeArgMapper, false);
    }
    signature.append(")");
    toSignature(signature, method.returnType(), typeArgMapper, false);
    return signature.toString();
}
 
Example 3
Source File: InterceptedStaticMethodsProcessor.java    From quarkus with Apache License 2.0 6 votes vote down vote up
private void implementForward(ClassCreator initializer,
        InterceptedStaticMethodBuildItem interceptedStaticMethod) {
    MethodInfo method = interceptedStaticMethod.getMethod();
    List<Type> params = method.parameters();
    Object[] paramTypes = new String[params.size()];
    for (int i = 0; i < paramTypes.length; ++i) {
        paramTypes[i] = DescriptorUtils.typeToString(params.get(i));
    }
    MethodCreator forward = initializer
            .getMethodCreator(interceptedStaticMethod.getHash(), DescriptorUtils.typeToString(method.returnType()),
                    paramTypes)
            .setModifiers(ACC_PUBLIC | ACC_FINAL | ACC_STATIC);
    ResultHandle argArray = forward.newArray(Object.class, params.size());
    for (int i = 0; i < params.size(); i++) {
        forward.writeArrayValue(argArray, i, forward.getMethodParam(i));
    }
    ResultHandle ret = forward.invokeStaticMethod(INTERCEPTED_STATIC_METHODS_AROUND_INVOKE,
            forward.load(interceptedStaticMethod.getHash()), argArray);
    forward.returnValue(ret);
}
 
Example 4
Source File: VertxWebProcessor.java    From quarkus with Apache License 2.0 6 votes vote down vote up
private void validateRouteMethod(BeanInfo bean, MethodInfo method, DotName[] validParamTypes) {
    if (!method.returnType().kind().equals(Type.Kind.VOID)) {
        throw new IllegalStateException(
                String.format("Route handler business method must return void [method: %s, bean: %s]", method, bean));
    }
    List<Type> params = method.parameters();
    boolean hasInvalidParam = true;
    if (params.size() == 1) {
        DotName paramTypeName = params.get(0).name();
        for (DotName type : validParamTypes) {
            if (type.equals(paramTypeName)) {
                hasInvalidParam = false;
            }
        }
    }
    if (hasInvalidParam) {
        throw new IllegalStateException(String.format(
                "Route business method must accept exactly one parameter of type %s: %s [method: %s, bean: %s]",
                validParamTypes, params, method, bean));
    }
}
 
Example 5
Source File: VertxProcessor.java    From quarkus with Apache License 2.0 6 votes vote down vote up
@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(
                            "Event consumer business method must accept exactly one parameter: %s [method: %s, bean:%s",
                            params, method, bean));
                }
                messageConsumerBusinessMethods
                        .produce(new EventConsumerBusinessMethodItem(bean, method, consumeEvent));
                LOGGER.debugf("Found event consumer business method %s declared on %s", method, bean);
            }
        }
    }
}
 
Example 6
Source File: EventBusCodecProcessor.java    From quarkus with Apache License 2.0 6 votes vote down vote up
private static Type extractPayloadTypeFromParameter(MethodInfo method) {
    List<Type> parameters = method.parameters();
    if (parameters.isEmpty()) {
        return null;
    }
    Type param = method.parameters().get(0);
    if (param.kind() == Type.Kind.CLASS) {
        return param;
    } else if (param.kind() == Type.Kind.PARAMETERIZED_TYPE) {
        ParameterizedType parameterType = param.asParameterizedType();
        if (isMessageClass(parameterType) && !parameterType.arguments().isEmpty()) {
            return parameterType.arguments().get(0);
        } else {
            return parameterType;
        }
    }
    return null;
}
 
Example 7
Source File: AnnotationScanner.java    From smallrye-open-api with Apache License 2.0 5 votes vote down vote up
/**
 * Go through the method parameters looking for one that is not annotated with a jax-rs/spring
 * annotation.That will be the one that is the request body.
 * 
 * @param method MethodInfo
 * @param extensions available extensions
 * @return Type
 */
default Type getRequestBodyParameterClassType(MethodInfo method, List<AnnotationScannerExtension> extensions) {
    List<Type> methodParams = method.parameters();
    if (methodParams.isEmpty()) {
        return null;
    }
    for (short i = 0; i < methodParams.size(); i++) {
        List<AnnotationInstance> parameterAnnotations = JandexUtil.getParameterAnnotations(method, i);
        if (parameterAnnotations.isEmpty()
                || !containsScannerAnnotations(parameterAnnotations, extensions)) {
            return methodParams.get(i);
        }
    }
    return null;
}
 
Example 8
Source File: TypeUtil.java    From serianalyzer with GNU General Public License v3.0 5 votes vote down vote up
/**
 * @param i
 * @return
 * @throws SerianalyzerException
 */
static String makeSignature ( MethodInfo i, boolean fix ) throws SerianalyzerException {

    StringBuilder sb = new StringBuilder();
    sb.append('(');
    ClassInfo declaringImpl = i.declaringClass();
    if ( fix && "<init>".equals(i.name()) && declaringImpl.nestingType() == NestingType.INNER ) { //$NON-NLS-1$
        // there seems to be some sort of bug, missing the the outer instance parameter in the constructor
        if ( !Modifier.isStatic(declaringImpl.flags()) ) {
            org.jboss.jandex.Type enclosingClass = org.jboss.jandex.Type.create(declaringImpl.enclosingClass(), Kind.CLASS);
            org.jboss.jandex.Type firstArg = i.parameters().size() > 0 ? i.parameters().get(0) : null;
            if ( firstArg instanceof TypeVariable ) {
                firstArg = firstArg.asTypeVariable().bounds().get(0);
            }
            if ( firstArg == null || !firstArg.equals(enclosingClass) ) {
                sb.append(toString(enclosingClass));
            }
        }
    }

    for ( org.jboss.jandex.Type p : i.parameters() ) {
        sb.append(toString(p));
    }
    sb.append(')');
    sb.append(toString(i.returnType()));
    return sb.toString();
}
 
Example 9
Source File: SchedulerProcessor.java    From quarkus with Apache License 2.0 5 votes vote down vote up
@BuildStep
void validateScheduledBusinessMethods(SchedulerConfig config, List<ScheduledBusinessMethodItem> scheduledMethods,
        ValidationPhaseBuildItem validationPhase, BuildProducer<ValidationErrorBuildItem> validationErrors) {
    List<Throwable> errors = new ArrayList<>();
    Map<String, AnnotationInstance> encounteredIdentities = new HashMap<>();

    for (ScheduledBusinessMethodItem scheduledMethod : scheduledMethods) {
        MethodInfo method = scheduledMethod.getMethod();

        // Validate method params and return type
        List<Type> params = method.parameters();
        if (params.size() > 1
                || (params.size() == 1 && !params.get(0).equals(SCHEDULED_EXECUTION_TYPE))) {
            errors.add(new IllegalStateException(String.format(
                    "Invalid scheduled business method parameters %s [method: %s, bean: %s]", params,
                    method, scheduledMethod.getBean())));
        }
        if (!method.returnType().kind().equals(Type.Kind.VOID)) {
            errors.add(new IllegalStateException(
                    String.format("Scheduled business method must return void [method: %s, bean: %s]",
                            method, scheduledMethod.getBean())));
        }
        // Validate cron() and every() expressions
        CronParser parser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(config.cronType));
        for (AnnotationInstance scheduled : scheduledMethod.getSchedules()) {
            Throwable error = validateScheduled(parser, scheduled, encounteredIdentities);
            if (error != null) {
                errors.add(error);
            }
        }
    }

    if (!errors.isEmpty()) {
        validationErrors.produce(new ValidationErrorBuildItem(errors));
    }
}
 
Example 10
Source File: InterceptedStaticMethodsProcessor.java    From quarkus with Apache License 2.0 5 votes vote down vote up
private ResultHandle createForwardingFunction(MethodCreator init, ClassInfo target, MethodInfo method) {
    // Forwarding function
    // Function<InvocationContext, Object> forward = ctx -> Foo.interceptMe_original((java.lang.String)ctx.getParameters()[0])
    FunctionCreator func = init.createFunction(Function.class);
    BytecodeCreator funcBytecode = func.getBytecode();
    List<Type> paramTypes = method.parameters();
    ResultHandle[] paramHandles;
    String[] params;
    if (paramTypes.isEmpty()) {
        paramHandles = new ResultHandle[0];
        params = new String[0];
    } else {
        paramHandles = new ResultHandle[paramTypes.size()];
        ResultHandle ctxHandle = funcBytecode.getMethodParam(0);
        ResultHandle ctxParamsHandle = funcBytecode.invokeInterfaceMethod(
                MethodDescriptor.ofMethod(InvocationContext.class, "getParameters", Object[].class),
                ctxHandle);
        // autoboxing is handled inside Gizmo
        for (int i = 0; i < paramHandles.length; i++) {
            paramHandles[i] = funcBytecode.readArrayValue(ctxParamsHandle, i);
        }
        params = new String[paramTypes.size()];
        for (int i = 0; i < paramTypes.size(); i++) {
            params[i] = paramTypes.get(i).name().toString();
        }
    }
    ResultHandle ret = funcBytecode.invokeStaticMethod(
            MethodDescriptor.ofMethod(target.name().toString(), method.name() + ORGINAL_METHOD_COPY_SUFFIX,
                    method.returnType().name().toString(),
                    params),
            paramHandles);
    if (ret == null) {
        funcBytecode.returnValue(funcBytecode.loadNull());
    } else {
        funcBytecode.returnValue(ret);
    }
    return func.getInstance();
}
 
Example 11
Source File: GenerationUtil.java    From quarkus with Apache License 2.0 5 votes vote down vote up
static MethodDescriptor toMethodDescriptor(String generatedClassName, MethodInfo methodInfo) {
    final List<String> parameterTypesStr = new ArrayList<>();
    for (Type parameter : methodInfo.parameters()) {
        parameterTypesStr.add(parameter.name().toString());
    }
    return MethodDescriptor.ofMethod(generatedClassName, methodInfo.name(), methodInfo.returnType().name().toString(),
            parameterTypesStr.toArray(new String[0]));
}
 
Example 12
Source File: ControllerAdviceAbstractExceptionMapperGenerator.java    From quarkus with Apache License 2.0 5 votes vote down vote up
ControllerAdviceAbstractExceptionMapperGenerator(MethodInfo controllerAdviceMethod, DotName exceptionDotName,
        ClassOutput classOutput, TypesUtil typesUtil) {
    super(exceptionDotName, classOutput);
    this.controllerAdviceMethod = controllerAdviceMethod;
    this.typesUtil = typesUtil;

    this.returnType = controllerAdviceMethod.returnType();
    this.parameterTypes = controllerAdviceMethod.parameters();
    this.declaringClassName = controllerAdviceMethod.declaringClass().name().toString();
}
 
Example 13
Source File: QuteProcessor.java    From quarkus with Apache License 2.0 4 votes vote down vote up
/**
 * Find a non-static non-synthetic method with the given name, matching number of params and assignable parameter types.
 * 
 * @param virtualMethod
 * @param clazz
 * @param expression
 * @param index
 * @param templateIdToPathFun
 * @param results
 * @return the method or null
 */
private AnnotationTarget findMethod(VirtualMethodPart virtualMethod, ClassInfo clazz, Expression expression,
        IndexView index, Function<String, String> templateIdToPathFun, Map<String, Match> results) {
    while (clazz != null) {
        for (MethodInfo method : clazz.methods()) {
            if (Modifier.isPublic(method.flags()) && !Modifier.isStatic(method.flags())
                    && !ValueResolverGenerator.isSynthetic(method.flags())
                    && method.name().equals(virtualMethod.getName())) {
                boolean isVarArgs = ValueResolverGenerator.isVarArgs(method);
                List<Type> parameters = method.parameters();
                int lastParamIdx = parameters.size() - 1;

                if (isVarArgs) {
                    // For varargs methods match the minimal number of params
                    if (lastParamIdx > virtualMethod.getParameters().size()) {
                        continue;
                    }
                } else {
                    if (virtualMethod.getParameters().size() != parameters.size()) {
                        // Number of params must be equal
                        continue;
                    }
                }

                // Check parameter types if available
                boolean matches = true;
                byte idx = 0;

                for (Expression param : virtualMethod.getParameters()) {
                    Match result = results.get(param.toOriginalString());
                    if (result != null && !result.isEmpty()) {
                        // Type info available - validate parameter type
                        Type paramType;
                        if (isVarArgs && idx >= lastParamIdx) {
                            // Replace the type for varargs methods
                            paramType = parameters.get(lastParamIdx).asArrayType().component();
                        } else {
                            paramType = parameters.get(idx);
                        }
                        if (!Types.isAssignableFrom(result.type,
                                paramType, index)) {
                            matches = false;
                            break;
                        }
                    } else {
                        LOGGER.debugf(
                                "Type info not available - skip validation for parameter [%s] of method [%s] for expression [%s] in template [%s] on line %s",
                                method.parameterName(idx),
                                method.declaringClass().name() + "#" + method,
                                expression.toOriginalString(),
                                templateIdToPathFun.apply(expression.getOrigin().getTemplateId()),
                                expression.getOrigin().getLine());
                    }
                    idx++;
                }
                return matches ? method : null;
            }
        }
        DotName superName = clazz.superName();
        if (superName == null || DotNames.OBJECT.equals(superName)) {
            clazz = null;
        } else {
            clazz = index.getClassByName(clazz.superName());
        }
    }
    return null;
}
 
Example 14
Source File: SchedulerProcessor.java    From quarkus with Apache License 2.0 4 votes vote down vote up
private String generateInvoker(BeanInfo bean, MethodInfo method, ClassOutput classOutput) {

        String baseName;
        if (bean.getImplClazz().enclosingClass() != null) {
            baseName = DotNames.simpleName(bean.getImplClazz().enclosingClass()) + "_"
                    + DotNames.simpleName(bean.getImplClazz().name());
        } else {
            baseName = DotNames.simpleName(bean.getImplClazz().name());
        }
        StringBuilder sigBuilder = new StringBuilder();
        sigBuilder.append(method.name()).append("_").append(method.returnType().name().toString());
        for (Type i : method.parameters()) {
            sigBuilder.append(i.name().toString());
        }
        String targetPackage = DotNames.packageName(bean.getImplClazz().name());
        String generatedName = targetPackage.replace('.', '/') + "/" + baseName + INVOKER_SUFFIX + "_" + method.name() + "_"
                + HashUtil.sha1(sigBuilder.toString());

        ClassCreator invokerCreator = ClassCreator.builder().classOutput(classOutput).className(generatedName)
                .interfaces(ScheduledInvoker.class)
                .build();

        // The descriptor is: void invokeBean(Object execution)
        MethodCreator invoke = invokerCreator.getMethodCreator("invokeBean", void.class, Object.class);
        // InjectableBean<Foo: bean = Arc.container().bean("1");
        // InstanceHandle<Foo> handle = Arc.container().instance(bean);
        // handle.get().ping();
        ResultHandle containerHandle = invoke
                .invokeStaticMethod(MethodDescriptor.ofMethod(Arc.class, "container", ArcContainer.class));
        ResultHandle beanHandle = invoke.invokeInterfaceMethod(
                MethodDescriptor.ofMethod(ArcContainer.class, "bean", InjectableBean.class, String.class),
                containerHandle, invoke.load(bean.getIdentifier()));
        ResultHandle instanceHandle = invoke.invokeInterfaceMethod(
                MethodDescriptor.ofMethod(ArcContainer.class, "instance", InstanceHandle.class, InjectableBean.class),
                containerHandle, beanHandle);
        ResultHandle beanInstanceHandle = invoke
                .invokeInterfaceMethod(MethodDescriptor.ofMethod(InstanceHandle.class, "get", Object.class), instanceHandle);
        if (method.parameters().isEmpty()) {
            invoke.invokeVirtualMethod(
                    MethodDescriptor.ofMethod(bean.getImplClazz().name().toString(), method.name(), void.class),
                    beanInstanceHandle);
        } else {
            invoke.invokeVirtualMethod(
                    MethodDescriptor.ofMethod(bean.getImplClazz().name().toString(), method.name(), void.class,
                            ScheduledExecution.class),
                    beanInstanceHandle, invoke.getMethodParam(0));
        }
        // handle.destroy() - destroy dependent instance afterwards
        if (BuiltinScope.DEPENDENT.is(bean.getScope())) {
            invoke.invokeInterfaceMethod(MethodDescriptor.ofMethod(InstanceHandle.class, "destroy", void.class),
                    instanceHandle);
        }
        invoke.returnValue(null);

        invokerCreator.close();
        return generatedName.replace('/', '.');
    }
 
Example 15
Source File: PanacheEntityEnhancer.java    From quarkus with Apache License 2.0 4 votes vote down vote up
private void generateMethod(MethodInfo method, AnnotationValue targetReturnTypeErased) {
    String descriptor = AsmUtil.getDescriptor(method, name -> null);
    String signature = AsmUtil.getSignature(method, name -> null);
    List<org.jboss.jandex.Type> parameters = method.parameters();
    String castTo = null;
    if (targetReturnTypeErased != null && targetReturnTypeErased.asBoolean()) {
        castTo = method.returnType().name().toString('/');
    }

    MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC,
            method.name(),
            descriptor,
            signature,
            null);
    for (int i = 0; i < parameters.size(); i++) {
        mv.visitParameter(method.parameterName(i), 0 /* modifiers */);
    }
    mv.visitCode();
    for (PanacheMethodCustomizer customizer : methodCustomizers) {
        customizer.customize(thisClass, method, mv);
    }
    // inject model
    injectModel(mv);
    for (int i = 0; i < parameters.size(); i++) {
        mv.visitIntInsn(Opcodes.ALOAD, i);
    }
    // inject Class
    String forwardingDescriptor = "(" + getModelDescriptor() + descriptor.substring(1);
    if (castTo != null) {
        // return type is erased to Object
        int lastParen = forwardingDescriptor.lastIndexOf(')');
        forwardingDescriptor = forwardingDescriptor.substring(0, lastParen + 1) + "Ljava/lang/Object;";
    }
    mv.visitMethodInsn(Opcodes.INVOKESTATIC,
            getPanacheOperationsBinaryName(),
            method.name(),
            forwardingDescriptor, false);
    if (castTo != null)
        mv.visitTypeInsn(Opcodes.CHECKCAST, castTo);
    String returnTypeDescriptor = descriptor.substring(descriptor.lastIndexOf(")") + 1);
    mv.visitInsn(AsmUtil.getReturnInstruction(returnTypeDescriptor));
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}
 
Example 16
Source File: PanacheRepositoryEnhancer.java    From quarkus with Apache License 2.0 4 votes vote down vote up
private void generateJvmBridge(MethodInfo method) {
    // get a bounds-erased descriptor
    String descriptor = AsmUtil.getDescriptor(method, name -> null);
    // make sure we need a bridge
    if (!userMethods.contains(method.name() + "/" + descriptor)) {
        MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE,
                method.name(),
                descriptor,
                null,
                null);
        List<org.jboss.jandex.Type> parameters = method.parameters();
        for (int i = 0; i < parameters.size(); i++) {
            mv.visitParameter(method.parameterName(i), 0 /* modifiers */);
        }
        mv.visitCode();
        // this
        mv.visitIntInsn(Opcodes.ALOAD, 0);
        // each param
        for (int i = 0; i < parameters.size(); i++) {
            org.jboss.jandex.Type paramType = parameters.get(i);
            if (paramType.kind() == Kind.PRIMITIVE)
                throw new IllegalStateException("BUG: Don't know how to generate JVM bridge method for " + method
                        + ": has primitive parameters");
            mv.visitIntInsn(Opcodes.ALOAD, i + 1);
            if (paramType.kind() == Kind.TYPE_VARIABLE) {
                String typeParamName = paramType.asTypeVariable().identifier();
                switch (typeParamName) {
                    case "Entity":
                        mv.visitTypeInsn(Opcodes.CHECKCAST, entityBinaryType);
                        break;
                    case "Id":
                        mv.visitTypeInsn(Opcodes.CHECKCAST, idBinaryType);
                        break;
                }
            }
        }

        String targetDescriptor = AsmUtil.getDescriptor(method, name -> typeArguments.get(name));
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
                daoBinaryName,
                method.name(),
                targetDescriptor, false);
        String targetReturnTypeDescriptor = targetDescriptor.substring(targetDescriptor.indexOf(')') + 1);
        mv.visitInsn(AsmUtil.getReturnInstruction(targetReturnTypeDescriptor));
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }

}
 
Example 17
Source File: ExtensionMethodGenerator.java    From quarkus with Apache License 2.0 4 votes vote down vote up
private void implementAppliesTo(ClassCreator valueResolver, MethodInfo method, String matchName) {
    MethodCreator appliesTo = valueResolver.getMethodCreator("appliesTo", boolean.class, EvalContext.class)
            .setModifiers(ACC_PUBLIC);

    List<Type> parameters = method.parameters();
    boolean matchAny = matchName.equals(TemplateExtension.ANY);
    boolean isVarArgs = ValueResolverGenerator.isVarArgs(method);
    int realParamSize = parameters.size() - (matchAny ? 2 : 1);
    ResultHandle evalContext = appliesTo.getMethodParam(0);
    ResultHandle base = appliesTo.invokeInterfaceMethod(Descriptors.GET_BASE, evalContext);
    ResultHandle name = appliesTo.invokeInterfaceMethod(Descriptors.GET_NAME, evalContext);
    BytecodeCreator baseNull = appliesTo.ifNull(base).trueBranch();
    baseNull.returnValue(baseNull.load(false));

    // Test base object class
    ResultHandle baseClass = appliesTo.invokeVirtualMethod(Descriptors.GET_CLASS, base);
    ResultHandle testClass = appliesTo.loadClass(parameters.get(0).name().toString());
    ResultHandle baseClassTest = appliesTo.invokeVirtualMethod(Descriptors.IS_ASSIGNABLE_FROM, testClass,
            baseClass);
    BytecodeCreator baseNotAssignable = appliesTo.ifTrue(baseClassTest).falseBranch();
    baseNotAssignable.returnValue(baseNotAssignable.load(false));

    // Test property name
    if (!matchAny) {
        ResultHandle nameTest = appliesTo.invokeVirtualMethod(Descriptors.EQUALS, name,
                appliesTo.load(matchName));
        BytecodeCreator nameNotMatched = appliesTo.ifTrue(nameTest).falseBranch();
        nameNotMatched.returnValue(nameNotMatched.load(false));
    }

    // Test number of parameters
    if (!isVarArgs || realParamSize > 1) {
        ResultHandle params = appliesTo.invokeInterfaceMethod(Descriptors.GET_PARAMS, evalContext);
        ResultHandle paramsCount = appliesTo.invokeInterfaceMethod(Descriptors.COLLECTION_SIZE, params);
        BytecodeCreator paramsNotMatching;
        if (isVarArgs) {
            // For varargs methods match the minimal number of params
            paramsNotMatching = appliesTo.ifIntegerGreaterThan(appliesTo.load(realParamSize - 1), paramsCount).trueBranch();
        } else {
            paramsNotMatching = appliesTo.ifIntegerEqual(appliesTo.load(realParamSize), paramsCount).falseBranch();
        }
        paramsNotMatching.returnValue(paramsNotMatching.load(false));
    }

    appliesTo.returnValue(appliesTo.load(true));
}
 
Example 18
Source File: BeanGenerator.java    From quarkus with Apache License 2.0 4 votes vote down vote up
Collection<Resource> generateProducerMethodBean(BeanInfo bean, MethodInfo producerMethod) {

        ClassInfo declaringClass = producerMethod.declaringClass();
        String declaringClassBase;
        if (declaringClass.enclosingClass() != null) {
            declaringClassBase = DotNames.simpleName(declaringClass.enclosingClass()) + UNDERSCORE
                    + DotNames.simpleName(declaringClass);
        } else {
            declaringClassBase = DotNames.simpleName(declaringClass);
        }

        Type providerType = bean.getProviderType();
        StringBuilder sigBuilder = new StringBuilder();
        sigBuilder.append(producerMethod.name())
                .append(UNDERSCORE)
                .append(producerMethod.returnType().name().toString());

        for (Type i : producerMethod.parameters()) {
            sigBuilder.append(i.name().toString());
        }

        String baseName = declaringClassBase + PRODUCER_METHOD_SUFFIX + UNDERSCORE + producerMethod.name() + UNDERSCORE
                + Hashes.sha1(sigBuilder.toString());
        String providerTypeName = providerType.name().toString();
        String targetPackage = DotNames.packageName(declaringClass.name());
        String generatedName = generatedNameFromTarget(targetPackage, baseName, BEAN_SUFFIX);
        beanToGeneratedName.put(bean, generatedName);
        if (existingClasses.contains(generatedName)) {
            return Collections.emptyList();
        }

        boolean isApplicationClass = applicationClassPredicate.test(declaringClass.name());
        ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass,
                name -> name.equals(generatedName) ? SpecialType.BEAN : null, generateSources);

        // Foo_Bean implements InjectableBean<T>
        ClassCreator beanCreator = ClassCreator.builder().classOutput(classOutput).className(generatedName)
                .interfaces(InjectableBean.class, Supplier.class).build();

        // Fields
        FieldCreator beanTypes = beanCreator.getFieldCreator(FIELD_NAME_BEAN_TYPES, Set.class)
                .setModifiers(ACC_PRIVATE | ACC_FINAL);
        FieldCreator qualifiers = null;
        if (!bean.getQualifiers().isEmpty() && !bean.hasDefaultQualifiers()) {
            qualifiers = beanCreator.getFieldCreator(FIELD_NAME_QUALIFIERS, Set.class).setModifiers(ACC_PRIVATE | ACC_FINAL);
        }
        if (bean.getScope().isNormal()) {
            // For normal scopes a client proxy is generated too
            initializeProxy(bean, baseName, beanCreator);
        }
        FieldCreator stereotypes = null;
        if (!bean.getStereotypes().isEmpty()) {
            stereotypes = beanCreator.getFieldCreator(FIELD_NAME_STEREOTYPES, Set.class).setModifiers(ACC_PRIVATE | ACC_FINAL);
        }

        Map<InjectionPointInfo, String> injectionPointToProviderField = new HashMap<>();
        // Producer methods are not intercepted
        initMaps(bean, injectionPointToProviderField, null);

        createProviderFields(beanCreator, bean, injectionPointToProviderField, Collections.emptyMap());
        createConstructor(classOutput, beanCreator, bean, baseName, injectionPointToProviderField, Collections.emptyMap(),
                annotationLiterals, reflectionRegistration);

        implementGetIdentifier(bean, beanCreator);
        implementSupplierGet(beanCreator);
        if (!bean.hasDefaultDestroy()) {
            implementDestroy(bean, beanCreator, providerTypeName, injectionPointToProviderField, reflectionRegistration,
                    isApplicationClass, baseName);
        }
        implementCreate(classOutput, beanCreator, bean, providerTypeName, baseName, injectionPointToProviderField,
                Collections.emptyMap(),
                reflectionRegistration, targetPackage, isApplicationClass);
        implementGet(bean, beanCreator, providerTypeName, baseName);

        implementGetTypes(beanCreator, beanTypes.getFieldDescriptor());
        if (!BuiltinScope.isDefault(bean.getScope())) {
            implementGetScope(bean, beanCreator);
        }
        if (qualifiers != null) {
            implementGetQualifiers(bean, beanCreator, qualifiers.getFieldDescriptor());
        }
        if (bean.isAlternative()) {
            implementGetAlternativePriority(bean, beanCreator);
        }
        implementGetDeclaringBean(beanCreator);
        if (stereotypes != null) {
            implementGetStereotypes(bean, beanCreator, stereotypes.getFieldDescriptor());
        }
        implementGetBeanClass(bean, beanCreator);
        implementGetName(bean, beanCreator);
        if (bean.isDefaultBean()) {
            implementIsDefaultBean(bean, beanCreator);
        }
        implementGetKind(beanCreator, InjectableBean.Kind.PRODUCER_METHOD);

        beanCreator.close();
        return classOutput.getResources();
    }
 
Example 19
Source File: SmallRyeReactiveMessagingProcessor.java    From quarkus with Apache License 2.0 4 votes vote down vote up
/**
 * Generates an invoker class that looks like the following:
 *
 * <pre>
 * public class SomeName implements Invoker {
 *     private BeanType beanInstance;
 *
 *     public SomeName(Object var1) {
 *         this.beanInstance = var1;
 *     }
 *
 *     public Object invoke(Object[] args) {
 *         return this.beanInstance.doSomething(var1);
 *     }
 * }
 * </pre>
 */
private String generateInvoker(BeanInfo bean, MethodInfo method, ClassOutput classOutput) {
    String baseName;
    if (bean.getImplClazz().enclosingClass() != null) {
        baseName = DotNames.simpleName(bean.getImplClazz().enclosingClass()) + "_"
                + DotNames.simpleName(bean.getImplClazz().name());
    } else {
        baseName = DotNames.simpleName(bean.getImplClazz().name());
    }
    StringBuilder sigBuilder = new StringBuilder();
    sigBuilder.append(method.name()).append("_").append(method.returnType().name().toString());
    for (Type i : method.parameters()) {
        sigBuilder.append(i.name().toString());
    }
    String targetPackage = DotNames.packageName(bean.getImplClazz().name());
    String generatedName = targetPackage.replace('.', '/') + "/" + baseName + INVOKER_SUFFIX + "_" + method.name() + "_"
            + HashUtil.sha1(sigBuilder.toString());

    try (ClassCreator invoker = ClassCreator.builder().classOutput(classOutput).className(generatedName)
            .interfaces(Invoker.class)
            .build()) {

        String beanInstanceType = method.declaringClass().name().toString();
        FieldDescriptor beanInstanceField = invoker.getFieldCreator("beanInstance", beanInstanceType)
                .getFieldDescriptor();

        // generate a constructor that takes the bean instance as an argument
        // the method type needs to be Object because that is what is used as the call site in SmallRye Reactive Messaging
        try (MethodCreator ctor = invoker.getMethodCreator("<init>", void.class, Object.class)) {
            ctor.setModifiers(Modifier.PUBLIC);
            ctor.invokeSpecialMethod(MethodDescriptor.ofConstructor(Object.class), ctor.getThis());
            ResultHandle self = ctor.getThis();
            ResultHandle beanInstance = ctor.getMethodParam(0);
            ctor.writeInstanceField(beanInstanceField, self, beanInstance);
            ctor.returnValue(null);
        }

        try (MethodCreator invoke = invoker.getMethodCreator(
                MethodDescriptor.ofMethod(generatedName, "invoke", Object.class, Object[].class))) {

            int parametersCount = method.parameters().size();
            String[] argTypes = new String[parametersCount];
            ResultHandle[] args = new ResultHandle[parametersCount];
            for (int i = 0; i < parametersCount; i++) {
                // the only method argument of io.smallrye.reactive.messaging.Invoker is an object array so we need to pull out
                // each argument and put it in the target method arguments array
                args[i] = invoke.readArrayValue(invoke.getMethodParam(0), i);
                argTypes[i] = method.parameters().get(i).name().toString();
            }
            ResultHandle result = invoke.invokeVirtualMethod(
                    MethodDescriptor.ofMethod(beanInstanceType, method.name(),
                            method.returnType().name().toString(), argTypes),
                    invoke.readInstanceField(beanInstanceField, invoke.getThis()), args);
            if (ReactiveMessagingDotNames.VOID.equals(method.returnType().name())) {
                invoke.returnValue(invoke.loadNull());
            } else {
                invoke.returnValue(result);
            }
        }
    }

    return generatedName.replace('/', '.');
}
 
Example 20
Source File: AsmUtil.java    From quarkus with Apache License 2.0 3 votes vote down vote up
/**
 * Returns the Java bytecode descriptor of a given Jandex MethodInfo using the given type argument mappings.
 * For example, given this method:
 * 
 * <pre>
 * {@code
 * public class Foo<T> {
 *  public <R> List<R> method(int a, T t){...} 
 * }
 * }
 * </pre>
 * 
 * This will return <tt>(ILjava/lang/Integer;)Ljava/util/List;</tt> if
 * your {@code typeArgMapper} contains {@code T=Ljava/lang/Integer;}.
 * 
 * @param method the method you want the descriptor for.
 * @param typeArgMapper a mapping between type argument names and their bytecode descriptor.
 * @return a bytecode descriptor for that method.
 */
public static String getDescriptor(MethodInfo method, Function<String, String> typeArgMapper) {
    List<Type> parameters = method.parameters();

    StringBuilder descriptor = new StringBuilder("(");
    for (Type type : parameters) {
        toSignature(descriptor, type, typeArgMapper, true);
    }
    descriptor.append(")");
    toSignature(descriptor, method.returnType(), typeArgMapper, true);
    return descriptor.toString();
}