You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fx-dev@ws.apache.org by di...@apache.org on 2004/08/09 18:36:19 UTC
cvs commit: ws-fx/addressing/src/org/apache/axis/message/addressing/handler AxisClientSideAddressingHandler.java AxisServerSideAddressingHandler.java GenericAxisHandler.java ServerSideAddressingHandler.java
dims 2004/08/09 09:36:19
Added: addressing/src/org/apache/axis/message/addressing/handler
AxisClientSideAddressingHandler.java
AxisServerSideAddressingHandler.java
GenericAxisHandler.java
ServerSideAddressingHandler.java
Log:
Contribution from Ian Springer <ia...@hp.com>
===================================================
The attached classes are intended to replace the existing class
AddressingHandler. They are in the following class hierarchies, which
are designed to facilitate easy porting to any JAX-RPC container:
AxisClientSideAddressingHandler extends ClientSideAddressingHandler
extends AbstractAddressingHandler
AxisServerSideAddressingHandler extends ServerSideAddressingHandler
extends AbstractAddressingHandler
AbstractAddressingHandler is an abstract base class containing
functionality shared by server-side and client-side handlers.
ClientSideAddressingHandler and ServerSideAddressingHandler are
client-side and server-side JAX-RPC handlers, respectively, that should
work within any JAX-RPC container. They contain a few methods that can
be overridden by platform-specific subclasses to provide more robust
functionality. AxisClientSideAddressingHandler and
AxisServerSideAddressingHandler are subclasses of the platform-neutral
handlers that implement the Axis Handler interface and that leverage
some Axis-specific APIs in overridden methods.
All platform-neutral classes are below the org.apache.ws.addressing
package, and all Axis-specific classes are below
org.apache.axis.message.addressing.handler.
I've written unit tests that test the key methods - handleRequest() and
handleResponse() - in the platform-neutral handlers.
Additionally, I've written an interface and factory that allow one to
easily plug in different UUID-generation impls. The platform-neutral
handlers utilize the opensource JUG library as the UUID generator, but
use refelction to avoid a compile-time dependency on it. The
Axis-specific handlers utilize the UUID generator that comes with Axis.
There are still a number of data structure classes and interfaces in
Apache Addressing that use Axis-specific classes like MessageElement and
URI. These could be refactored fairly easily to be platform-neutral.
Once this is done, Apache Addressing will be a portable WS-Addressing
implementation that can be deployed and utilized on any JAX-RPC
container. I think this will broaden the project's user and developer
base.
===================================================
Revision Changes Path
1.1 ws-fx/addressing/src/org/apache/axis/message/addressing/handler/AxisClientSideAddressingHandler.java
Index: AxisClientSideAddressingHandler.java
===================================================================
/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed 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.axis.message.addressing.handler;
import org.apache.axis.AxisFault;
import org.apache.axis.Handler;
import org.apache.ws.addressing.handler.ClientSideAddressingHandler;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.rpc.handler.MessageContext;
import java.util.Hashtable;
import java.util.List;
/**
* Axis-specific client-side WS-Addressing handler.
*
* @author Davanum Srinivas (dims@yahoo.com)
* @author Ian P. Springer
*/
public class AxisClientSideAddressingHandler extends ClientSideAddressingHandler implements Handler
{
private GenericAxisHandler axisHelperHandler = new GenericAxisHandler( this );
/**
* @see org.apache.axis.Handler#init()
*/
public void init()
{
axisHelperHandler.init();
}
/**
* @see org.apache.axis.Handler#cleanup()
*/
public void cleanup()
{
axisHelperHandler.cleanup();
}
/**
* @see org.apache.axis.Handler#onFault(org.apache.axis.MessageContext)
*/
public void onFault( MessageContext msgContext )
{
axisHelperHandler.onFault( (org.apache.axis.MessageContext) msgContext );
}
/**
* @see org.apache.axis.Handler#canHandleBlock(javax.xml.namespace.QName)
*/
public boolean canHandleBlock( QName qname )
{
return ( axisHelperHandler.canHandleBlock( qname ) );
}
/**
* @see org.apache.axis.Handler#setOption(java.lang.String, java.lang.Object)
*/
public void setOption( String name,
Object value )
{
axisHelperHandler.setOption( name, value );
}
/**
* Set a default value for the given option: if the option is not already set, then set it. if the option is already set,
* then do not set it.
* <p/>
* If this is called multiple times, the first with a non-null value if 'value' will set the default, remaining calls will
* be ignored.
* <p/>
* Returns true if value set (by this call), otherwise false;
*/
public boolean setOptionDefault( String name,
Object value )
{
return axisHelperHandler.setOptionDefault( name, value );
}
/**
* @see org.apache.axis.Handler#getOption(java.lang.String)
*/
public Object getOption( String name )
{
return axisHelperHandler.getOption( name );
}
/**
* @see org.apache.axis.Handler#getOptions()
*/
public Hashtable getOptions()
{
return axisHelperHandler.getOptions();
}
/**
* @see org.apache.axis.Handler#setOptions(java.util.Hashtable)
*/
public void setOptions( Hashtable opts )
{
axisHelperHandler.setOptions( opts );
}
/**
* @see org.apache.axis.Handler#setName(java.lang.String)
*/
public void setName( String name )
{
axisHelperHandler.setName( name );
}
/**
* @see org.apache.axis.Handler#getName()
*/
public String getName()
{
return axisHelperHandler.getName();
}
/**
* @see org.apache.axis.Handler#getDeploymentData(org.w3c.dom.Document)
*/
public Element getDeploymentData( Document doc )
{
return axisHelperHandler.getDeploymentData( doc );
}
/**
* @see org.apache.axis.Handler#getUnderstoodHeaders()
*/
public List getUnderstoodHeaders()
{
return axisHelperHandler.getUnderstoodHeaders();
}
/**
* @see org.apache.axis.Handler#generateWSDL(org.apache.axis.MessageContext)
*/
public void generateWSDL( org.apache.axis.MessageContext msgContext ) throws AxisFault
{
axisHelperHandler.generateWSDL( msgContext );
}
/**
* @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)
*/
public void invoke( org.apache.axis.MessageContext msgContext ) throws AxisFault
{
axisHelperHandler.invoke( msgContext );
}
/**
* @see org.apache.axis.Handler#onFault(org.apache.axis.MessageContext)
*/
public void onFault( org.apache.axis.MessageContext msgContext )
{
axisHelperHandler.onFault( msgContext );
}
/**
* Use the UUID generator that comes with Axis.
*
* @return a UUID
*/
protected String generateUUId()
{
return axisHelperHandler.generateUUId();
}
/**
* Axis-specific impl of {@link org.apache.ws.addressing.handler.ClientSideAddressingHandler#getSOAPAction(javax.xml.rpc.handler.MessageContext)}.
*
* @param msgContext JAX-RPC message context
*
* @return the value of the SOAPAction HTTP header
*/
protected String getSOAPAction( MessageContext msgContext )
{
org.apache.axis.MessageContext axisMsgContext = (org.apache.axis.MessageContext) msgContext;
return axisMsgContext.getSOAPActionURI();
}
/**
* Axis-specific impl of {@link org.apache.ws.addressing.handler.ClientSideAddressingHandler#setSOAPAction(javax.xml.rpc.handler.MessageContext,
* String)}.
*
* @param msgContext JAX-RPC message context
* @param actionURI the SOAPAction URI to be set
*/
protected void setSOAPAction( MessageContext msgContext, String actionURI )
{
org.apache.axis.MessageContext axisMsgContext = (org.apache.axis.MessageContext) msgContext;
axisMsgContext.setUseSOAPAction( true );
axisMsgContext.setSOAPActionURI( actionURI );
}
}
1.1 ws-fx/addressing/src/org/apache/axis/message/addressing/handler/AxisServerSideAddressingHandler.java
Index: AxisServerSideAddressingHandler.java
===================================================================
/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed 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.axis.message.addressing.handler;
import org.apache.axis.AxisFault;
import org.apache.axis.Handler;
import org.apache.axis.Message;
import org.apache.axis.message.addressing.AddressingHeaders;
import org.apache.axis.message.addressing.Constants;
import org.apache.axis.message.addressing.EndpointReference;
import org.apache.ws.addressing.handler.ServerSideAddressingHandler;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.Service;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPBody;
import java.util.Hashtable;
import java.util.List;
/**
* Axis-specific server-side WS-Addressing handler.
*
* @author Davanum Srinivas (dims@yahoo.com)
* @author Ian P. Springer
*/
public class AxisServerSideAddressingHandler extends ServerSideAddressingHandler implements Handler
{
private GenericAxisHandler axisHelperHandler = new GenericAxisHandler( this );
/**
* @see org.apache.axis.Handler#init()
*/
public void init()
{
axisHelperHandler.init();
}
/**
* @see org.apache.axis.Handler#cleanup()
*/
public void cleanup()
{
axisHelperHandler.cleanup();
}
/**
* @see org.apache.axis.Handler#onFault(org.apache.axis.MessageContext)
*/
public void onFault( MessageContext msgContext )
{
axisHelperHandler.onFault( (org.apache.axis.MessageContext) msgContext );
}
/**
* @see org.apache.axis.Handler#canHandleBlock(javax.xml.namespace.QName)
*/
public boolean canHandleBlock( QName qname )
{
return ( axisHelperHandler.canHandleBlock( qname ) );
}
/**
* @see org.apache.axis.Handler#setOption(java.lang.String, java.lang.Object)
*/
public void setOption( String name,
Object value )
{
axisHelperHandler.setOption( name, value );
}
/**
* Set a default value for the given option:
* if the option is not already set, then set it.
* if the option is already set, then do not set it.
* <p/>
* If this is called multiple times, the first with a non-null value
* if 'value' will set the default, remaining calls will be ignored.
* <p/>
* Returns true if value set (by this call), otherwise false;
*/
public boolean setOptionDefault( String name,
Object value )
{
return axisHelperHandler.setOptionDefault( name, value );
}
/**
* @see org.apache.axis.Handler#getOption(java.lang.String)
*/
public Object getOption( String name )
{
return axisHelperHandler.getOption( name );
}
/**
* @see org.apache.axis.Handler#getOptions()
*/
public Hashtable getOptions()
{
return axisHelperHandler.getOptions();
}
/**
* @see org.apache.axis.Handler#setOptions(java.util.Hashtable)
*/
public void setOptions( Hashtable opts )
{
axisHelperHandler.setOptions( opts );
}
/**
* @see org.apache.axis.Handler#setName(java.lang.String)
*/
public void setName( String name )
{
axisHelperHandler.setName( name );
}
/**
* @see org.apache.axis.Handler#getName()
*/
public String getName()
{
return axisHelperHandler.getName();
}
/**
* @see org.apache.axis.Handler#getDeploymentData(org.w3c.dom.Document)
*/
public Element getDeploymentData( Document doc )
{
return axisHelperHandler.getDeploymentData( doc );
}
/**
* @see org.apache.axis.Handler#getUnderstoodHeaders()
*/
public List getUnderstoodHeaders()
{
return axisHelperHandler.getUnderstoodHeaders();
}
/**
* @see org.apache.axis.Handler#generateWSDL(org.apache.axis.MessageContext)
*/
public void generateWSDL( org.apache.axis.MessageContext msgContext ) throws AxisFault
{
axisHelperHandler.generateWSDL( msgContext );
}
/**
* @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)
*/
public void invoke( org.apache.axis.MessageContext msgContext ) throws AxisFault
{
axisHelperHandler.invoke( msgContext );
}
/**
* @see org.apache.axis.Handler#onFault(org.apache.axis.MessageContext)
*/
public void onFault( org.apache.axis.MessageContext msgContext )
{
axisHelperHandler.onFault( msgContext );
}
/**
* Use the UUID generator that comes with Axis.
*
* @return a UUID
*/
protected String generateUUId()
{
return axisHelperHandler.generateUUId();
}
// TODO: not sure if overriding this method is even necessary.
protected void forwardMessage( SOAPMessageContext soapMsgContext, EndpointReference endpointRef )
{
try
{
Service service = getService( soapMsgContext );
Call call = service.createCall();
call.setTargetEndpointAddress( endpointRef.getAddress().toString() );
( (org.apache.axis.client.Call) call ).setRequestMessage( (Message) soapMsgContext.getMessage() );
AddressingHeaders addrHeaders = buildAddressingHeadersForMessageForward( soapMsgContext, endpointRef );
call.setProperty( Constants.ENV_ADDRESSING_REQUEST_HEADERS, addrHeaders );
configureCall( call, soapMsgContext );
call.invoke( new Object[0] );
SOAPBody responseBody = soapMsgContext.getMessage().getSOAPPart().getEnvelope().getBody();
removeAllChildElements( responseBody );
}
catch ( Exception e )
{
throw new JAXRPCException( "Failed to forward SOAP message." );
}
}
protected void setTargetService( SOAPMessageContext soapMsgContext, AddressingHeaders headers )
throws Exception
{
org.apache.axis.MessageContext axisMsgContext = (org.apache.axis.MessageContext) soapMsgContext;
// TODO: why is the below code necessary? - add comments
if ( axisMsgContext.getService() == null &&
axisMsgContext.getTargetService() == null )
{
axisMsgContext.setTargetService( getTargetServiceName( headers ) );
// This is to ensure the SOAPEnvelope is rebuilt with the right type mappings and
// MessageContext is set with the right properties.
if ( axisMsgContext.getTargetService() != null )
{
( (Message) axisMsgContext.getMessage() ).getSOAPPartAsString();
}
}
}
private AddressingHeaders buildAddressingHeadersForMessageForward( SOAPMessageContext soapMsgContext, EndpointReference endpointRef )
{
AddressingHeaders headers = null;
if ( soapMsgContext != null )
{
headers = (AddressingHeaders) soapMsgContext.getProperty( Constants.ENV_ADDRESSING_RESPONSE_HEADERS );
}
if ( headers == null )
{
headers = new AddressingHeaders( endpointRef );
}
return headers;
}
}
1.1 ws-fx/addressing/src/org/apache/axis/message/addressing/handler/GenericAxisHandler.java
Index: GenericAxisHandler.java
===================================================================
/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed 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.axis.message.addressing.handler;
import org.apache.axis.AxisFault;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.message.addressing.uuid.AxisUUIdGenerator;
import org.apache.ws.addressing.uuid.UUIdGeneratorFactory;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.handler.Handler;
/**
* Helper class to which the Axis-specific JAX-RPC handlers in this package
* can delegate methods defined in the Axis {@link org.apache.axis.Handler}
* interface. This is one so that the Axis handler base class
* {@link BasicHandler} can be leveraged.
*
* @author Ian P. Springer
*/
class GenericAxisHandler extends BasicHandler
{
private Handler jaxRpcHandler;
public GenericAxisHandler( Handler handler )
{
jaxRpcHandler = handler;
}
/**
* Impl of {@link org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)}
* that delegates to either
* JAX-RPC {@link Handler#handleRequest(javax.xml.rpc.handler.MessageContext)} or
* JAX-RPC {@link Handler#handleResponse(javax.xml.rpc.handler.MessageContext)},
* depending upon whether the handler chain pivot has been passed yet or not.
*/
public void invoke( org.apache.axis.MessageContext msgContext ) throws AxisFault
{
if ( !msgContext.getPastPivot() )
{
jaxRpcHandler.handleRequest( msgContext );
}
else
{
jaxRpcHandler.handleResponse( msgContext );
}
}
/**
* Impl of {@link org.apache.axis.Handler#onFault(org.apache.axis.MessageContext)}
* that delegates to
* JAX-RPC {@link Handler#handleFault(javax.xml.rpc.handler.MessageContext)}.
*/
public void onFault( org.apache.axis.MessageContext msgContext )
{
jaxRpcHandler.handleFault( msgContext );
}
/**
* Use the UUID generator that comes with Axis.
*
* @return a UUID
*/
String generateUUId()
{
try
{
return UUIdGeneratorFactory.createUUIdGenerator( AxisUUIdGenerator.class ).generateUUId();
}
catch ( RuntimeException re )
{
throw new JAXRPCException( "Failed to generate UUId using Axis UUId generator " + AxisUUIdGenerator.class.getName() + ".", re );
}
}
}
1.1 ws-fx/addressing/src/org/apache/axis/message/addressing/handler/ServerSideAddressingHandler.java
Index: ServerSideAddressingHandler.java
===================================================================
/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed 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.ws.addressing.handler;
import org.apache.axis.message.addressing.Action;
import org.apache.axis.message.addressing.AddressingHeaders;
import org.apache.axis.message.addressing.AttributedURI;
import org.apache.axis.message.addressing.Constants;
import org.apache.axis.message.addressing.EndpointReference;
import org.apache.axis.message.addressing.MessageID;
import org.apache.axis.message.addressing.To;
import org.apache.axis.message.addressing.util.AddressingUtils;
import org.apache.axis.types.URI;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.TransformerFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A server-side JAX-RPC {@link javax.xml.rpc.handler.Handler} that extracts
* WS-Addressing headers from incoming SOAP requests and inserts them into
* outgoing SOAP responses.
*
* @author Davanum Srinivas (dims@yahoo.com)
* @author Ian P. Springer <ia...@hp.com>
*/
public class ServerSideAddressingHandler extends AbstractAddressingHandler
{
private static final Log LOG =
LogFactory.getLog( ServerSideAddressingHandler.class.getName() );
/**
* thread local that gives each thread its own TransformerFactory (since it is not thread-safe)
*/
public static ThreadLocal TRANSFORMER_FACTORY =
new ThreadLocal()
{
protected synchronized Object initialValue()
{
return TransformerFactory.newInstance();
}
};
public boolean handleRequest( MessageContext msgContext )
{
SOAPMessageContext soapMsgContext = (SOAPMessageContext) msgContext;
try
{
SOAPMessage msg = soapMsgContext.getMessage();
if ( msg == null )
{
return CONTINUE_HANDLER_CHAIN_PROCESSING;
}
AddressingHeaders headers =
new AddressingHeaders( msg.getSOAPPart().getEnvelope(),
getActor(),
true,
isRemoveHeadersEnabled(),
false,
getReferencePropertyQNames() );
msgContext.setProperty( Constants.ENV_ADDRESSING_REQUEST_HEADERS,
headers );
// set the target service based on To header if it hasn't already been
// determined. NOTE: May want to add an option to override later.
setTargetService( soapMsgContext, headers );
}
catch ( Exception e )
{
if ( LOG.isDebugEnabled() )
{
e.printStackTrace();
}
throw new JAXRPCException( "unexpected error in handleRequest()", e );
}
return CONTINUE_HANDLER_CHAIN_PROCESSING;
}
public boolean handleResponse( MessageContext msgContext )
{
SOAPMessageContext soapMsgContext = (SOAPMessageContext) msgContext;
try
{
SOAPMessage msg = soapMsgContext.getMessage();
if ( msg == null )
{
return CONTINUE_HANDLER_CHAIN_PROCESSING;
}
AddressingHeaders reqHeaders =
(AddressingHeaders) msgContext.getProperty( Constants.ENV_ADDRESSING_REQUEST_HEADERS );
if ( reqHeaders == null )
{
// error?
return CONTINUE_HANDLER_CHAIN_PROCESSING;
}
AddressingHeaders resHeaders =
AddressingUtils.getResponseHeaders( msgContext );
resHeaders.setSetMustUnderstand( isMustUnderstandEnabled( msgContext ) );
processFromHeader( reqHeaders, resHeaders );
processActionHeader( reqHeaders, resHeaders );
processToHeader( reqHeaders, resHeaders );
processRelatesToHeader( reqHeaders, resHeaders );
processMessageIdHeader( resHeaders );
resHeaders.toEnvelope( msg.getSOAPPart().getEnvelope(), getActor() );
processReplyToHeader( reqHeaders, soapMsgContext );
}
catch ( Exception e )
{
if ( LOG.isDebugEnabled() )
{
e.printStackTrace();
}
throw new JAXRPCException( "unexpected error in handleResponse()", e );
}
return CONTINUE_HANDLER_CHAIN_PROCESSING;
}
public boolean handleFault( MessageContext msgContext )
{
SOAPMessageContext soapMsgContext = (SOAPMessageContext) msgContext;
try
{
AddressingHeaders reqHeaders =
(AddressingHeaders) msgContext.getProperty( Constants.ENV_ADDRESSING_REQUEST_HEADERS );
if ( reqHeaders == null )
{
// error?
return CONTINUE_HANDLER_CHAIN_PROCESSING;
}
AddressingHeaders resHeaders =
AddressingUtils.getResponseHeaders( msgContext );
processFromHeader( reqHeaders, resHeaders );
// set action for fault only with 04 spec. 03 spec unclear on that issue
if ( Constants.NS_URI_ADDRESSING.equals( Constants.NS_URI_ADDRESSING_04 ) )
{
resHeaders.setAction( new Action( new URI( Constants.FAULT_ACTION ) ) );
}
addRelatesToHeader( reqHeaders, resHeaders );
addMessageIdHeader( resHeaders );
addAddressingHeadersToSOAPEnvelope( soapMsgContext, resHeaders );
processFaultToHeader( reqHeaders, soapMsgContext );
}
catch ( Exception e )
{
if ( LOG.isDebugEnabled() )
{
e.printStackTrace();
}
throw new JAXRPCException( "unexpected error in handleFault()", e );
}
return CONTINUE_HANDLER_CHAIN_PROCESSING;
}
/**
* Forward the SOAP message contained in the specified SOAP message context
* on to the specified endpoint reference.
*
* @param soapMsgContext
* @param endpointRef
*/
protected void forwardMessage( SOAPMessageContext soapMsgContext, EndpointReference endpointRef )
{
try
{
SOAPConnection soapConn = SOAPConnectionFactory.newInstance().createConnection();
soapConn.call( soapMsgContext.getMessage(), toURL( endpointRef.getAddress() ) );
soapConn.close();
SOAPBody responseBody = soapMsgContext.getMessage().getSOAPPart().getEnvelope().getBody();
removeAllChildElements( responseBody );
}
catch ( Exception e )
{
throw new JAXRPCException( "Failed to forward SOAP message." );
}
}
private URL toURL( AttributedURI addr )
throws MalformedURLException
{
return new URL( addr.toString() );
}
/**
* Override this method if you need something other than the default Service.<br>
* The service returned by this method is used in creating the new Call object.
* Something like: <br>
* <pre>
* Service service = getService(msgContext);
* Call call = service.createCall()
* call.setTargetEndpointAddress(toEndPointReference.getAddress().toString());
* </pre>
*
* @param msgContext
*
* @return
*/
protected javax.xml.rpc.Service getService( MessageContext msgContext ) throws ServiceException
{
return ServiceFactory.newInstance().createService( new QName( "" ) );
}
/**
* Override this method to prepare the new call, for instance to add
* properties from the old MessageContext that may be needed by other
* handlers.
*
* @param call Call object about to be invoked
* @param oldContext MessageContext of the original request/response.
*/
protected void configureCall( Call call, MessageContext oldContext )
{
return; // intentionally empty
}
/**
* Can be overridden by subclasses to customize how the wsa:to header is interpreted.
*/
protected String getTargetServiceName( AddressingHeaders headers )
throws Exception
{
To toURI = headers.getTo();
if ( toURI == null )
{
return null;
}
String to = toURI.getPath();
if ( to == null )
{
return null;
}
// set the target service
return ( to.substring( to.lastIndexOf( '/' ) + 1 ) );
}
/**
* Platform-specific subclasses can optionally implement this method.
*
* @param soapMsgContext
* @param headers
*
* @throws Exception
*/
protected void setTargetService( SOAPMessageContext soapMsgContext, AddressingHeaders headers )
throws Exception
{
return; // intentionally empty
}
private void processFromHeader( AddressingHeaders requestAddrHeaders, AddressingHeaders responseAddrHeaders )
{
EndpointReference fromEPR = responseAddrHeaders.getFrom();
if ( fromEPR == null )
{
To toURI = requestAddrHeaders.getTo();
if ( toURI != null )
{
fromEPR = new EndpointReference( toURI );
fromEPR.setProperties( requestAddrHeaders.getReferenceProperties() );
responseAddrHeaders.setFrom( fromEPR );
}
}
}
private void processActionHeader( AddressingHeaders requestAddrHeaders, AddressingHeaders responseAddrHeaders )
throws URI.MalformedURIException
{
Action action = responseAddrHeaders.getAction();
if ( action == null )
{
// not set - try request headers
action = requestAddrHeaders.getAction();
if ( action != null )
{
responseAddrHeaders.setAction( new Action( new URI( action.toString() +
"Response" ) ) );
}
}
}
private void processToHeader( AddressingHeaders requestAddrHeaders, AddressingHeaders responseAddrHeaders )
throws URI.MalformedURIException
{
if ( responseAddrHeaders.getFrom() == null && requestAddrHeaders.getFrom() != null )
{
responseAddrHeaders.setTo( requestAddrHeaders.getFrom().getAddress() );
}
else
{
responseAddrHeaders.setTo( new To( Constants.NS_URI_ANONYMOUS ) );
}
}
private void processRelatesToHeader( AddressingHeaders requestAddrHeaders, AddressingHeaders responseAddrHeaders )
throws URI.MalformedURIException
{
MessageID msgID = requestAddrHeaders.getMessageID();
if ( msgID != null )
{
responseAddrHeaders.addRelatesTo( msgID.toString(),
Constants.QNAME_RESPONSE );
}
}
private void processMessageIdHeader( AddressingHeaders responseAddrHeaders )
throws URI.MalformedURIException
{
responseAddrHeaders.setMessageID( createMessageID() );
}
private void processReplyToHeader( AddressingHeaders requestAddrHeaders, SOAPMessageContext soapMsgContext )
throws Exception
{
EndpointReference replyTo = requestAddrHeaders.getReplyTo();
if ( replyTo != null )
{
AttributedURI address = replyTo.getAddress();
if ( address != null )
{
String uri = address.toString();
if ( uri != null && !uri.equals( Constants.NS_URI_ANONYMOUS ) )
{
forwardMessage( soapMsgContext, replyTo );
}
}
}
}
private void addAddressingHeadersToSOAPEnvelope( SOAPMessageContext soapMsgContext, AddressingHeaders resHeaders )
throws Exception
{
SOAPMessage msg = soapMsgContext.getMessage();
if ( msg == null )
{
throw new JAXRPCException( "Unable to obtain response message from SOAP message context." );
}
resHeaders.toEnvelope( msg.getSOAPPart().getEnvelope() );
}
private void processFaultToHeader( AddressingHeaders reqHeaders, SOAPMessageContext soapMsgContext )
throws Exception
{
EndpointReference faultTo = reqHeaders.getFaultTo();
if ( faultTo != null )
{
AttributedURI address = faultTo.getAddress();
if ( address != null && address.toString() != null )
{
forwardMessage( soapMsgContext, faultTo );
}
}
}
private void addRelatesToHeader( AddressingHeaders reqHeaders, AddressingHeaders resHeaders )
throws URI.MalformedURIException
{
MessageID msgID;
msgID = reqHeaders.getMessageID();
if ( msgID != null )
{
resHeaders.addRelatesTo( msgID.toString(),
Constants.QNAME_RESPONSE );
}
}
private void addMessageIdHeader( AddressingHeaders resHeaders )
throws URI.MalformedURIException
{
MessageID msgID;
msgID = new MessageID( new URI( "uuid:" + generateUUId() ) );
resHeaders.setMessageID( msgID );
}
/**
* Removes all child elements from the specified {@link javax.xml.soap.SOAPElement}.
* NOTE: w
*/
protected static void removeAllChildElements( SOAPElement soapElem )
{
Iterator iter = soapElem.getChildElements();
// NOTE: Convert iterator to list to avoid ConcurrentModificationExceptions
// caused by modifying items in an iterator during iteration
List children = toList( iter );
for ( int i = 0; i < children.size(); i++ )
{
Node child = (Node) children.get( i );
if ( child.getParentElement() != null )
{
child.detachNode();
child.recycleNode();
}
}
}
private static List toList( Iterator iter )
{
List list = new ArrayList();
while ( iter.hasNext() )
{
list.add( iter.next() );
}
return list;
}
}