org.apache.cxf.jaxws.JaxWsClientProxy 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
The newest version!
/**
* 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;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Binding;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.EndpointReference;
import javax.xml.ws.Response;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext.Scope;
import javax.xml.ws.http.HTTPBinding;
import javax.xml.ws.http.HTTPException;
import javax.xml.ws.soap.SOAPBinding;
import javax.xml.ws.soap.SOAPFaultException;
import org.w3c.dom.Node;
import org.apache.cxf.binding.soap.SoapFault;
import org.apache.cxf.binding.soap.saaj.SAAJFactoryResolver;
import org.apache.cxf.binding.soap.saaj.SAAJUtils;
import org.apache.cxf.common.i18n.Message;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.ClientCallback;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.jaxws.context.WrappedMessageContext;
import org.apache.cxf.jaxws.support.JaxWsEndpointImpl;
import org.apache.cxf.service.invoker.MethodDispatcher;
import org.apache.cxf.service.model.BindingOperationInfo;
public class JaxWsClientProxy extends org.apache.cxf.frontend.ClientProxy implements
BindingProvider {
public static final String THREAD_LOCAL_REQUEST_CONTEXT = "thread.local.request.context";
private static final Logger LOG = LogUtils.getL7dLogger(JaxWsClientProxy.class);
private Binding binding;
private EndpointReferenceBuilder builder;
public JaxWsClientProxy(Client c, Binding b) {
super(c);
this.binding = b;
setupEndpointAddressContext(getClient().getEndpoint());
this.builder = new EndpointReferenceBuilder((JaxWsEndpointImpl)getClient().getEndpoint());
}
public void close() throws IOException {
super.close();
binding = null;
builder = null;
}
private void setupEndpointAddressContext(Endpoint endpoint) {
// NOTE for jms transport the address would be null
if (null != endpoint && null != endpoint.getEndpointInfo().getAddress()) {
getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
endpoint.getEndpointInfo().getAddress());
}
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (client == null) {
throw new IllegalStateException("The client has been closed.");
}
Endpoint endpoint = getClient().getEndpoint();
String address = endpoint.getEndpointInfo().getAddress();
MethodDispatcher dispatcher = (MethodDispatcher)endpoint.getService().get(
MethodDispatcher.class
.getName());
Object[] params = args;
if (null == params) {
params = new Object[0];
}
BindingOperationInfo oi = dispatcher.getBindingOperation(method, endpoint);
if (oi == null) {
// check for method on BindingProvider and Object
if (method.getDeclaringClass().equals(BindingProvider.class)
|| method.getDeclaringClass().equals(Object.class)
|| method.getDeclaringClass().equals(Closeable.class)) {
try {
return method.invoke(this, params);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
Message msg = new Message("NO_BINDING_OPERATION_INFO", LOG, method.getName());
throw new WebServiceException(msg.toString());
}
client.getRequestContext().put(Method.class.getName(), method);
boolean isAsync = isAsync(method);
Object result = null;
try {
if (isAsync) {
result = invokeAsync(method, oi, params);
} else {
result = invokeSync(method, oi, params);
}
} catch (WebServiceException wex) {
throw wex;
} catch (Exception ex) {
for (Class> excls : method.getExceptionTypes()) {
if (excls.isInstance(ex)) {
throw ex;
}
}
if (ex instanceof Fault && ex.getCause() instanceof IOException) {
throw new WebServiceException(ex.getMessage(), ex.getCause());
}
if (getBinding() instanceof HTTPBinding) {
HTTPException exception = new HTTPException(HttpURLConnection.HTTP_INTERNAL_ERROR);
exception.initCause(ex);
throw exception;
} else if (getBinding() instanceof SOAPBinding) {
SOAPFault soapFault = createSoapFault((SOAPBinding)getBinding(), ex);
if (soapFault == null) {
throw new WebServiceException(ex);
}
SOAPFaultException exception = new SOAPFaultException(soapFault);
if (ex instanceof Fault && ex.getCause() != null) {
exception.initCause(ex.getCause());
} else {
exception.initCause(ex);
}
throw exception;
} else {
throw new WebServiceException(ex);
}
} finally {
if (addressChanged(address)) {
setupEndpointAddressContext(getClient().getEndpoint());
}
}
Map respContext = client.getResponseContext();
Map scopes = CastUtils.cast((Map, ?>)respContext.get(WrappedMessageContext.SCOPES));
if (scopes != null) {
for (Map.Entry scope : scopes.entrySet()) {
if (scope.getValue() == Scope.HANDLER) {
respContext.remove(scope.getKey());
}
}
}
return adjustObject(result);
}
boolean isAsync(Method m) {
return m.getName().endsWith("Async")
&& (Future.class.equals(m.getReturnType())
|| Response.class.equals(m.getReturnType()));
}
static SOAPFault createSoapFault(SOAPBinding binding, Exception ex) throws SOAPException {
SOAPFault soapFault;
try {
soapFault = binding.getSOAPFactory().createFault();
} catch (Throwable t) {
//probably an old version of saaj or something that is not allowing createFault
//method to work. Try the saaj 1.2 method of doing this.
try {
soapFault = binding.getMessageFactory().createMessage()
.getSOAPPart().getEnvelope().getBody().addFault();
} catch (Throwable t2) {
//still didn't work, we'll just throw what we have
return null;
}
}
if (ex instanceof SoapFault) {
if (!soapFault.getNamespaceURI().equals(((SoapFault)ex).getFaultCode().getNamespaceURI())
&& SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE
.equals(((SoapFault)ex).getFaultCode().getNamespaceURI())) {
//change to 1.1
try {
soapFault = SAAJFactoryResolver.createSOAPFactory(null).createFault();
} catch (Throwable t) {
//ignore
}
}
final boolean isSoap11 = SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(soapFault.getNamespaceURI());
if (isSoap11 || ((SoapFault)ex).getLang() == null) {
soapFault.setFaultString(((SoapFault)ex).getReason());
} else {
soapFault.setFaultString(((SoapFault)ex).getReason(), stringToLocale(((SoapFault)ex).getLang()));
}
SAAJUtils.setFaultCode(soapFault, ((SoapFault)ex).getFaultCode());
String role = ((SoapFault)ex).getRole();
if (role != null) {
soapFault.setFaultActor(role);
}
if (((SoapFault)ex).getSubCodes() != null && !isSoap11) {
// set the subcode only if it is supported (e.g, 1.2)
for (QName fsc : ((SoapFault)ex).getSubCodes()) {
soapFault.appendFaultSubcode(fsc);
}
}
if (((SoapFault)ex).hasDetails()) {
Node nd = soapFault.getOwnerDocument().importNode(((SoapFault)ex).getDetail(),
true);
nd = nd.getFirstChild();
soapFault.addDetail();
while (nd != null) {
Node next = nd.getNextSibling();
soapFault.getDetail().appendChild(nd);
nd = next;
}
}
} else {
String msg = ex.getMessage();
if (msg != null) {
soapFault.setFaultString(msg);
}
}
return soapFault;
}
private static Locale stringToLocale(String locale) {
// use the IETF BCP 47 delimiter but accept the toString delimiter for cxf 2.7.x
final String ch;
if (locale.indexOf('_') > 0) {
LOG.log(Level.WARNING, "invalid IETF BCP 47 language tag: {0}", locale);
ch = "_";
} else {
ch = "-";
}
String parts[] = locale.split(ch, 0);
if (parts.length == 1) {
return new Locale(parts[0]);
} else if (parts.length == 2) {
return new Locale(parts[0], parts[1]);
} else {
return new Locale(parts[0], parts[1], parts[2]);
}
}
private boolean addressChanged(String address) {
return !(address == null
|| getClient().getEndpoint().getEndpointInfo() == null
|| address.equals(getClient().getEndpoint().getEndpointInfo().getAddress()));
}
@SuppressWarnings("unchecked")
private Object invokeAsync(Method method, BindingOperationInfo oi, Object[] params) throws Exception {
client.setExecutor(getClient().getEndpoint().getExecutor());
AsyncHandler