org.apache.cxf.jaxws.support.JaxWsEndpointImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cxf-bundle-minimal Show documentation
Show all versions of cxf-bundle-minimal Show documentation
Apache CXF Minimal Bundle Jar
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 org.apache.cxf.jaxws.support;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.ExtensionRegistry;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.Binding;
import javax.xml.ws.RespectBindingFeature;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.Addressing;
import javax.xml.ws.soap.AddressingFeature;
import javax.xml.ws.soap.MTOMFeature;
import javax.xml.ws.soap.SOAPBinding;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
import org.w3c.dom.Element;
import org.apache.cxf.Bus;
import org.apache.cxf.binding.soap.SoapBinding;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
import org.apache.cxf.binding.xml.XMLBinding;
import org.apache.cxf.common.classloader.ClassLoaderUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.endpoint.EndpointException;
import org.apache.cxf.endpoint.EndpointImpl;
import org.apache.cxf.feature.AbstractFeature;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.AbstractInDatabindingInterceptor;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.jaxws.binding.DefaultBindingImpl;
import org.apache.cxf.jaxws.binding.http.HTTPBindingImpl;
import org.apache.cxf.jaxws.binding.soap.SOAPBindingImpl;
import org.apache.cxf.jaxws.handler.logical.LogicalHandlerFaultInInterceptor;
import org.apache.cxf.jaxws.handler.logical.LogicalHandlerFaultOutInterceptor;
import org.apache.cxf.jaxws.handler.logical.LogicalHandlerInInterceptor;
import org.apache.cxf.jaxws.handler.logical.LogicalHandlerOutInterceptor;
import org.apache.cxf.jaxws.handler.soap.SOAPHandlerFaultInInterceptor;
import org.apache.cxf.jaxws.handler.soap.SOAPHandlerFaultOutInterceptor;
import org.apache.cxf.jaxws.handler.soap.SOAPHandlerInterceptor;
import org.apache.cxf.jaxws.interceptors.HolderInInterceptor;
import org.apache.cxf.jaxws.interceptors.HolderOutInterceptor;
import org.apache.cxf.jaxws.interceptors.MessageModeInInterceptor;
import org.apache.cxf.jaxws.interceptors.MessageModeOutInterceptor;
import org.apache.cxf.jaxws.interceptors.SwAInInterceptor;
import org.apache.cxf.jaxws.interceptors.SwAOutInterceptor;
import org.apache.cxf.jaxws.interceptors.WrapperClassInInterceptor;
import org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor;
import org.apache.cxf.jaxws.spi.ProviderImpl;
import org.apache.cxf.message.Message;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.model.BindingFaultInfo;
import org.apache.cxf.service.model.BindingInfo;
import org.apache.cxf.service.model.BindingMessageInfo;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.DescriptionInfo;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.service.model.Extensible;
import org.apache.cxf.staxutils.W3CDOMStreamWriter;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.apache.cxf.ws.addressing.JAXWSAConstants;
import org.apache.cxf.ws.addressing.Names;
import org.apache.cxf.ws.addressing.WSAddressingFeature;
import org.apache.cxf.wsdl.WSDLManager;
/**
* A JAX-WS specific implementation of the CXF {@link org.apache.cxf.endpoint.Endpoint} interface.
* Extends the interceptor provider functionality of its base class by adding
* interceptors in which to execute the JAX-WS handlers.
* Creates and owns an implementation of {@link Binding} in addition to the
* CXF {@link org.apache.cxf.binding.Binding}.
*
*/
public class JaxWsEndpointImpl extends EndpointImpl {
private static final long serialVersionUID = 4718088821386100282L;
private static final String URI_POLICY_NS = "http://www.w3.org/ns/ws-policy";
private static final String URI_WSU_NS
= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
private static final Logger LOG = LogUtils.getL7dLogger(JaxWsEndpointImpl.class);
private Binding jaxwsBinding;
private JaxWsImplementorInfo implInfo;
private List wsFeatures;
private List features;
//interceptors added/removed to chains as needed
private SOAPHandlerInterceptor soapHandlerInterceptor;
private LogicalHandlerInInterceptor logicalInInterceptor;
private LogicalHandlerOutInterceptor logicalOutInterceptor;
private LogicalHandlerFaultOutInterceptor logicalFaultOutInterceptor;
private SOAPHandlerFaultOutInterceptor soapFaultOutInterceptor;
private LogicalHandlerFaultInInterceptor logicalFaultInInterceptor;
private SOAPHandlerFaultInInterceptor soapFaultInInterceptor;
public JaxWsEndpointImpl(Bus bus, Service s, EndpointInfo ei) throws EndpointException {
this(bus, s, ei, null, null, null, true);
}
public JaxWsEndpointImpl(Bus bus, Service s, EndpointInfo ei,
List wf) throws EndpointException {
this(bus, s, ei, null, wf, new ArrayList(), true);
}
public JaxWsEndpointImpl(Bus bus, Service s, EndpointInfo ei, JaxWsImplementorInfo implementorInfo,
List wf, List af, boolean isFromWsdl)
throws EndpointException {
super(bus, s, ei);
this.implInfo = implementorInfo;
this.wsFeatures = wf;
this.features = af;
if (features == null) {
features = new ArrayList();
}
createJaxwsBinding();
List> in = super.getInInterceptors();
List> out = super.getOutInterceptors();
boolean isProvider = implInfo != null && implInfo.isWebServiceProvider();
Class> clazz = implInfo != null && isProvider ? implInfo.getProviderParameterType() : null;
Mode mode = implInfo != null && isProvider ? implInfo.getServiceMode() : null;
if (isProvider) {
s.put(AbstractInDatabindingInterceptor.NO_VALIDATE_PARTS, Boolean.TRUE);
}
// Inbound chain
logicalInInterceptor = new LogicalHandlerInInterceptor(jaxwsBinding);
if (!isProvider) {
in.add(new WrapperClassInInterceptor());
in.add(new HolderInInterceptor());
}
if (getBinding() instanceof SoapBinding) {
soapHandlerInterceptor = new SOAPHandlerInterceptor(jaxwsBinding);
in.add(new SwAInInterceptor());
getOutInterceptors().add(new SwAOutInterceptor());
if (isProvider && mode == Mode.MESSAGE) {
in.add(new SAAJInInterceptor());
}
}
if (isProvider && mode == Mode.MESSAGE) {
in.add(new MessageModeInInterceptor(clazz, getBinding().getBindingInfo().getName()));
}
// Outbound chain
logicalOutInterceptor = new LogicalHandlerOutInterceptor(jaxwsBinding);
if (!isProvider) {
out.add(new WrapperClassOutInterceptor());
out.add(new HolderOutInterceptor());
}
if (getBinding() instanceof SoapBinding && mode == Mode.MESSAGE) {
SAAJOutInterceptor saajOut = new SAAJOutInterceptor();
out.add(saajOut);
out.add(new MessageModeOutInterceptor(saajOut,
getBinding().getBindingInfo().getName()));
} else if (isProvider) {
out.add(new MessageModeOutInterceptor(clazz, getBinding().getBindingInfo().getName()));
}
logicalFaultOutInterceptor = new LogicalHandlerFaultOutInterceptor(jaxwsBinding);
logicalFaultInInterceptor = new LogicalHandlerFaultInInterceptor(jaxwsBinding);
if (getBinding() instanceof SoapBinding) {
soapFaultOutInterceptor = new SOAPHandlerFaultOutInterceptor(jaxwsBinding);
soapFaultInInterceptor = new SOAPHandlerFaultInInterceptor(jaxwsBinding);
}
if (ei != null) {
if (!isFromWsdl) {
buildWsdlExtensibilities(ei.getBinding());
}
extractWsdlExtensibilities(ei);
}
resolveFeatures();
}
private void extractWsdlExtensibilities(EndpointInfo endpoint) {
List portExtensors = getExtensors(endpoint);
List bindingExtensors = getExtensors(endpoint.getBinding());
//check the extensions under
checkRespectBindingFeature(bindingExtensors);
Collection bindingOperations = endpoint.getBinding().getOperations();
if (null != bindingOperations) {
Iterator iterator = bindingOperations.iterator();
while (iterator.hasNext()) {
BindingOperationInfo operationInfo = iterator.next();
BindingMessageInfo inputInfo = operationInfo.getInput();
BindingMessageInfo outputnfo = operationInfo.getOutput();
Collection faults = operationInfo.getFaults();
//check the extensions under
checkRespectBindingFeature(getExtensors(operationInfo));
//check the extensions under
checkRespectBindingFeature(getExtensors(inputInfo));
//check the extensions under
checkRespectBindingFeature(getExtensors(outputnfo));
if (null != faults) {
Iterator faultIterator = faults.iterator();
while (faultIterator.hasNext()) {
BindingFaultInfo faultInfo = faultIterator.next();
//check the extensions under
checkRespectBindingFeature(getExtensors(faultInfo));
}
}
}
}
if (hasUsingAddressing(bindingExtensors) || hasUsingAddressing(portExtensors)) {
WSAddressingFeature feature = new WSAddressingFeature();
if (addressingRequired(bindingExtensors)
|| addressingRequired(portExtensors)) {
feature.setAddressingRequired(true);
}
addAddressingFeature(feature);
}
extractWsdlEprs(endpoint);
}
private List getExtensors(Extensible extensibleInfo) {
return (null != extensibleInfo) ? extensibleInfo.getExtensors(ExtensibilityElement.class) : null;
}
private void checkRespectBindingFeature(List bindingExtensors) {
if (bindingExtensors != null) {
Iterator extensionElements = bindingExtensors.iterator();
while (extensionElements.hasNext()) {
ExtensibilityElement ext = extensionElements.next();
if (ext instanceof UnknownExtensibilityElement && Boolean.TRUE.equals(ext.getRequired())) {
for (WebServiceFeature feature : this.wsFeatures) {
if (feature instanceof RespectBindingFeature && feature.isEnabled()) {
org.apache.cxf.common.i18n.Message message =
new org.apache.cxf.common.i18n.Message("UNKONWN_REQUIRED_WSDL_BINDING", LOG);
LOG.severe(message.toString());
throw new WebServiceException(message.toString());
}
}
}
}
}
}
private void extractWsdlEprs(EndpointInfo endpoint) {
//parse the EPR in wsdl
List portExtensors = endpoint.getExtensors(ExtensibilityElement.class);
if (portExtensors != null) {
Iterator extensionElements = portExtensors.iterator();
QName wsaEpr = new QName(Names.WSA_NAMESPACE_NAME, "EndpointReference");
while (extensionElements.hasNext()) {
ExtensibilityElement ext = extensionElements.next();
if (ext instanceof UnknownExtensibilityElement && wsaEpr.equals(ext.getElementType())) {
DOMSource domSource = new DOMSource(((UnknownExtensibilityElement)ext).getElement());
W3CEndpointReference w3cEPR = new W3CEndpointReference(domSource);
EndpointReferenceType ref = ProviderImpl.convertToInternal(w3cEPR);
endpoint.getTarget().setMetadata(ref.getMetadata());
endpoint.getTarget().setReferenceParameters(ref.getReferenceParameters());
endpoint.getTarget().getOtherAttributes().putAll(ref.getOtherAttributes());
}
}
}
}
private boolean hasUsingAddressing(List exts) {
boolean found = false;
if (exts != null) {
Iterator extensionElements = exts.iterator();
while (extensionElements.hasNext() && !found) {
ExtensibilityElement ext =
extensionElements.next();
found = JAXWSAConstants.WSAW_USINGADDRESSING_QNAME.equals(ext.getElementType());
}
}
return found;
}
private boolean addressingRequired(List exts) {
boolean found = false;
if (exts != null) {
Iterator extensionElements = exts.iterator();
while (extensionElements.hasNext() && !found) {
ExtensibilityElement ext =
extensionElements.next();
if (JAXWSAConstants.WSAW_USINGADDRESSING_QNAME.equals(ext.getElementType())
&& ext.getRequired() != null) {
return ext.getRequired();
}
}
}
return false;
}
private void buildWsdlExtensibilities(BindingInfo bindingInfo) {
Addressing addressing = getAddressing();
if (addressing != null) {
ExtensionRegistry extensionRegistry = getBus().getExtension(WSDLManager.class)
.getExtensionRegistry();
try {
ExtensibilityElement el = extensionRegistry.createExtension(javax.wsdl.Binding.class,
JAXWSAConstants.
WSAW_USINGADDRESSING_QNAME);
el.setRequired(addressing.required());
bindingInfo.addExtensor(el);
StringBuilder polRefId = new StringBuilder(bindingInfo.getName().getLocalPart());
polRefId.append("_WSAM_Addressing_Policy");
UnknownExtensibilityElement uel = new UnknownExtensibilityElement();
W3CDOMStreamWriter writer = new W3CDOMStreamWriter();
writer.writeStartElement("wsp", "PolicyReference", URI_POLICY_NS);
writer.writeAttribute("URI", "#" + polRefId.toString());
writer.writeEndElement();
Element pr = writer.getDocument().getDocumentElement();
uel.setElement(pr);
uel.setElementType(DOMUtils.getElementQName(pr));
bindingInfo.addExtensor(uel);
writer = new W3CDOMStreamWriter();
writer.writeStartElement("wsp", "Policy", URI_POLICY_NS);
writer.writeAttribute("wsu", URI_WSU_NS,
"Id", polRefId.toString());
writer.writeStartElement("wsam", "Addressing", JAXWSAConstants.NS_WSAM);
if (!addressing.required()) {
writer.writeAttribute("wsp", URI_POLICY_NS,
"Optional", "true");
}
writer.writeStartElement("wsp", "Policy", URI_POLICY_NS);
String s = getAddressingRequirement(addressing);
if (s != null) {
writer.writeEmptyElement("wsam", s, JAXWSAConstants.NS_WSAM);
}
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndElement();
pr = writer.getDocument().getDocumentElement();
uel = new UnknownExtensibilityElement();
uel.setElement(pr);
uel.setElementType(DOMUtils.getElementQName(pr));
if (bindingInfo.getService().getDescription() == null) {
DescriptionInfo description = new DescriptionInfo();
description.setName(bindingInfo.getService().getName());
bindingInfo.getService().setDescription(description);
}
bindingInfo.getService().getDescription().addExtensor(uel);
} catch (Exception e) {
//ignore
e.printStackTrace();
}
}
}
private String getAddressingRequirement(Addressing addressing) {
try {
Object o = Addressing.class.getMethod("responses").invoke(addressing);
if (o != null) {
String s = o.toString();
if ("ANONYMOUS".equals(s)) {
return "AnonymousResponses";
} else if ("NON_ANONYMOUS".equals(s)) {
return "NonAnonymousResponses";
}
}
} catch (Throwable ex) {
//ignore - probably JAX-WS 2.1
}
return null;
}
private Addressing getAddressing() {
Class> serviceClass = implInfo.getImplementorClass();
if (serviceClass != null) {
Addressing ad = serviceClass.getAnnotation(Addressing.class);
if (ad != null) {
return ad;
}
}
serviceClass = implInfo.getSEIClass();
if (serviceClass != null) {
Addressing ad = serviceClass.getAnnotation(Addressing.class);
if (ad != null) {
return ad;
}
}
return null;
}
public Binding getJaxwsBinding() {
return jaxwsBinding;
}
private AddressingFeature getAddressingFeature() {
if (wsFeatures == null) {
return null;
}
for (WebServiceFeature feature : wsFeatures) {
if (feature instanceof AddressingFeature) {
return (AddressingFeature)feature;
}
}
return null;
}
public final void resolveFeatures() {
AddressingFeature addressing = getAddressingFeature();
if (addressing == null) {
return;
}
if (addressing.isEnabled()) {
WSAddressingFeature feature = getWSAddressingFeature();
if (feature == null) {
feature = new WSAddressingFeature();
addAddressingFeature(feature);
}
feature.setAddressingRequired(addressing.isRequired());
if (ProviderImpl.isJaxWs22()) {
try {
Class> addrClass = ClassLoaderUtils.loadClass("javax.xml.ws.soap.AddressingFeature",
ProviderImpl.class);
Method responsesMethod = addrClass.getMethod("getResponses", new Class[] {});
Object responses = responsesMethod.invoke(addressing, new Object[] {});
feature.setResponses(responses.toString());
} catch (Exception e) {
// ignore
}
}
} else {
removeAddressingFeature();
getEndpointInfo().setProperty("org.apache.cxf.ws.addressing.MAPAggregator.addressingDisabled",
Boolean.TRUE);
}
}
public List getFeatures() {
return features;
}
private WSAddressingFeature getWSAddressingFeature() {
if (features == null) {
return null;
}
for (AbstractFeature f : features) {
if (f instanceof WSAddressingFeature) {
return (WSAddressingFeature)f;
}
}
return null;
}
private void addAddressingFeature(AbstractFeature a) {
AbstractFeature f = getWSAddressingFeature();
if (f == null) {
features.add(a);
}
}
private void removeAddressingFeature() {
AbstractFeature f = getWSAddressingFeature();
if (f != null) {
features.remove(f);
}
}
private MTOMFeature getMTOMFeature() {
if (wsFeatures == null) {
return null;
}
for (WebServiceFeature feature : wsFeatures) {
if (feature instanceof MTOMFeature) {
return (MTOMFeature)feature;
}
}
return null;
}
final void createJaxwsBinding() {
if (getBinding() instanceof SoapBinding) {
jaxwsBinding = new SOAPBindingImpl(getEndpointInfo().getBinding(), this);
MTOMFeature mtomFeature = getMTOMFeature();
if (mtomFeature != null && mtomFeature.isEnabled()) {
((SOAPBinding)jaxwsBinding).setMTOMEnabled(true);
}
} else if (getBinding() instanceof XMLBinding) {
jaxwsBinding = new HTTPBindingImpl(getEndpointInfo().getBinding(), this);
} else {
//REVISIT: Should not get here, though some bindings like JBI
//did not implement their own Binding type.
jaxwsBinding = new DefaultBindingImpl(this);
}
}
public void addHandlerInterceptors() {
List> in = super.getInInterceptors();
List> out = super.getOutInterceptors();
List> outFault = super.getOutFaultInterceptors();
List> inFault = super.getInFaultInterceptors();
in.add(logicalInInterceptor);
out.add(logicalOutInterceptor);
inFault.add(logicalFaultInInterceptor);
outFault.add(logicalFaultOutInterceptor);
if (soapHandlerInterceptor != null) {
in.add(soapHandlerInterceptor);
out.add(soapHandlerInterceptor);
}
if (soapFaultInInterceptor != null) {
inFault.add(soapFaultInInterceptor);
}
if (soapFaultOutInterceptor != null) {
outFault.add(soapFaultOutInterceptor);
}
}
public void removeHandlerInterceptors() {
List> in = super.getInInterceptors();
List> out = super.getOutInterceptors();
List> outFault = super.getOutFaultInterceptors();
List> inFault = super.getInFaultInterceptors();
in.remove(logicalInInterceptor);
out.remove(logicalOutInterceptor);
inFault.remove(logicalFaultInInterceptor);
outFault.remove(logicalFaultOutInterceptor);
if (soapHandlerInterceptor != null) {
in.remove(soapHandlerInterceptor);
out.remove(soapHandlerInterceptor);
}
if (soapFaultInInterceptor != null) {
inFault.remove(soapFaultInInterceptor);
}
if (soapFaultOutInterceptor != null) {
outFault.remove(soapFaultOutInterceptor);
}
}
}