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