Search in sources :

Example 1 with BeanMetadataElement

use of org.springframework.beans.BeanMetadataElement in project spring-framework by spring-projects.

the class AutowireUtils method resolveReturnTypeForFactoryMethod.

/**
	 * Determine the target type for the generic return type of the given
	 * <em>generic factory method</em>, where formal type variables are declared
	 * on the given method itself.
	 * <p>For example, given a factory method with the following signature, if
	 * {@code resolveReturnTypeForFactoryMethod()} is invoked with the reflected
	 * method for {@code creatProxy()} and an {@code Object[]} array containing
	 * {@code MyService.class}, {@code resolveReturnTypeForFactoryMethod()} will
	 * infer that the target return type is {@code MyService}.
	 * <pre class="code">{@code public static <T> T createProxy(Class<T> clazz)}</pre>
	 * <h4>Possible Return Values</h4>
	 * <ul>
	 * <li>the target return type, if it can be inferred</li>
	 * <li>the {@linkplain Method#getReturnType() standard return type}, if
	 * the given {@code method} does not declare any {@linkplain
	 * Method#getTypeParameters() formal type variables}</li>
	 * <li>the {@linkplain Method#getReturnType() standard return type}, if the
	 * target return type cannot be inferred (e.g., due to type erasure)</li>
	 * <li>{@code null}, if the length of the given arguments array is shorter
	 * than the length of the {@linkplain
	 * Method#getGenericParameterTypes() formal argument list} for the given
	 * method</li>
	 * </ul>
	 * @param method the method to introspect (never {@code null})
	 * @param args the arguments that will be supplied to the method when it is
	 * invoked (never {@code null})
	 * @param classLoader the ClassLoader to resolve class names against,
	 * if necessary (never {@code null})
	 * @return the resolved target return type or the standard method return type
	 * @since 3.2.5
	 */
public static Class<?> resolveReturnTypeForFactoryMethod(Method method, Object[] args, ClassLoader classLoader) {
    Assert.notNull(method, "Method must not be null");
    Assert.notNull(args, "Argument array must not be null");
    Assert.notNull(classLoader, "ClassLoader must not be null");
    TypeVariable<Method>[] declaredTypeVariables = method.getTypeParameters();
    Type genericReturnType = method.getGenericReturnType();
    Type[] methodParameterTypes = method.getGenericParameterTypes();
    Assert.isTrue(args.length == methodParameterTypes.length, "Argument array does not match parameter count");
    // Ensure that the type variable (e.g., T) is declared directly on the method
    // itself (e.g., via <T>), not on the enclosing class or interface.
    boolean locallyDeclaredTypeVariableMatchesReturnType = false;
    for (TypeVariable<Method> currentTypeVariable : declaredTypeVariables) {
        if (currentTypeVariable.equals(genericReturnType)) {
            locallyDeclaredTypeVariableMatchesReturnType = true;
            break;
        }
    }
    if (locallyDeclaredTypeVariableMatchesReturnType) {
        for (int i = 0; i < methodParameterTypes.length; i++) {
            Type methodParameterType = methodParameterTypes[i];
            Object arg = args[i];
            if (methodParameterType.equals(genericReturnType)) {
                if (arg instanceof TypedStringValue) {
                    TypedStringValue typedValue = ((TypedStringValue) arg);
                    if (typedValue.hasTargetType()) {
                        return typedValue.getTargetType();
                    }
                    try {
                        return typedValue.resolveTargetType(classLoader);
                    } catch (ClassNotFoundException ex) {
                        throw new IllegalStateException("Failed to resolve value type [" + typedValue.getTargetTypeName() + "] for factory method argument", ex);
                    }
                }
                // Only consider argument type if it is a simple value...
                if (arg != null && !(arg instanceof BeanMetadataElement)) {
                    return arg.getClass();
                }
                return method.getReturnType();
            } else if (methodParameterType instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) methodParameterType;
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                for (Type typeArg : actualTypeArguments) {
                    if (typeArg.equals(genericReturnType)) {
                        if (arg instanceof Class) {
                            return (Class<?>) arg;
                        } else {
                            String className = null;
                            if (arg instanceof String) {
                                className = (String) arg;
                            } else if (arg instanceof TypedStringValue) {
                                TypedStringValue typedValue = ((TypedStringValue) arg);
                                String targetTypeName = typedValue.getTargetTypeName();
                                if (targetTypeName == null || Class.class.getName().equals(targetTypeName)) {
                                    className = typedValue.getValue();
                                }
                            }
                            if (className != null) {
                                try {
                                    return ClassUtils.forName(className, classLoader);
                                } catch (ClassNotFoundException ex) {
                                    throw new IllegalStateException("Could not resolve class name [" + arg + "] for factory method argument", ex);
                                }
                            }
                            // For now, just fall back...
                            return method.getReturnType();
                        }
                    }
                }
            }
        }
    }
    // Fall back...
    return method.getReturnType();
}
Also used : Method(java.lang.reflect.Method) BeanMetadataElement(org.springframework.beans.BeanMetadataElement) ParameterizedType(java.lang.reflect.ParameterizedType) ParameterizedType(java.lang.reflect.ParameterizedType) Type(java.lang.reflect.Type) TypeVariable(java.lang.reflect.TypeVariable) TypedStringValue(org.springframework.beans.factory.config.TypedStringValue)

