Java tutorial
/* * 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.idp.profile.spring.relyingparty.metadata.impl; import java.util.List; import javax.xml.namespace.QName; import net.shibboleth.ext.spring.util.SpringSupport; import net.shibboleth.idp.profile.spring.relyingparty.metadata.AbstractMetadataProviderParser; import net.shibboleth.idp.profile.spring.relyingparty.metadata.FileCachingHttpClientFactoryBean; import net.shibboleth.idp.profile.spring.relyingparty.metadata.HttpClientFactoryBean; import net.shibboleth.idp.profile.spring.relyingparty.metadata.InMemoryCachingHttpClientFactoryBean; import net.shibboleth.utilities.java.support.httpclient.HttpClientSupport; import net.shibboleth.utilities.java.support.primitive.StringSupport; import net.shibboleth.utilities.java.support.xml.ElementSupport; import net.shibboleth.utilities.java.support.xml.XMLConstants; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.conn.ssl.StrictHostnameVerifier; import org.opensaml.security.httpclient.impl.SecurityEnhancedTLSSocketFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.beans.factory.parsing.Location; import org.springframework.beans.factory.parsing.Problem; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** * Parser for abstract dynamic HTTP metadata resolvers. */ public abstract class AbstractDynamicHTTPMetadataProviderParser extends AbstractDynamicMetadataProviderParser { /** TLSTrustEngine element name. */ public static final QName TLS_TRUST_ENGINE_ELEMENT_NAME = new QName( AbstractMetadataProviderParser.METADATA_NAMESPACE, "TLSTrustEngine"); /** BASIC auth username. */ private static final String BASIC_AUTH_USER = "basicAuthUser"; /** BASIC auth password. */ private static final String BASIC_AUTH_PASSWORD = "basicAuthPassword"; /** Default caching type . */ private static final String DEFAULT_CACHING = "memory"; /** Logger. */ private final Logger log = LoggerFactory.getLogger(AbstractDynamicHTTPMetadataProviderParser.class); /** {@inheritDoc} */ // Checkstyle: CyclomaticComplexity OFF -- more readable not split up @Override protected void doNativeParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doNativeParse(element, parserContext, builder); boolean haveTLSTrustEngine = false; if (element.hasAttributeNS(null, "tlsTrustEngineRef")) { builder.addPropertyReference("tLSTrustEngine", StringSupport.trimOrNull(element.getAttributeNS(null, "tlsTrustEngineRef"))); haveTLSTrustEngine = true; } else { BeanDefinition tlsTrustEngine = parseTLSTrustEngine(element, parserContext); if (tlsTrustEngine != null) { builder.addPropertyValue("tLSTrustEngine", tlsTrustEngine); haveTLSTrustEngine = true; } } if (element.hasAttributeNS(null, "httpClientRef")) { builder.addConstructorArgReference( StringSupport.trimOrNull(element.getAttributeNS(null, "httpClientRef"))); if (element.hasAttributeNS(null, "requestTimeout") || element.hasAttributeNS(null, "disregardSslCertificate") || element.hasAttributeNS(null, "disregardTLSCertificate") || element.hasAttributeNS(null, "proxyHost") || element.hasAttributeNS(null, "proxyPort") || element.hasAttributeNS(null, "proxyUser") || element.hasAttributeNS(null, "proxyPassword")) { log.warn("httpClientRef overrides settings for requestTimeout, disregardSslCertificate, " + "disregardTLSCertificate, proxyHost, proxyPort, proxyUser and proxyPassword"); } } else { builder.addConstructorArgValue(buildHttpClient(element, parserContext, haveTLSTrustEngine)); } if (element.hasAttributeNS(null, "credentialsProviderRef")) { builder.addPropertyReference("credentialsProviderRef", StringSupport.trimOrNull(element.getAttributeNS(null, "credentialsProviderRef"))); if (element.hasAttributeNS(null, BASIC_AUTH_USER) || element.hasAttributeNS(null, BASIC_AUTH_PASSWORD)) { log.warn("credentialsProviderRef overrides settings for basicAuthUser and basicAuthPassword"); } } else { if (element.hasAttributeNS(null, BASIC_AUTH_USER) || element.hasAttributeNS(null, BASIC_AUTH_PASSWORD)) { builder.addPropertyValue("basicCredentials", buildBasicCredentials(element)); } } if (element.hasAttributeNS(null, "supportedContentTypes")) { List<String> supportedContentTypes = StringSupport.stringToList( StringSupport.trimOrNull(element.getAttributeNS(null, "supportedContentTypes")), XMLConstants.LIST_DELIMITERS); builder.addPropertyValue("supportedContentTypes", supportedContentTypes); } } // Checkstyle: CyclomaticComplexity ON /** * Build the definition of the HTTPClientBuilder which contains all our configuration. * * @param element the HTTPMetadataProvider parser. * @param parserContext thee context * @param haveTLSTrustEngine whether have a TLS TrustEngine configured * @return the bean definition with the parameters. */ // Checkstyle: CyclomaticComplexity OFF // Checkstyle: MethodLength OFF private BeanDefinition buildHttpClient(Element element, ParserContext parserContext, boolean haveTLSTrustEngine) { String caching = DEFAULT_CACHING; if (element.hasAttributeNS(null, "httpCaching")) { caching = StringSupport.trimOrNull(element.getAttributeNS(null, "httpCaching")); } BeanDefinitionBuilder clientBuilder = null; switch (caching) { case "none": clientBuilder = BeanDefinitionBuilder.genericBeanDefinition(HttpClientFactoryBean.class); break; case "file": clientBuilder = BeanDefinitionBuilder.genericBeanDefinition(FileCachingHttpClientFactoryBean.class); if (element.hasAttributeNS(null, "httpCacheDirectory")) { clientBuilder.addPropertyValue("cacheDirectory", StringSupport.trimOrNull(element.getAttributeNS(null, "httpCacheDirectory"))); } if (element.hasAttributeNS(null, "httpMaxCacheEntries")) { clientBuilder.addPropertyValue("maxCacheEntries", StringSupport.trimOrNull(element.getAttributeNS(null, "httpMaxCacheEntries"))); } if (element.hasAttributeNS(null, "httpMaxCacheEntrySize")) { clientBuilder.addPropertyValue("maxCacheEntrySize", StringSupport.trimOrNull(element.getAttributeNS(null, "httpMaxCacheEntrySize"))); } break; case "memory": clientBuilder = BeanDefinitionBuilder.genericBeanDefinition(InMemoryCachingHttpClientFactoryBean.class); if (element.hasAttributeNS(null, "httpMaxCacheEntries")) { clientBuilder.addPropertyValue("maxCacheEntries", StringSupport.trimOrNull(element.getAttributeNS(null, "httpMaxCacheEntries"))); } if (element.hasAttributeNS(null, "httpMaxCacheEntrySize")) { clientBuilder.addPropertyValue("maxCacheEntrySize", StringSupport.trimOrNull(element.getAttributeNS(null, "httpMaxCacheEntrySize"))); } break; default: throw new BeanDefinitionParsingException( new Problem(String.format("Caching value '%s' is unsupported", caching), new Location(parserContext.getReaderContext().getResource()))); } clientBuilder.setLazyInit(true); if (element.hasAttributeNS(null, "requestTimeout")) { clientBuilder.addPropertyValue("connectionTimeout", StringSupport.trimOrNull(element.getAttributeNS(null, "requestTimeout"))); } if (haveTLSTrustEngine) { clientBuilder.addPropertyValue("tLSSocketFactory", new SecurityEnhancedTLSSocketFactory( HttpClientSupport.buildNoTrustTLSSocketFactory(), new StrictHostnameVerifier())); } if (element.hasAttributeNS(null, "disregardTLSCertificate")) { clientBuilder.addPropertyValue("connectionDisregardTLSCertificate", StringSupport.trimOrNull(element.getAttributeNS(null, "disregardTLSCertificate"))); } else if (element.hasAttributeNS(null, "disregardSslCertificate")) { log.warn("disregardSslCertificate is deprecated, please switch to disregardTLSCertificate"); clientBuilder.addPropertyValue("connectionDisregardTLSCertificate", StringSupport.trimOrNull(element.getAttributeNS(null, "disregardSslCertificate"))); } if (element.hasAttributeNS(null, "proxyHost")) { clientBuilder.addPropertyValue("connectionProxyHost", StringSupport.trimOrNull(element.getAttributeNS(null, "proxyHost"))); } if (element.hasAttributeNS(null, "proxyPort")) { clientBuilder.addPropertyValue("connectionProxyPort", StringSupport.trimOrNull(element.getAttributeNS(null, "proxyPort"))); } if (element.hasAttributeNS(null, "proxyUser")) { clientBuilder.addPropertyValue("connectionProxyUsername", StringSupport.trimOrNull(element.getAttributeNS(null, "proxyUser"))); } if (element.hasAttributeNS(null, "proxyPassword")) { clientBuilder.addPropertyValue("connectionProxyPassword", element.getAttributeNS(null, "proxyPassword")); } return clientBuilder.getBeanDefinition(); } // Checkstyle: CyclomaticComplexity ON // Checkstyle: MethodLength ON /** * Build the POJO with the username and password. * * @param element the HTTPMetadataProvider parser. * @return the bean definition with the username and password. */ private BeanDefinition buildBasicCredentials(Element element) { BeanDefinitionBuilder builder = BeanDefinitionBuilder .genericBeanDefinition(UsernamePasswordCredentials.class); builder.setLazyInit(true); builder.addConstructorArgValue(StringSupport.trimOrNull(element.getAttributeNS(null, BASIC_AUTH_USER))); builder.addConstructorArgValue(StringSupport.trimOrNull(element.getAttributeNS(null, BASIC_AUTH_PASSWORD))); return builder.getBeanDefinition(); } /** * Build the definition of the HTTPClientBuilder which contains all our configuration. * * @param element the HTTPMetadataProvider element * @param parserContext the context * @return the bean definition */ private BeanDefinition parseTLSTrustEngine(Element element, ParserContext parserContext) { Element tlsTrustEngine = ElementSupport.getFirstChildElement(element, TLS_TRUST_ENGINE_ELEMENT_NAME); if (tlsTrustEngine != null) { Element trustEngine = ElementSupport.getFirstChildElement(tlsTrustEngine, AbstractMetadataProviderParser.TRUST_ENGINE_ELEMENT_NAME); if (trustEngine != null) { return SpringSupport.parseCustomElement(trustEngine, parserContext); } else { // This should be schema-invalid, but log a warning just in case. log.warn("{}:, Element {} did not contain a {} child element", parserContext.getReaderContext().getResource().getDescription(), TLS_TRUST_ENGINE_ELEMENT_NAME, AbstractMetadataProviderParser.TRUST_ENGINE_ELEMENT_NAME); } } return null; } }