Clover coverage report - Apache Addressing - 1.0
Coverage timestamp: Tue Mar 22 2005 07:59:24 EST
file stats: LOC: 450   Methods: 22
NCLOC: 335   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ServerSideAddressingHandler.java 25% 41.1% 40.9% 36.6%
coverage coverage
 1   
 /*
 2   
  * Copyright  2004 The Apache Software Foundation.
 3   
  *
 4   
  *  Licensed under the Apache License, Version 2.0 (the "License");
 5   
  *  you may not use this file except in compliance with the License.
 6   
  *  You may obtain a copy of the License at
 7   
  *
 8   
  *      http://www.apache.org/licenses/LICENSE-2.0
 9   
  *
 10   
  *  Unless required by applicable law or agreed to in writing, software
 11   
  *  distributed under the License is distributed on an "AS IS" BASIS,
 12   
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13   
  *  See the License for the specific language governing permissions and
 14   
  *  limitations under the License.
 15   
  *
 16   
  */
 17   
 package org.apache.ws.addressing.handler;
 18   
 
 19   
 import org.apache.axis.message.addressing.Action;
 20   
 import org.apache.axis.message.addressing.AddressingHeaders;
 21   
 import org.apache.axis.message.addressing.AttributedURI;
 22   
 import org.apache.axis.message.addressing.Constants;
 23   
 import org.apache.axis.message.addressing.EndpointReference;
 24   
 import org.apache.axis.message.addressing.MessageID;
 25   
 import org.apache.axis.message.addressing.To;
 26   
 import org.apache.axis.message.addressing.util.AddressingUtils;
 27   
 import org.apache.axis.types.URI;
 28   
 import org.apache.commons.logging.Log;
 29   
 import org.apache.commons.logging.LogFactory;
 30   
 
 31   
 import javax.xml.namespace.QName;
 32   
 import javax.xml.rpc.Call;
 33   
 import javax.xml.rpc.JAXRPCException;
 34   
 import javax.xml.rpc.ServiceException;
 35   
 import javax.xml.rpc.ServiceFactory;
 36   
 import javax.xml.rpc.handler.MessageContext;
 37   
 import javax.xml.rpc.handler.soap.SOAPMessageContext;
 38   
 import javax.xml.soap.Node;
 39   
 import javax.xml.soap.SOAPBody;
 40   
 import javax.xml.soap.SOAPConnection;
 41   
 import javax.xml.soap.SOAPConnectionFactory;
 42   
 import javax.xml.soap.SOAPElement;
 43   
 import javax.xml.soap.SOAPMessage;
 44   
 import javax.xml.transform.TransformerFactory;
 45   
 import java.net.MalformedURLException;
 46   
 import java.net.URL;
 47   
 import java.util.ArrayList;
 48   
 import java.util.Iterator;
 49   
 import java.util.List;
 50   
 
 51   
 /**
 52   
  * A server-side JAX-RPC {@link javax.xml.rpc.handler.Handler} that extracts
 53   
  * WS-Addressing headers from incoming SOAP requests and inserts them into
 54   
  * outgoing SOAP responses.
 55   
  *
 56   
  * @author Davanum Srinivas (dims@yahoo.com)
 57   
  * @author Ian P. Springer <ian_springer@hp.com>
 58   
  */
 59   
 public class ServerSideAddressingHandler extends AbstractAddressingHandler
 60   
 {
 61   
 
 62   
    private static final Log LOG =
 63   
          LogFactory.getLog( ServerSideAddressingHandler.class.getName() );
 64   
 
 65   
    /**
 66   
     * thread local that gives each thread its own TransformerFactory (since it is not thread-safe)
 67   
     */
 68   
    public static ThreadLocal TRANSFORMER_FACTORY =
 69   
          new ThreadLocal()
 70   
          {
 71  0
             protected synchronized Object initialValue()
 72   
             {
 73  0
                return TransformerFactory.newInstance();
 74   
             }
 75   
          };
 76   
 
 77  2
    public boolean handleRequest( MessageContext msgContext )
 78   
    {
 79  2
       SOAPMessageContext soapMsgContext = (SOAPMessageContext) msgContext;
 80  2
       try
 81   
       {
 82  2
          SOAPMessage msg = soapMsgContext.getMessage();
 83  2
          if ( msg == null )
 84   
          {
 85  0
             return CONTINUE_HANDLER_CHAIN_PROCESSING;
 86   
          }
 87  2
          AddressingHeaders headers =
 88   
                new AddressingHeaders( msg.getSOAPPart().getEnvelope(),
 89   
                      getActor(),
 90   
                      true,
 91   
                      isRemoveHeadersEnabled(),
 92   
                      false,
 93   
                      getReferencePropertyQNames() );
 94   
 
 95  2
          if (headers.getTo()==null)
 96   
          {
 97   
             // not a WS-A request; let it pass thru w/out doing anything
 98  0
             return CONTINUE_HANDLER_CHAIN_PROCESSING;
 99   
          }
 100  2
          if (headers.getAction()==null)
 101   
          {
 102   
             // should we throw a SOAPFaultException here?
 103  0
             LOG.debug("WS-A request to endpoint " + headers.getTo() + " is missing the required wsa:Action header.");
 104   
          }
 105  2
          msgContext.setProperty( Constants.ENV_ADDRESSING_REQUEST_HEADERS,
 106   
                headers );
 107   
 
 108   
          // set the target service based on To header if it hasn't already been
 109   
          // determined.  NOTE: May want to add an option to override later.
 110  2
          setTargetService( soapMsgContext, headers );
 111   
       }
 112   
       catch ( Exception e )
 113   
       {
 114  0
          if ( LOG.isDebugEnabled() )
 115   
          {
 116  0
             e.printStackTrace();
 117   
          }
 118  0
          throw new JAXRPCException( "unexpected error in handleRequest()", e );
 119   
       }
 120  2
       return CONTINUE_HANDLER_CHAIN_PROCESSING;
 121   
    }
 122   
 
 123  1
    public boolean handleResponse( MessageContext msgContext )
 124   
    {
 125  1
       SOAPMessageContext soapMsgContext = (SOAPMessageContext) msgContext;
 126  1
       try
 127   
       {
 128  1
          SOAPMessage msg = soapMsgContext.getMessage();
 129  1
          if ( msg == null )
 130   
          {
 131  0
             return CONTINUE_HANDLER_CHAIN_PROCESSING;
 132   
          }
 133   
 
 134  1
          AddressingHeaders reqHeaders =
 135   
                (AddressingHeaders) msgContext.getProperty( Constants.ENV_ADDRESSING_REQUEST_HEADERS );
 136   
 
 137  1
          if ( reqHeaders == null )
 138   
          {
 139   
             // not a WS-A response; let it pass thru w/out doing anything
 140  0
             return CONTINUE_HANDLER_CHAIN_PROCESSING;
 141   
          }
 142  1
          AddressingHeaders resHeaders =
 143   
                AddressingUtils.getResponseHeaders( msgContext );
 144  1
          resHeaders.setSetMustUnderstand( isMustUnderstandEnabled( msgContext ) );
 145  1
          processFromHeader( reqHeaders, resHeaders );
 146  1
          processActionHeader( reqHeaders, resHeaders );
 147  1
          processToHeader( reqHeaders, resHeaders );
 148  1
          processRelatesToHeader( reqHeaders, resHeaders );
 149  1
          processMessageIdHeader( resHeaders );
 150  1
          resHeaders.toEnvelope( msg.getSOAPPart().getEnvelope(), getActor() );
 151  1
          processReplyToHeader( reqHeaders, soapMsgContext );
 152   
       }
 153   
       catch ( Exception e )
 154   
       {
 155  0
          if ( LOG.isDebugEnabled() )
 156   
          {
 157  0
             e.printStackTrace();
 158   
          }
 159  0
          throw new JAXRPCException( "unexpected error in handleResponse()", e );
 160   
       }
 161  1
       return CONTINUE_HANDLER_CHAIN_PROCESSING;
 162   
    }
 163   
 
 164  0
    public boolean handleFault( MessageContext msgContext )
 165   
    {
 166  0
       SOAPMessageContext soapMsgContext = (SOAPMessageContext) msgContext;
 167  0
       try
 168   
       {
 169  0
          AddressingHeaders reqHeaders =
 170   
                (AddressingHeaders) msgContext.getProperty( Constants.ENV_ADDRESSING_REQUEST_HEADERS );
 171  0
          if ( reqHeaders == null )
 172   
          {
 173   
             // not a WS-A fault; let it pass thru w/out doing anything
 174  0
             return CONTINUE_HANDLER_CHAIN_PROCESSING;
 175   
          }
 176  0
          AddressingHeaders resHeaders =
 177   
                AddressingUtils.getResponseHeaders( msgContext );
 178  0
          processFromHeader( reqHeaders, resHeaders );
 179   
          // set action for fault only with 04 spec; 03 spec unclear on that issue
 180  0
          if ( ! reqHeaders.getNamespaceURI().equals( Constants.NS_URI_ADDRESSING_2003_03 ) )
 181   
          {
 182  0
             resHeaders.setAction( new Action( new URI( Constants.FAULT_ACTION ) ) );
 183   
          }
 184  0
          addRelatesToHeader( reqHeaders, resHeaders );
 185  0
          addMessageIdHeader( resHeaders );
 186  0
          addAddressingHeadersToSOAPEnvelope( soapMsgContext, resHeaders );
 187  0
          processFaultToHeader( reqHeaders, soapMsgContext );
 188   
       }
 189   
       catch ( Exception e )
 190   
       {
 191  0
          if ( LOG.isDebugEnabled() )
 192   
          {
 193  0
             e.printStackTrace();
 194   
          }
 195  0
          throw new JAXRPCException( "unexpected error in handleFault()", e );
 196   
       }
 197  0
       return CONTINUE_HANDLER_CHAIN_PROCESSING;
 198   
    }
 199   
 
 200   
    /**
 201   
     * Forward the SOAP message contained in the specified SOAP message context
 202   
     * on to the specified endpoint reference.
 203   
     *
 204   
     * @param soapMsgContext
 205   
     * @param endpointRef
 206   
     */
 207  0
    protected void forwardMessage( SOAPMessageContext soapMsgContext, EndpointReference endpointRef )
 208   
    {
 209  0
       try
 210   
       {
 211  0
          SOAPConnection soapConn = SOAPConnectionFactory.newInstance().createConnection();
 212  0
          soapConn.call( soapMsgContext.getMessage(), toURL( endpointRef.getAddress() ) );
 213  0
          soapConn.close();
 214  0
          SOAPBody responseBody = soapMsgContext.getMessage().getSOAPPart().getEnvelope().getBody();
 215  0
          removeAllChildElements( responseBody );
 216   
       }
 217   
       catch ( Exception e )
 218   
       {
 219  0
          throw new JAXRPCException( "Failed to forward SOAP message." );
 220   
       }
 221   
    }
 222   
 
 223  0
    private URL toURL( AttributedURI addr )
 224   
          throws MalformedURLException
 225   
    {
 226  0
       return new URL( addr.toString() );
 227   
    }
 228   
 
 229   
    /**
 230   
     * Override this method if you need something other than the default Service.<br>
 231   
     * The service returned by this method is used in creating the new Call object.
 232   
     * Something like: <br>
 233   
     * <pre>
 234   
     * Service service = getService(msgContext);
 235   
     * Call call = service.createCall()
 236   
     * call.setTargetEndpointAddress(toEndPointReference.getAddress().toString());
 237   
     * </pre>
 238   
     *
 239   
     * @param msgContext
 240   
     *
 241   
     * @return
 242   
     */
 243  0
    protected javax.xml.rpc.Service getService( MessageContext msgContext ) throws ServiceException
 244   
    {
 245  0
       return ServiceFactory.newInstance().createService( new QName( "" ) );
 246   
    }
 247   
 
 248   
    /**
 249   
     * Override this method to prepare the new call, for instance to add
 250   
     * properties from the old MessageContext that may be needed by other
 251   
     * handlers.
 252   
     *
 253   
     * @param call       Call object about to be invoked
 254   
     * @param oldContext MessageContext of the original request/response.
 255   
     */
 256  0
    protected void configureCall( Call call, MessageContext oldContext )
 257   
    {
 258  0
       return;  // intentionally empty
 259   
    }
 260   
 
 261   
    /**
 262   
     * Can be overridden by subclasses to customize how the wsa:to header is interpreted.
 263   
     */
 264  0
    protected String getTargetServiceName( AddressingHeaders headers )
 265   
          throws Exception
 266   
    {
 267  0
       To toURI = headers.getTo();
 268  0
       if ( toURI == null )
 269   
       {
 270  0
          return null;
 271   
       }
 272  0
       String to = toURI.getPath();
 273  0
       if ( to == null )
 274   
       {
 275  0
          return null;
 276   
       }
 277   
       // set the target service
 278  0
       return ( to.substring( to.lastIndexOf( '/' ) + 1 ) );
 279   
    }
 280   
 
 281   
    /**
 282   
     * Platform-specific subclasses can optionally implement this method.
 283   
     *
 284   
     * @param soapMsgContext
 285   
     * @param headers
 286   
     *
 287   
     * @throws Exception
 288   
     */
 289  2
    protected void setTargetService( SOAPMessageContext soapMsgContext, AddressingHeaders headers )
 290   
          throws Exception
 291   
    {
 292  2
       return;  // intentionally empty
 293   
    }
 294   
 
 295  1
    private void processFromHeader( AddressingHeaders requestAddrHeaders, AddressingHeaders responseAddrHeaders )
 296   
    {
 297  1
       EndpointReference fromEPR = responseAddrHeaders.getFrom();
 298  1
       if ( fromEPR == null )
 299   
       {
 300  1
          To toURI = requestAddrHeaders.getTo();
 301  1
          if ( toURI != null )
 302   
          {
 303  1
             fromEPR = new EndpointReference( toURI );
 304  1
             fromEPR.setProperties( requestAddrHeaders.getReferenceProperties() );
 305  1
             responseAddrHeaders.setFrom( fromEPR );
 306   
          }
 307   
       }
 308   
    }
 309   
 
 310  1
    private void processActionHeader( AddressingHeaders requestAddrHeaders, AddressingHeaders responseAddrHeaders )
 311   
          throws URI.MalformedURIException
 312   
    {
 313  1
       Action action = responseAddrHeaders.getAction();
 314  1
       if ( action == null )
 315   
       {
 316   
          // not set - try request headers
 317  1
          action = requestAddrHeaders.getAction();
 318  1
          if ( action != null )
 319   
          {
 320  1
             responseAddrHeaders.setAction( new Action( new URI( action.toString() +
 321   
                   "Response" ) ) );
 322   
          }
 323   
       }
 324   
    }
 325   
 
 326  1
    private void processToHeader( AddressingHeaders requestAddrHeaders, AddressingHeaders responseAddrHeaders )
 327   
          throws URI.MalformedURIException
 328   
    {
 329  1
       if ( responseAddrHeaders.getFrom() == null && requestAddrHeaders.getFrom() != null )
 330   
       {
 331  0
          responseAddrHeaders.setTo( requestAddrHeaders.getFrom().getAddress() );
 332   
       }
 333   
       else
 334   
       {
 335  1
          responseAddrHeaders.setTo( new To( Constants.NS_URI_ANONYMOUS ) );
 336   
       }
 337   
    }
 338   
 
 339  1
    private void processRelatesToHeader( AddressingHeaders requestAddrHeaders, AddressingHeaders responseAddrHeaders )
 340   
          throws URI.MalformedURIException
 341   
    {
 342  1
       MessageID msgID = requestAddrHeaders.getMessageID();
 343  1
       if ( msgID != null )
 344   
       {
 345  1
          responseAddrHeaders.addRelatesTo( msgID.toString(),
 346   
                Constants.QNAME_RESPONSE );
 347   
       }
 348   
    }
 349   
 
 350  1
    private void processMessageIdHeader( AddressingHeaders responseAddrHeaders )
 351   
          throws URI.MalformedURIException
 352   
    {
 353  1
       responseAddrHeaders.setMessageID( createMessageID() );
 354   
    }
 355   
 
 356  1
    private void processReplyToHeader( AddressingHeaders requestAddrHeaders, SOAPMessageContext soapMsgContext )
 357   
          throws Exception
 358   
    {
 359  1
       EndpointReference replyTo = requestAddrHeaders.getReplyTo();
 360  1
       if ( replyTo != null )
 361   
       {
 362  1
          AttributedURI address = replyTo.getAddress();
 363  1
          if ( address != null )
 364   
          {
 365  1
             String uri = address.toString();
 366  1
             if ( uri != null && !uri.equals( Constants.NS_URI_ANONYMOUS ) )
 367   
             {
 368  0
                forwardMessage( soapMsgContext, replyTo );
 369   
             }
 370   
          }
 371   
       }
 372   
    }
 373   
 
 374  0
    private void addAddressingHeadersToSOAPEnvelope( SOAPMessageContext soapMsgContext, AddressingHeaders resHeaders )
 375   
          throws Exception
 376   
    {
 377  0
       SOAPMessage msg = soapMsgContext.getMessage();
 378  0
       if ( msg == null )
 379   
       {
 380  0
          throw new JAXRPCException( "Unable to obtain response message from SOAP message context." );
 381   
       }
 382  0
       resHeaders.toEnvelope( msg.getSOAPPart().getEnvelope() );
 383   
    }
 384   
 
 385  0
    private void processFaultToHeader( AddressingHeaders reqHeaders, SOAPMessageContext soapMsgContext )
 386   
          throws Exception
 387   
    {
 388  0
       EndpointReference faultTo = reqHeaders.getFaultTo();
 389  0
       if ( faultTo != null )
 390   
       {
 391  0
          AttributedURI address = faultTo.getAddress();
 392  0
          if ( address != null && address.toString() != null )
 393   
          {
 394  0
             forwardMessage( soapMsgContext, faultTo );
 395   
          }
 396   
       }
 397   
    }
 398   
 
 399  0
    private void addRelatesToHeader( AddressingHeaders reqHeaders, AddressingHeaders resHeaders )
 400   
          throws URI.MalformedURIException
 401   
    {
 402  0
       MessageID msgID = reqHeaders.getMessageID();
 403  0
       if ( msgID != null )
 404   
       {
 405  0
          resHeaders.addRelatesTo( msgID.toString(),
 406   
                Constants.QNAME_RESPONSE );
 407   
       }
 408   
    }
 409   
 
 410  0
    private void addMessageIdHeader( AddressingHeaders resHeaders )
 411   
          throws URI.MalformedURIException
 412   
    {
 413  0
       MessageID msgID = new MessageID( new URI( "uuid:" + generateUUId() ) );
 414  0
       resHeaders.setMessageID( msgID );
 415   
    }
 416   
 
 417   
    /**
 418   
     * Removes all child elements from the specified {@link javax.xml.soap.SOAPElement}.
 419   
     * NOTE: w
 420   
     */
 421  0
    protected static void removeAllChildElements( SOAPElement soapElem )
 422   
    {
 423  0
       Iterator iter = soapElem.getChildElements();
 424   
       // NOTE: Convert iterator to list to avoid ConcurrentModificationExceptions
 425   
       // caused by modifying items in an iterator during iteration
 426  0
       List children = toList( iter );
 427  0
       for ( int i = 0; i < children.size(); i++ )
 428   
       {
 429  0
          Node child = (Node) children.get( i );
 430  0
          if ( child.getParentElement() != null )
 431   
          {
 432  0
             child.detachNode();
 433  0
             child.recycleNode();
 434   
          }
 435   
       }
 436   
    }
 437   
 
 438  0
    private static List toList( Iterator iter )
 439   
    {
 440  0
       List list = new ArrayList();
 441  0
       while ( iter.hasNext() )
 442   
       {
 443  0
          list.add( iter.next() );
 444   
       }
 445  0
       return list;
 446   
    }
 447   
 
 448   
 }
 449   
 
 450