Example 2 with BeanMetadataElement

use of org.springframework.beans.BeanMetadataElement in project spring-framework by spring-projects.

the class ConstructorResolver method resolvePreparedArguments.

/**
	 * Resolve the prepared arguments stored in the given bean definition.
	 */
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, Executable executable, Object[] argsToResolve) {
    TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
    TypeConverter converter = (customConverter != null ? customConverter : bw);
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
    Class<?>[] paramTypes = executable.getParameterTypes();
    Object[] resolvedArgs = new Object[argsToResolve.length];
    for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
        Object argValue = argsToResolve[argIndex];
        MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
        GenericTypeResolver.resolveParameterType(methodParam, executable.getDeclaringClass());
        if (argValue instanceof AutowiredArgumentMarker) {
            argValue = resolveAutowiredArgument(methodParam, beanName, null, converter);
        } else if (argValue instanceof BeanMetadataElement) {
            argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
        } else if (argValue instanceof String) {
            argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
        }
        Class<?> paramType = paramTypes[argIndex];
        try {
            resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
        } catch (TypeMismatchException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
        }
    }
    return resolvedArgs;
}
Also used : InjectionPoint(org.springframework.beans.factory.InjectionPoint) TypeMismatchException(org.springframework.beans.TypeMismatchException) InjectionPoint(org.springframework.beans.factory.InjectionPoint) TypeConverter(org.springframework.beans.TypeConverter) BeanMetadataElement(org.springframework.beans.BeanMetadataElement) UnsatisfiedDependencyException(org.springframework.beans.factory.UnsatisfiedDependencyException) MethodParameter(org.springframework.core.MethodParameter)

Example 3 with BeanMetadataElement

use of org.springframework.beans.BeanMetadataElement in project spring-security-oauth by spring-projects.

the class ConsumerServiceBeanDefinitionParser method doParse.

