net.shibboleth.ext.spring.util.SpringSupport Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-extensions Show documentation
Show all versions of spring-extensions Show documentation
A set of extensions for the Spring framework. This package includes things like
factory beans, converters, etc.
/*
* Licensed to the University Corporation for Advanced Internet Development,
* Inc. (UCAID) under one or more contributor license agreements. See the
* NOTICE file distributed with this work for additional information regarding
* copyright ownership. The UCAID licenses this file to You under the Apache
* License, Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.shibboleth.ext.spring.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.xml.namespace.QName;
import net.shibboleth.ext.spring.config.DurationToLongConverter;
import net.shibboleth.ext.spring.config.StringBooleanToPredicateConverter;
import net.shibboleth.ext.spring.config.StringToIPRangeConverter;
import net.shibboleth.ext.spring.context.FilesystemGenericApplicationContext;
import net.shibboleth.ext.spring.resource.PreferFileSystemResourceLoader;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.logic.Constraint;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
import net.shibboleth.utilities.java.support.xml.AttributeSupport;
import net.shibboleth.utilities.java.support.xml.SerializeSupport;
import net.shibboleth.utilities.java.support.xml.XMLConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.support.ConversionServiceFactoryBean;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.Resource;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import com.google.common.base.Strings;
/**
* Helper class for performing some common Spring-related functions.
*/
public final class SpringSupport {
/** Spring beans element name. */
@Nonnull public static final QName SPRING_BEANS_ELEMENT_NAME = new QName(
"http://www.springframework.org/schema/beans", "beans");
/** Logger. */
@Nonnull static final Logger LOG = LoggerFactory.getLogger(SpringSupport.class);
/** Constructor. */
private SpringSupport() {
}
// Checkstyle: ParameterNumber OFF
/**
* Creates a new, started, application context from the given configuration resources.
*
* @param name name of the application context
* @param configurationResources configuration resources
* @param factoryPostProcessors post processors to inject
* @param postProcessors post processors to inject
* @param initializers application context initializers
* @param parentContext parent context, or null if there is no parent
*
* @return the created context
*/
@Nonnull public static GenericApplicationContext newContext(@Nonnull @NotEmpty final String name,
@Nonnull @NonnullElements final List configurationResources,
@Nonnull @NonnullElements final List factoryPostProcessors,
@Nonnull @NonnullElements final List postProcessors,
@Nonnull @NonnullElements final List initializers,
@Nullable final ApplicationContext parentContext) {
Constraint.isNotNull(configurationResources, "configurationResources cannot be null");
Constraint.noNullItems(configurationResources, "configurationResources must have no null items");
Constraint.isNotNull(factoryPostProcessors, "factoryPostProcessors cannot be null");
Constraint.noNullItems(factoryPostProcessors, "factoryPostProcessors must have no null items");
Constraint.isNotNull(postProcessors, "postProcessors cannot be null");
Constraint.noNullItems(postProcessors, "postProcessors must have no null items");
Constraint.isNotNull(initializers, "initializers cannot be null");
Constraint.noNullItems(initializers, "initializers must have no null items");
final GenericApplicationContext context = new FilesystemGenericApplicationContext(parentContext);
context.setDisplayName("ApplicationContext:" + name);
context.setResourceLoader(new PreferFileSystemResourceLoader());
final ConversionServiceFactoryBean service = new ConversionServiceFactoryBean();
service.setConverters(new HashSet<>(Arrays.asList(new DurationToLongConverter(), new StringToIPRangeConverter(),
new StringBooleanToPredicateConverter())));
service.afterPropertiesSet();
for (final BeanFactoryPostProcessor bfpp : factoryPostProcessors) {
context.addBeanFactoryPostProcessor(bfpp);
}
context.getBeanFactory().setConversionService(service.getObject());
for (final BeanPostProcessor bpp : postProcessors) {
context.getBeanFactory().addBeanPostProcessor(bpp);
}
final SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
new SchemaTypeAwareXMLBeanDefinitionReader(context);
beanDefinitionReader.loadBeanDefinitions(configurationResources.toArray(new Resource[] {}));
if (initializers != null) {
for (final ApplicationContextInitializer initializer : initializers) {
initializer.initialize(context);
}
}
context.refresh();
return context;
}
// Checkstyle: ParameterNumber ON
/**
* Parse list of elements into bean definitions.
*
* @param elements list of elements to parse
* @param parserContext current parsing context
*
* @return list of bean definitions
*/
// TODO better javadoc, annotations
@Nullable public static ManagedList parseCustomElements(
@Nullable @NonnullElements final Collection elements, @Nonnull final ParserContext parserContext) {
if (elements == null) {
return null;
}
final ManagedList definitions = new ManagedList<>(elements.size());
for (final Element e : elements) {
if (e != null) {
definitions.add(parseCustomElement(e, parserContext));
}
}
return definitions;
}
/**
* Parse an element into a bean definition.
*
* @param element the element to parse
* @param parserContext current parsing context
*
* @return the parsed bean definition
*/
@Nullable public static BeanDefinition parseCustomElement(@Nullable final Element element,
@Nonnull final ParserContext parserContext) {
if (element == null) {
return null;
}
return parserContext.getDelegate().parseCustomElement(element);
}
/**
* Parse the provided Element into the provided registry.
*
* @param springBeans the element to parse
* @param registry the registry to populate
*/
public static void
parseNativeElement(@Nonnull final Element springBeans, @Nullable final BeanDefinitionRegistry registry) {
final XmlBeanDefinitionReader definitionReader = new XmlBeanDefinitionReader(registry);
definitionReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
definitionReader.setNamespaceAware(true);
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
SerializeSupport.writeNode(springBeans, outputStream);
definitionReader.loadBeanDefinitions(new InputSource(new ByteArrayInputStream(outputStream.toByteArray())));
}
/**
* Creates a Spring bean factory from the supplied Spring beans element.
*
* @param springBeans to create bean factory from
*
* @return bean factory
*/
@Nonnull public static BeanFactory createBeanFactory(@Nonnull final Element springBeans) {
// Pull in the closest xsi:schemaLocation attribute we can find.
if (!springBeans.hasAttributeNS(XMLConstants.XSI_SCHEMA_LOCATION_ATTRIB_NAME.getNamespaceURI(),
XMLConstants.XSI_SCHEMA_LOCATION_ATTRIB_NAME.getLocalPart())) {
Node parent = springBeans.getParentNode();
while (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
final String schemaLoc =
((Element) parent).getAttributeNS(
XMLConstants.XSI_SCHEMA_LOCATION_ATTRIB_NAME.getNamespaceURI(),
XMLConstants.XSI_SCHEMA_LOCATION_ATTRIB_NAME.getLocalPart());
if (!Strings.isNullOrEmpty(schemaLoc)) {
springBeans.setAttributeNS(XMLConstants.XSI_SCHEMA_LOCATION_ATTRIB_NAME.getNamespaceURI(),
XMLConstants.XSI_SCHEMA_LOCATION_ATTRIB_NAME.getPrefix() + ':'
+ XMLConstants.XSI_SCHEMA_LOCATION_ATTRIB_NAME.getLocalPart(), schemaLoc);
break;
} else {
parent = parent.getParentNode();
}
}
}
final GenericApplicationContext ctx = new FilesystemGenericApplicationContext();
parseNativeElement(springBeans, ctx);
ctx.refresh();
return ctx.getBeanFactory();
}
/**
* Retrieves the bean of the supplied type from the supplied bean factory. Returns null if no bean definition is
* found.
*
* @param type of bean to return
* @param beanFactory to get the bean from
* @param clazz type of the bean to retrieve
*
* @return spring bean
*/
@Nullable public static T getBean(@Nonnull final BeanFactory beanFactory, @Nonnull final Class clazz) {
T bean = null;
try {
bean = beanFactory.getBean(clazz);
LOG.debug("created spring bean {}", bean);
} catch (final NoSuchBeanDefinitionException e) {
LOG.debug("no spring bean configured of type {}", clazz);
}
return bean;
}
/**
* Gets the value of a list-type attribute as a {@link ManagedList}.
*
* @param attribute attribute whose value will be turned into a list
*
* @return list of values, never null
*/
@Nonnull public static ManagedList getAttributeValueAsManagedList(@Nullable final Attr attribute) {
final List valuesAsList = AttributeSupport.getAttributeValueAsList(attribute);
final ManagedList managedList = new ManagedList<>(valuesAsList.size());
managedList.addAll(valuesAsList);
return managedList;
}
/**
* Gets the text content of a list of {@link Element}s as a {@link ManagedList}.
*
* @param elements the elements whose values will be turned into a list
*
* @return list of values, never null
*/
@Nonnull public static ManagedList getElementTextContentAsManagedList(
@Nullable final Collection elements) {
if (null == elements || elements.isEmpty()) {
return new ManagedList<>(0);
}
final ManagedList result = new ManagedList<>(elements.size());
for (final Element element : elements) {
final String textContent = StringSupport.trimOrNull(element.getTextContent());
if (null != textContent) {
result.add(textContent);
}
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy