Home » synapse-1.2-src » org.apache.synapse.mediators.transform » [javadoc | source]

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
   10    *   http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    *  Unless required by applicable law or agreed to in writing,
   13    *  software distributed under the License is distributed on an
   14    *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    *  KIND, either express or implied.  See the License for the
   16    *  specific language governing permissions and limitations
   17    *  under the License.
   18    */
   19   
   20   package org.apache.synapse.mediators.transform;
   21   
   22   import org.apache.axiom.om.OMAbstractFactory;
   23   import org.apache.axiom.om.OMDocument;
   24   import org.apache.axiom.om.OMElement;
   25   import org.apache.axiom.om.OMFactory;
   26   import org.apache.axiom.soap;
   27   import org.apache.axis2.AxisFault;
   28   import org.apache.axis2.addressing.RelatesTo;
   29   import org.apache.synapse.MessageContext;
   30   import org.apache.synapse.SynapseException;
   31   import org.apache.synapse.core.axis2.Axis2MessageContext;
   32   import org.apache.synapse.mediators.AbstractMediator;
   33   import org.apache.synapse.util.xpath.SynapseXPath;
   34   
   35   import javax.xml.namespace.QName;
   36   import java.net.URI;
   37   import java.util.Iterator;
   38   
   39   /**
   40    * This transforms the current message instance into a SOAP Fault message. The
   41    * SOAP version for the fault message could be explicitly specified. Else if the
   42    * original message was SOAP 1.1 the fault will also be SOAP 1.1 else, SOAP 1.2
   43    *
   44    * This class exposes methods to set SOAP 1.1 and 1.2 fault elements and uses
   45    * these as required.
   46    *
   47    * Directs the fault messages' "To" EPR to the "FaultTo" or the "ReplyTo" or to
   48    * null of the original SOAP message
   49    */
   50   public class FaultMediator extends AbstractMediator {
   51   
   52       public static final String WSA_ACTION = "Action";
   53       /** Make a SOAP 1.1 fault */
   54       public static final int SOAP11 = 1;
   55       /** Make a SOAP 1.2 fault */
   56       public static final int SOAP12 = 2;
   57       /** Make a POX fault */
   58       public static final int POX = 3;
   59       /** Holds the SOAP version to be used to make the fault, if specified */
   60       private int soapVersion;
   61   
   62       // -- fault elements --
   63       /** The fault code QName to be used */
   64       private QName faultCodeValue = null;
   65       /** An XPath expression that will give the fault code QName at runtime */
   66       private SynapseXPath faultCodeExpr = null;
   67       /** The fault reason to be used */
   68       private String faultReasonValue = null;
   69       /** An XPath expression that will give the fault reason string at runtime */
   70       private SynapseXPath faultReasonExpr = null;
   71       /** The fault node URI to be used */
   72       private URI faultNode = null;
   73       /** The fault role URI to be used - if applicable */
   74       private URI faultRole = null;
   75       /** The fault detail to be used */
   76       private String faultDetail = null;
   77       /** An XPath expression that will give the fault code QName at runtime */    
   78       private SynapseXPath faultDetailExpr = null;
   79   
   80       public boolean mediate(MessageContext synCtx) {
   81   
   82           boolean traceOn = isTraceOn(synCtx);
   83           boolean traceOrDebugOn = isTraceOrDebugOn(traceOn);
   84   
   85           if (traceOrDebugOn) {
   86               traceOrDebug(traceOn, "Start : Fault mediator");
   87   
   88               if (traceOn && trace.isTraceEnabled()) {
   89                   trace.trace("Message : " + synCtx.getEnvelope());
   90               }
   91           }
   92   
   93           switch (soapVersion) {
   94               case SOAP11:
   95                   return makeSOAPFault(synCtx, SOAP11, traceOrDebugOn, traceOn);
   96               case SOAP12:
   97                   return makeSOAPFault(synCtx, SOAP12, traceOrDebugOn, traceOn);
   98               case POX:
   99                   return makePOXFault(synCtx, traceOrDebugOn, traceOn);
  100   
  101               default : {
  102                   // if this is a POX or REST message then make a POX fault
  103                   if (synCtx.isDoingPOX() || synCtx.isDoingGET()) {
  104                       
  105                       return makePOXFault(synCtx, traceOrDebugOn, traceOn);
  106   
  107                   } else {
  108                       
  109                       // determine from current message's SOAP envelope namespace
  110                       SOAPEnvelope envelop = synCtx.getEnvelope();
  111                       if (envelop != null) {
  112                           
  113                           if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(
  114                               envelop.getNamespace().getNamespaceURI())) {
  115   
  116                               soapVersion = SOAP12;
  117                               return makeSOAPFault(synCtx, SOAP12, traceOrDebugOn, traceOn);
  118   
  119                           } else {
  120                               soapVersion = SOAP11;
  121                               return makeSOAPFault(synCtx, SOAP11, traceOrDebugOn, traceOn);
  122                           }
  123                           
  124                       } else {
  125                           // default to SOAP 11
  126                           return makeSOAPFault(synCtx, SOAP11, traceOrDebugOn, traceOn);
  127                       }
  128                   }
  129               }
  130           }
  131       }
  132   
  133       private boolean makePOXFault(MessageContext synCtx, boolean traceOrDebugOn, boolean traceOn) {
  134   
  135           OMFactory fac = synCtx.getEnvelope().getOMFactory();
  136           OMElement faultPayload = fac.createOMElement(new QName("Exception"));
  137   
  138           if (faultDetail != null) {
  139   
  140               if (traceOrDebugOn) {
  141                   traceOrDebug(traceOn, "Setting the fault detail : "
  142                       + faultDetail + " as the POX Fault");
  143               }
  144   
  145               faultPayload.setText(faultDetail);
  146   
  147           } else if (faultDetailExpr != null) {
  148   
  149               String faultDetail = faultDetailExpr.stringValueOf(synCtx);
  150   
  151               if (traceOrDebugOn) {
  152                   traceOrDebug(traceOn, "Setting the fault detail : "
  153                           + faultDetail + " as the POX Fault");
  154               }
  155   
  156               faultPayload.setText(faultDetail);
  157               
  158           } else if (faultReasonValue != null) {
  159   
  160               if (traceOrDebugOn) {
  161                   traceOrDebug(traceOn, "Setting the fault reason : "
  162                       + faultReasonValue + " as the POX Fault");
  163               }
  164   
  165               faultPayload.setText(faultReasonValue);
  166   
  167           } else if (faultReasonExpr != null) {
  168   
  169               String faultReason = faultReasonExpr.stringValueOf(synCtx);
  170               faultPayload.setText(faultReason);
  171   
  172               if (traceOrDebugOn) {
  173                   traceOrDebug(traceOn, "Setting the fault reason : "
  174                       + faultReason + " as the POX Fault");
  175               }
  176           }
  177   
  178           SOAPBody body = synCtx.getEnvelope().getBody();
  179           if (body != null) {
  180   
  181               if (body.getFirstElement() != null) {
  182                   body.getFirstElement().detach();
  183               }
  184   
  185               synCtx.setFaultResponse(true);
  186               ((Axis2MessageContext) synCtx).getAxis2MessageContext().setProcessingFault(true);
  187   
  188               if (traceOrDebugOn) {
  189                   String msg = "Original SOAP Message : " + synCtx.getEnvelope().toString() +
  190                       "POXFault Message created : " + faultPayload.toString();
  191                   if (traceOn && trace.isTraceEnabled()) {
  192                       trace.trace(msg);
  193                   }
  194                   if (log.isTraceEnabled()) {
  195                       log.trace(msg);
  196                   }
  197               }
  198               
  199               body.addChild(faultPayload);
  200           }
  201   
  202           return true;
  203       }
  204   
  205       /**
  206        * Actual transformation of the current message into a fault message
  207        * @param synCtx the current message context
  208        * @param soapVersion SOAP version of the resulting fault desired
  209        * @param traceOrDebugOn is trace or debug logging on?
  210        * @param traceOn is tracing on?
  211        * @return true, always
  212        */
  213       private boolean makeSOAPFault(MessageContext synCtx, int soapVersion,
  214           boolean traceOrDebugOn, boolean traceOn) {
  215   
  216           if (traceOrDebugOn) {
  217               traceOrDebug(traceOn, "Creating a SOAP "
  218                       + (soapVersion == SOAP11 ? "1.1" : "1.2") + " fault");
  219           }
  220   
  221           // get the correct SOAP factory to be used
  222           SOAPFactory factory = (soapVersion == SOAP11 ?
  223                   OMAbstractFactory.getSOAP11Factory() : OMAbstractFactory.getSOAP12Factory());
  224   
  225           // create the SOAP fault document and envelope
  226           OMDocument soapFaultDocument = factory.createOMDocument();
  227           SOAPEnvelope faultEnvelope = factory.getDefaultFaultEnvelope();
  228           soapFaultDocument.addChild(faultEnvelope);
  229   
  230           // create the fault element  if it is need
  231           SOAPFault fault = faultEnvelope.getBody().getFault();
  232           if(fault == null){
  233               fault = factory.createSOAPFault();
  234           }
  235   
  236           // populate it
  237           setFaultCode(synCtx, factory, fault);
  238           setFaultResaon(synCtx, factory, fault);
  239           setFaultNode(factory, fault);
  240           setFaultRole(factory, fault);
  241           setFaultDetail(synCtx, factory, fault);
  242   
  243           // set the all headers of original SOAP Envelope to the Fault Envelope
  244           if (synCtx.getEnvelope() != null) {
  245               SOAPHeader soapHeader = synCtx.getEnvelope().getHeader();
  246               if (soapHeader != null) {
  247                   for (Iterator iter = soapHeader.examineAllHeaderBlocks(); iter.hasNext();) {
  248                       Object o = iter.next();
  249                       if (o instanceof SOAPHeaderBlock) {
  250                           SOAPHeaderBlock header = (SOAPHeaderBlock) o;
  251                           faultEnvelope.getHeader().addChild(header);
  252                       } else if (o instanceof OMElement) {
  253                           faultEnvelope.getHeader().addChild((OMElement) o);
  254                       }
  255                   }
  256               }
  257           }
  258   
  259           if (traceOrDebugOn) {
  260               String msg =
  261                   "Original SOAP Message : " + synCtx.getEnvelope().toString() +
  262                   "Fault Message created : " + faultEnvelope.toString();
  263               if (traceOn && trace.isTraceEnabled()) {
  264                   trace.trace(msg);
  265               }
  266               if (log.isTraceEnabled()) {
  267                   log.trace(msg);
  268               }
  269           }
  270   
  271           // overwrite current message envelope with new fault envelope
  272           try {
  273               synCtx.setEnvelope(faultEnvelope);
  274           } catch (AxisFault af) {
  275               handleException("Error replacing current SOAP envelope " +
  276                       "with the fault envelope", af, synCtx);
  277           }
  278   
  279           if (synCtx.getFaultTo() != null) {
  280               synCtx.setTo(synCtx.getFaultTo());
  281           } else if (synCtx.getReplyTo() != null) {
  282               synCtx.setTo(synCtx.getReplyTo());
  283           } else {
  284               synCtx.setTo(null);
  285           }
  286   
  287           // set original messageID as relatesTo
  288           if(synCtx.getMessageID() != null) {
  289               RelatesTo relatesTo = new RelatesTo(synCtx.getMessageID());
  290               synCtx.setRelatesTo(new RelatesTo[] { relatesTo });
  291           }
  292   
  293           if (traceOrDebugOn) {
  294               traceOrDebug(traceOn, "End : Fault mediator");
  295           }
  296           
  297           return true;
  298       }
  299   
  300       private void setFaultCode(MessageContext synCtx, SOAPFactory factory, SOAPFault fault) {
  301   
  302           QName fault_code = null;
  303   
  304           if (faultCodeValue == null && faultCodeExpr == null) {
  305               handleException("A valid fault code QName value or expression is required", synCtx);
  306           } else if (faultCodeValue != null) {
  307               fault_code = faultCodeValue;
  308           } else {
  309               fault_code = QName.valueOf(faultCodeExpr.stringValueOf(synCtx));
  310           }
  311   
  312           SOAPFaultCode code = factory.createSOAPFaultCode();
  313           switch(soapVersion){
  314               case SOAP11:
  315                   code.setText(fault_code);
  316                   break;
  317               case SOAP12:
  318                   SOAPFaultValue value = factory.createSOAPFaultValue(code);
  319                   value.setText(fault_code);
  320                   break;
  321           }
  322           fault.setCode(code);
  323       }
  324   
  325       private void setFaultResaon(MessageContext synCtx, SOAPFactory factory, SOAPFault fault) {
  326           String reasonString = null;
  327   
  328           if (faultReasonValue == null && faultReasonExpr == null) {
  329               handleException("A valid fault reason value or expression is required", synCtx);
  330           } else if (faultReasonValue != null) {
  331               reasonString = faultReasonValue;
  332           } else {
  333               reasonString = faultReasonExpr.stringValueOf(synCtx);
  334           }
  335   
  336           SOAPFaultReason reason = factory.createSOAPFaultReason();
  337           switch(soapVersion){
  338               case SOAP11:
  339                   reason.setText(reasonString);
  340                   break;
  341               case SOAP12:
  342                   SOAPFaultText text = factory.createSOAPFaultText();
  343                   text.setText(reasonString);
  344                   reason.addSOAPText(text);
  345                   break;
  346           }
  347           fault.setReason(reason);
  348       }
  349   
  350       private void setFaultNode(SOAPFactory factory, SOAPFault fault) {
  351           if (faultNode != null) {
  352               SOAPFaultNode soapfaultNode = factory.createSOAPFaultNode();
  353               soapfaultNode.setNodeValue(faultNode.toString());
  354               fault.setNode(soapfaultNode);
  355           }
  356       }
  357   
  358       private void setFaultRole(SOAPFactory factory, SOAPFault fault) {
  359           if (faultRole != null) {
  360               SOAPFaultRole soapFaultRole = factory.createSOAPFaultRole();
  361               soapFaultRole.setRoleValue(faultRole.toString());
  362               fault.setRole(soapFaultRole);
  363           }
  364       }
  365   
  366       private void setFaultDetail(MessageContext synCtx, SOAPFactory factory, SOAPFault fault) {
  367           if (faultDetail != null) {
  368               SOAPFaultDetail soapFaultDetail = factory.createSOAPFaultDetail();
  369               soapFaultDetail.setText(faultDetail);
  370               fault.setDetail(soapFaultDetail);
  371           } else if (faultDetailExpr != null) {
  372               SOAPFaultDetail soapFaultDetail = factory.createSOAPFaultDetail();
  373               soapFaultDetail.setText(faultDetailExpr.stringValueOf(synCtx));
  374               fault.setDetail(soapFaultDetail);
  375           } else if (fault.getDetail() != null) {
  376               // work around for a rampart issue in the following thread
  377               // http://www.nabble.com/Access-to-validation-error-message-tf4498668.html#a13284520
  378               fault.getDetail().detach();
  379           }
  380       }
  381   
  382       public int getSoapVersion() {
  383           return soapVersion;
  384       }
  385   
  386       public void setSoapVersion(int soapVersion) {
  387           this.soapVersion = soapVersion;
  388       }
  389   
  390       public QName getFaultCodeValue() {
  391           return faultCodeValue;
  392       }
  393   
  394       public void setFaultCodeValue(QName faultCodeValue) {
  395   
  396           if (soapVersion == SOAP11) {
  397               this.faultCodeValue = faultCodeValue;
  398   
  399           } else if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(
  400                   faultCodeValue.getNamespaceURI()) &&
  401                   (SOAP12Constants.FAULT_CODE_DATA_ENCODING_UNKNOWN.equals(
  402                           faultCodeValue.getLocalPart()) ||
  403                           SOAP12Constants.FAULT_CODE_MUST_UNDERSTAND.equals(
  404                                   faultCodeValue.getLocalPart()) ||
  405                           SOAP12Constants.FAULT_CODE_RECEIVER.equals(
  406                                   faultCodeValue.getLocalPart()) ||
  407                           SOAP12Constants.FAULT_CODE_SENDER.equals(
  408                                   faultCodeValue.getLocalPart()) ||
  409                           SOAP12Constants.FAULT_CODE_VERSION_MISMATCH.equals(
  410                                   faultCodeValue.getLocalPart())) ) {
  411   
  412               this.faultCodeValue = faultCodeValue;
  413   
  414           } else {
  415               handleException("Invalid Fault code value for a SOAP 1.2 fault : " + faultCodeValue);
  416           }
  417       }
  418   
  419       public SynapseXPath getFaultCodeExpr() {
  420           return faultCodeExpr;
  421       }
  422   
  423       public void setFaultCodeExpr(SynapseXPath faultCodeExpr) {
  424           this.faultCodeExpr = faultCodeExpr;
  425       }
  426   
  427       public String getFaultReasonValue() {
  428           return faultReasonValue;
  429       }
  430   
  431       public void setFaultReasonValue(String faultReasonValue) {
  432           this.faultReasonValue = faultReasonValue;
  433       }
  434   
  435       public SynapseXPath getFaultReasonExpr() {
  436           return faultReasonExpr;
  437       }
  438   
  439       public void setFaultReasonExpr(SynapseXPath faultReasonExpr) {
  440           this.faultReasonExpr = faultReasonExpr;
  441       }
  442   
  443       public URI getFaultNode() {
  444           return faultNode;
  445       }
  446   
  447       public void setFaultNode(URI faultNode) {
  448           if (soapVersion == SOAP11) {
  449               handleException("A fault node does not apply to a SOAP 1.1 fault");
  450           }
  451           this.faultNode = faultNode;
  452       }
  453   
  454       public URI getFaultRole() {
  455           return faultRole;
  456       }
  457   
  458       public void setFaultRole(URI faultRole) {
  459           this.faultRole = faultRole;
  460       }
  461   
  462       public String getFaultDetail() {
  463           return faultDetail;
  464       }
  465   
  466       public void setFaultDetail(String faultDetail) {
  467           this.faultDetail = faultDetail;
  468       }
  469   
  470       public SynapseXPath getFaultDetailExpr() {
  471           return faultDetailExpr;
  472       }
  473   
  474       public void setFaultDetailExpr(SynapseXPath faultDetailExpr) {
  475           this.faultDetailExpr = faultDetailExpr;
  476       }
  477   
  478       private void handleException(String msg) {
  479           log.error(msg);
  480           throw new SynapseException(msg);
  481       }
  482   }

Home » synapse-1.2-src » org.apache.synapse.mediators.transform » [javadoc | source]