001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.transport.http.spring;
019:
020: import javax.xml.bind.JAXBContext;
021: import javax.xml.bind.JAXBElement;
022: import javax.xml.bind.Unmarshaller;
023: import javax.xml.namespace.QName;
024:
025: import org.w3c.dom.Element;
026: import org.w3c.dom.Node;
027: import org.w3c.dom.NodeList;
028:
029: import org.apache.cxf.common.classloader.ClassLoaderUtils;
030: import org.apache.cxf.configuration.jsse.TLSClientParameters;
031: import org.apache.cxf.configuration.jsse.spring.TLSClientParametersConfig;
032: import org.apache.cxf.configuration.security.AuthorizationPolicy;
033: import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
034: import org.apache.cxf.configuration.security.TLSClientParametersType;
035: import org.apache.cxf.configuration.spring.AbstractBeanDefinitionParser;
036: import org.apache.cxf.transport.http.HTTPConduit;
037: import org.apache.cxf.transport.http.HttpBasicAuthSupplier;
038: import org.apache.cxf.transport.http.MessageTrustDecider;
039: import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
040: import org.springframework.beans.factory.support.BeanDefinitionBuilder;
041: import org.springframework.beans.factory.xml.ParserContext;
042:
043: public class HttpConduitBeanDefinitionParser extends
044: AbstractBeanDefinitionParser {
045:
046: private static final String HTTP_NS = "http://cxf.apache.org/transports/http/configuration";
047:
048: @Override
049: public void doParse(Element element, ParserContext ctx,
050: BeanDefinitionBuilder bean) {
051: bean.setAbstract(true);
052: mapElementToJaxbProperty(element, bean, new QName(HTTP_NS,
053: "client"), "client", HTTPClientPolicy.class);
054: mapElementToJaxbProperty(element, bean, new QName(HTTP_NS,
055: "proxyAuthorization"), "proxyAuthorization",
056: ProxyAuthorizationPolicy.class);
057: mapElementToJaxbProperty(element, bean, new QName(HTTP_NS,
058: "authorization"), "authorization",
059: AuthorizationPolicy.class);
060:
061: mapSpecificElements(element, bean);
062: }
063:
064: /**
065: * This method specifically maps the "trustDecider" and "basicAuthSupplier"
066: * elements to properties on the HttpConduit.
067: *
068: * @param parent This should represent "conduit".
069: * @param bean The bean parser.
070: */
071: private void mapSpecificElements(Element parent,
072: BeanDefinitionBuilder bean) {
073: NodeList nl = parent.getChildNodes();
074: for (int i = 0; i < nl.getLength(); i++) {
075: Node n = nl.item(i);
076: if (Node.ELEMENT_NODE != n.getNodeType()
077: || !HTTP_NS.equals(n.getNamespaceURI())) {
078: continue;
079: }
080: String elementName = n.getLocalName();
081: // Schema should require that no more than one each of these exist.
082: if ("trustDecider".equals(elementName)) {
083: mapBeanOrClassElement((Element) n, bean,
084: MessageTrustDecider.class);
085: } else if ("basicAuthSupplier".equals(elementName)) {
086: mapBeanOrClassElement((Element) n, bean,
087: HttpBasicAuthSupplier.class);
088: } else if ("tlsClientParameters".equals(elementName)) {
089: mapTLSClientParameters(n, bean);
090: }
091: }
092:
093: }
094:
095: /**
096: * Inject the "setTlsClientParameters" method with
097: * a TLSClientParametersConfig object initialized with the JAXB
098: * generated type unmarshalled from the selected node.
099: */
100: public void mapTLSClientParameters(Node n,
101: BeanDefinitionBuilder bean) {
102:
103: // Unmarshal the JAXB Generated Type from Config and inject
104: // the configured TLSClientParameters into the HTTPConduit.
105: JAXBContext context = null;
106: try {
107: context = JAXBContext.newInstance(
108: TLSClientParametersType.class.getPackage()
109: .getName(), getClass().getClassLoader());
110: Unmarshaller u = context.createUnmarshaller();
111: JAXBElement<TLSClientParametersType> jaxb = u.unmarshal(n,
112: TLSClientParametersType.class);
113: TLSClientParameters params = new TLSClientParametersConfig(
114: jaxb.getValue());
115: bean.addPropertyValue("tlsClientParameters", params);
116: } catch (Exception e) {
117: throw new RuntimeException(
118: "Could not process configuration.", e);
119: }
120: }
121:
122: /**
123: * This method finds the class or bean associated with the named element
124: * and sets the bean property that is associated with the same name as
125: * the element.
126: * <p>
127: * The element has either a "class" attribute or "bean" attribute, but
128: * not both.
129: *
130: * @param element The element.
131: * @param bean The Bean Definition Parser.
132: * @param elementClass The Class a bean or class is supposed to be.
133: */
134: protected void mapBeanOrClassElement(Element element,
135: BeanDefinitionBuilder bean, Class elementClass) {
136: String elementName = element.getLocalName();
137:
138: String classProperty = element.getAttribute("class");
139: if (classProperty != null && !classProperty.equals("")) {
140: try {
141: Object obj = ClassLoaderUtils.loadClass(classProperty,
142: getClass()).newInstance();
143: if (!elementClass.isInstance(obj)) {
144: throw new IllegalArgumentException("Element '"
145: + elementName + "' must be of type "
146: + elementClass.getName() + ".");
147: }
148: bean.addPropertyValue(elementName, obj);
149: } catch (IllegalAccessException ex) {
150: throw new IllegalArgumentException("Element '"
151: + elementName + "' could not load "
152: + classProperty + " - " + ex);
153: } catch (ClassNotFoundException ex) {
154: throw new IllegalArgumentException("Element '"
155: + elementName + "' could not load "
156: + classProperty + " - " + ex);
157: } catch (InstantiationException ex) {
158: throw new IllegalArgumentException("Element '"
159: + elementName + "' could not load "
160: + classProperty + " - " + ex);
161: }
162: }
163: String beanref = element.getAttribute("bean");
164: if (beanref != null && !beanref.equals("")) {
165: if (classProperty != null && !classProperty.equals("")) {
166: throw new IllegalArgumentException("Element '"
167: + elementName + "' cannot have both "
168: + "\"bean\" and \"class\" attributes.");
169:
170: }
171: bean.addPropertyReference(elementName, beanref);
172: } else if (classProperty == null || classProperty.equals("")) {
173: throw new IllegalArgumentException("Element '"
174: + elementName + "' requires at least one of the "
175: + "\"bean\" or \"class\" attributes.");
176: }
177: }
178:
179: @Override
180: protected Class getBeanClass(Element arg0) {
181: return HTTPConduit.class;
182: }
183:
184: }
|