@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
    List<Element> consumerElements = DomUtils.getChildElementsByTagName(element, "consumer");
    ManagedMap<String, BeanMetadataElement> consumers = new ManagedMap<String, BeanMetadataElement>();
    for (Object item : consumerElements) {
        BeanDefinitionBuilder consumer = BeanDefinitionBuilder.genericBeanDefinition(ConsumerDetailsFactoryBean.class);
        Element consumerElement = (Element) item;
        String key = consumerElement.getAttribute("key");
        if (StringUtils.hasText(key)) {
            consumer.addPropertyValue("consumerKey", key);
        } else {
            parserContext.getReaderContext().error("A consumer key must be supplied with the definition of a consumer.", consumerElement);
        }
        String secret = consumerElement.getAttribute("secret");
        if (StringUtils.hasText(secret)) {
            consumer.addPropertyValue("secret", secret);
            String typeOfSecret = consumerElement.getAttribute("typeOfSecret");
            consumer.addPropertyValue("typeOfSecret", typeOfSecret);
        } else {
            parserContext.getReaderContext().error("A consumer secret must be supplied with the definition of a consumer.", consumerElement);
        }
        String name = consumerElement.getAttribute("name");
        if (StringUtils.hasText(name)) {
            consumer.addPropertyValue("consumerName", name);
        }
        String authorities = consumerElement.getAttribute("authorities");
        if (StringUtils.hasText(authorities)) {
            consumer.addPropertyValue("authorities", authorities);
        }
        String resourceName = consumerElement.getAttribute("resourceName");
        if (StringUtils.hasText(resourceName)) {
            consumer.addPropertyValue("resourceName", resourceName);
        }
        String resourceDescription = consumerElement.getAttribute("resourceDescription");
        if (StringUtils.hasText(resourceDescription)) {
            consumer.addPropertyValue("resourceDescription", resourceDescription);
        }
        String requiredToObtainAuthenticatedToken = consumerElement.getAttribute("requiredToObtainAuthenticatedToken");
        if (StringUtils.hasText(requiredToObtainAuthenticatedToken)) {
            consumer.addPropertyValue("requiredToObtainAuthenticatedToken", requiredToObtainAuthenticatedToken);
        }
        consumers.put(key, consumer.getBeanDefinition());
    }
    builder.addPropertyValue("consumerDetailsStore", consumers);
}
Also used : BeanMetadataElement(org.springframework.beans.BeanMetadataElement) BeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionBuilder) BeanMetadataElement(org.springframework.beans.BeanMetadataElement) Element(org.w3c.dom.Element) ManagedMap(org.springframework.beans.factory.support.ManagedMap)

Example 4 with BeanMetadataElement

use of org.springframework.beans.BeanMetadataElement in project spring-security by spring-projects.

the class HttpConfigurationBuilder method createChannelProcessingFilter.

private void createChannelProcessingFilter() {
    ManagedMap<BeanMetadataElement, BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
    if (channelRequestMap.isEmpty()) {
        return;
    }
    RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
    BeanDefinitionBuilder metadataSourceBldr = BeanDefinitionBuilder.rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class);
    metadataSourceBldr.addConstructorArgValue(channelRequestMap);
    // metadataSourceBldr.addPropertyValue("stripQueryStringFromUrls", matcher
    // instanceof AntUrlPathMatcher);
    channelFilter.getPropertyValues().addPropertyValue("securityMetadataSource", metadataSourceBldr.getBeanDefinition());
    RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
    ManagedList<RootBeanDefinition> channelProcessors = new ManagedList<RootBeanDefinition>(3);
    RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class);
    RootBeanDefinition retryWithHttp = new RootBeanDefinition(RetryWithHttpEntryPoint.class);
    RootBeanDefinition retryWithHttps = new RootBeanDefinition(RetryWithHttpsEntryPoint.class);
    retryWithHttp.getPropertyValues().addPropertyValue("portMapper", portMapper);
    retryWithHttp.getPropertyValues().addPropertyValue("portResolver", portResolver);
    retryWithHttps.getPropertyValues().addPropertyValue("portMapper", portMapper);
    retryWithHttps.getPropertyValues().addPropertyValue("portResolver", portResolver);
    secureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttps);
    RootBeanDefinition inSecureChannelProcessor = new RootBeanDefinition(InsecureChannelProcessor.class);
    inSecureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttp);
    channelProcessors.add(secureChannelProcessor);
    channelProcessors.add(inSecureChannelProcessor);
    channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors);
    String id = pc.getReaderContext().registerWithGeneratedName(channelDecisionManager);
    channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", new RuntimeBeanReference(id));
    cpf = channelFilter;
}
Also used : BeanMetadataElement(org.springframework.beans.BeanMetadataElement) BeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionBuilder) RootBeanDefinition(org.springframework.beans.factory.support.RootBeanDefinition) ManagedList(org.springframework.beans.factory.support.ManagedList) RootBeanDefinition(org.springframework.beans.factory.support.RootBeanDefinition) BeanDefinition(org.springframework.beans.factory.config.BeanDefinition) RuntimeBeanReference(org.springframework.beans.factory.config.RuntimeBeanReference)

Example 5 with BeanMetadataElement

use of org.springframework.beans.BeanMetadataElement in project spring-security by spring-projects.

the class HttpConfigurationBuilder method parseInterceptUrlsForChannelSecurity.

/**
	 * Parses the intercept-url elements to obtain the map used by channel security. This
	 * will be empty unless the <tt>requires-channel</tt> attribute has been used on a URL
	 * path.
	 */
private ManagedMap<BeanMetadataElement, BeanDefinition> parseInterceptUrlsForChannelSecurity() {
    ManagedMap<BeanMetadataElement, BeanDefinition> channelRequestMap = new ManagedMap<BeanMetadataElement, BeanDefinition>();
    for (Element urlElt : interceptUrls) {
        String path = urlElt.getAttribute(ATT_PATH_PATTERN);
        String method = urlElt.getAttribute(ATT_HTTP_METHOD);
        String matcherRef = urlElt.getAttribute(ATT_REQUEST_MATCHER_REF);
        boolean hasMatcherRef = StringUtils.hasText(matcherRef);
        if (!hasMatcherRef && !StringUtils.hasText(path)) {
            pc.getReaderContext().error("pattern attribute cannot be empty or null", urlElt);
        }
        String requiredChannel = urlElt.getAttribute(ATT_REQUIRES_CHANNEL);
        if (StringUtils.hasText(requiredChannel)) {
            BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : matcherType.createMatcher(pc, path, method);
            RootBeanDefinition channelAttributes = new RootBeanDefinition(ChannelAttributeFactory.class);
            channelAttributes.getConstructorArgumentValues().addGenericArgumentValue(requiredChannel);
            channelAttributes.setFactoryMethodName("createChannelAttributes");
            channelRequestMap.put(matcher, channelAttributes);
        }
    }
    return channelRequestMap;
}
Also used : BeanMetadataElement(org.springframework.beans.BeanMetadataElement) BeanMetadataElement(org.springframework.beans.BeanMetadataElement) Element(org.w3c.dom.Element) RootBeanDefinition(org.springframework.beans.factory.support.RootBeanDefinition) RootBeanDefinition(org.springframework.beans.factory.support.RootBeanDefinition) BeanDefinition(org.springframework.beans.factory.config.BeanDefinition) RuntimeBeanReference(org.springframework.beans.factory.config.RuntimeBeanReference) ManagedMap(org.springframework.beans.factory.support.ManagedMap)

Aggregations

BeanMetadataElement (org.springframework.beans.BeanMetadataElement)23 BeanDefinitionBuilder (org.springframework.beans.factory.support.BeanDefinitionBuilder)16 RuntimeBeanReference (org.springframework.beans.factory.config.RuntimeBeanReference)15 Element (org.w3c.dom.Element)14 BeanDefinition (org.springframework.beans.factory.config.BeanDefinition)10 RootBeanDefinition (org.springframework.beans.factory.support.RootBeanDefinition)8 ManagedList (org.springframework.beans.factory.support.ManagedList)7 ManagedMap (org.springframework.beans.factory.support.ManagedMap)5 BeanComponentDefinition (org.springframework.beans.factory.parsing.BeanComponentDefinition)4 TypedStringValue (org.springframework.beans.factory.config.TypedStringValue)3 Method (java.lang.reflect.Method)2 BeanReference (org.springframework.beans.factory.config.BeanReference)2 CompositeComponentDefinition (org.springframework.beans.factory.parsing.CompositeComponentDefinition)2 ParameterizedType (java.lang.reflect.ParameterizedType)1 Type (java.lang.reflect.Type)1 TypeVariable (java.lang.reflect.TypeVariable)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 TypeConverter (org.springframework.beans.TypeConverter)1 TypeMismatchException (org.springframework.beans.TypeMismatchException)1