@Test
 public void createSoap12Fault() {
   SoapBinding sb = control.createMock(SoapBinding.class);
   EasyMock.expect(sb.getSoapVersion()).andReturn(Soap12.getInstance());
   setupJMSFault(true, SoapJMSConstants.getMismatchedSoapActionQName(), null);
   control.replay();
   SoapFaultFactory factory = new SoapFaultFactory(sb);
   SoapFault fault = (SoapFault) factory.createFault(jmsFault);
   assertEquals("reason", fault.getReason());
   assertEquals(Soap12.getInstance().getSender(), fault.getFaultCode());
   assertEquals(SoapJMSConstants.getMismatchedSoapActionQName(), fault.getSubCode());
   assertNull(fault.getDetail());
   assertNull(fault.getCause());
   control.verify();
 }
 private boolean isSOAP12(Message message) {
   if (message.getExchange().getBinding() instanceof SoapBinding) {
     SoapBinding binding = (SoapBinding) message.getExchange().getBinding();
     if (binding.getSoapVersion() == Soap12.getInstance()) {
       return true;
     }
   }
   return false;
 }
  /**
   * Mediate message flow.
   *
   * @param message the current message
   * @param isFault true if a fault is being mediated
   * @return true if processing should continue on dispatch path
   */
  protected boolean mediate(Message message, boolean isFault) {
    boolean continueProcessing = true;
    if (ContextUtils.isOutbound(message)) {
      if (usingAddressing(message)) {
        // request/response MAPs must be aggregated
        aggregate(message, isFault);
      }
      AddressingProperties theMaps =
          ContextUtils.retrieveMAPs(message, false, ContextUtils.isOutbound(message));
      if (null != theMaps) {
        if (ContextUtils.isRequestor(message)) {
          assertAddressing(message, theMaps.getReplyTo(), theMaps.getFaultTo());
        } else {
          checkReplyTo(message, theMaps);
        }
      }
    } else if (!ContextUtils.isRequestor(message)) {
      // responder validates incoming MAPs
      AddressingProperties maps = getMAPs(message, false, false);
      // check responses
      if (maps != null) {
        checkAddressingResponses(maps.getReplyTo(), maps.getFaultTo());
        assertAddressing(message, maps.getReplyTo(), maps.getFaultTo());
      }
      boolean isOneway = message.getExchange().isOneWay();
      if (null == maps && !addressingRequired) {
        return false;
      }
      continueProcessing = validateIncomingMAPs(maps, message);
      if (maps != null) {
        AddressingProperties theMaps =
            ContextUtils.retrieveMAPs(message, false, ContextUtils.isOutbound(message));
        if (null != theMaps) {
          assertAddressing(message, theMaps.getReplyTo(), theMaps.getFaultTo());
        }

        if (isOneway || !ContextUtils.isGenericAddress(maps.getReplyTo())) {
          InternalContextUtils.rebaseResponse(maps.getReplyTo(), maps, message);
        }
        if (!isOneway) {
          if (ContextUtils.isNoneAddress(maps.getReplyTo())) {
            LOG.warning("Detected NONE value in ReplyTo WSA header for request-respone MEP");
          } else {
            // ensure the inbound MAPs are available in both the full & fault
            // response messages (used to determine relatesTo etc.)
            ContextUtils.propogateReceivedMAPs(maps, message.getExchange());
          }
        }
      }
      if (continueProcessing) {
        // any faults thrown from here on can be correlated with this message
        message.put(FaultMode.class, FaultMode.LOGICAL_RUNTIME_FAULT);
      } else {
        // validation failure => dispatch is aborted, response MAPs
        // must be aggregated
        // isFault = true;
        // aggregate(message, isFault);
        if (isSOAP12(message)) {
          SoapFault soap12Fault =
              new SoapFault(
                  ContextUtils.retrieveMAPFaultReason(message), Soap12.getInstance().getSender());
          soap12Fault.setSubCode(
              new QName(Names.WSA_NAMESPACE_NAME, ContextUtils.retrieveMAPFaultName(message)));
          throw soap12Fault;
        }
        throw new SoapFault(
            ContextUtils.retrieveMAPFaultReason(message),
            new QName(Names.WSA_NAMESPACE_NAME, ContextUtils.retrieveMAPFaultName(message)));
      }
    } else {
      AddressingProperties theMaps =
          ContextUtils.retrieveMAPs(message, false, ContextUtils.isOutbound(message));
      if (null != theMaps) {
        assertAddressing(message, theMaps.getReplyTo(), theMaps.getFaultTo());
      }
      // If the wsa policy is enabled , but the client sets the
      // WSAddressingFeature.isAddressingRequired to false , we need to assert all WSA assertion to
      // true
      if (!ContextUtils.isOutbound(message)
          && ContextUtils.isRequestor(message)
          && getWSAddressingFeature(message) != null
          && !getWSAddressingFeature(message).isAddressingRequired()) {
        assertAddressing(message);
      }
      // CXF-3060 :If wsa policy is not enforced, AddressingProperties map is null and
      // AddressingFeature.isRequired, requestor checks inbound message and throw exception
      if (null == theMaps
          && !ContextUtils.isOutbound(message)
          && ContextUtils.isRequestor(message)
          && getWSAddressingFeature(message) != null
          && getWSAddressingFeature(message).isAddressingRequired()) {
        boolean missingWsaHeader = false;
        AssertionInfoMap aim = message.get(AssertionInfoMap.class);
        if (aim == null || aim.size() == 0) {
          missingWsaHeader = true;
        }
        if (aim != null && aim.size() > 0) {
          missingWsaHeader = true;
          QName[] types =
              new QName[] {
                MetadataConstants.ADDRESSING_ASSERTION_QNAME,
                MetadataConstants.USING_ADDRESSING_2004_QNAME,
                MetadataConstants.USING_ADDRESSING_2005_QNAME,
                MetadataConstants.USING_ADDRESSING_2006_QNAME
              };
          for (QName type : types) {
            for (AssertionInfo assertInfo : aim.getAssertionInfo(type)) {
              if (assertInfo.isAsserted()) {
                missingWsaHeader = false;
              }
            }
          }
        }
        if (missingWsaHeader) {
          throw new SoapFault(
              "MISSING_ACTION_MESSAGE",
              BUNDLE,
              new QName(Names.WSA_NAMESPACE_NAME, Names.HEADER_REQUIRED_NAME));
        }
      }
      if (MessageUtils.isPartialResponse(message)
          && message.getExchange().getOutMessage() != null) {
        // marked as a partial response, let's see if it really is
        MessageInfo min = message.get(MessageInfo.class);
        MessageInfo mout = message.getExchange().getOutMessage().get(MessageInfo.class);
        if (min != null
            && mout != null
            && min.getOperation() == mout.getOperation()
            && message.getContent(List.class) != null) {
          // the in and out messages are on the same operation
          // and we were able to get a response for it.
          message.remove(Message.PARTIAL_RESPONSE_MESSAGE);
        }
      }
    }
    return continueProcessing;
  }
  /**
   * Asserts all Addressing assertions for the current message, regardless their nested Policies.
   *
   * @param message the current message
   */
  private void assertAddressing(
      Message message, EndpointReferenceType replyTo, EndpointReferenceType faultTo) {
    AssertionInfoMap aim = message.get(AssertionInfoMap.class);
    if (null == aim) {
      return;
    }
    if (faultTo == null) {
      faultTo = replyTo;
    }
    boolean anonReply = ContextUtils.isGenericAddress(replyTo);
    boolean anonFault = ContextUtils.isGenericAddress(faultTo);
    boolean onlyAnonymous = anonReply && anonFault;
    boolean hasAnonymous = anonReply || anonFault;

    QName[] types =
        new QName[] {
          MetadataConstants.ADDRESSING_ASSERTION_QNAME,
          MetadataConstants.USING_ADDRESSING_2004_QNAME,
          MetadataConstants.USING_ADDRESSING_2005_QNAME,
          MetadataConstants.USING_ADDRESSING_2006_QNAME
        };

    for (QName type : types) {
      assertAssertion(aim, type);
      if (type.equals(MetadataConstants.ADDRESSING_ASSERTION_QNAME)) {
        if (onlyAnonymous) {
          assertAssertion(aim, MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME);
        } else if (!hasAnonymous) {
          assertAssertion(aim, MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME);
        }
      } else if (type.equals(MetadataConstants.ADDRESSING_ASSERTION_QNAME_0705)) {
        if (onlyAnonymous) {
          assertAssertion(aim, MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME_0705);
        } else if (!hasAnonymous) {
          assertAssertion(aim, MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME_0705);
        }
      }
    }
    if (!MessageUtils.isRequestor(message) && !MessageUtils.isOutbound(message)) {
      // need to throw an appropriate fault for these
      Collection<AssertionInfo> aicNonAnon =
          aim.getAssertionInfo(MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME);
      Collection<AssertionInfo> aicNonAnon2 =
          aim.getAssertionInfo(MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME_0705);
      Collection<AssertionInfo> aicAnon =
          aim.getAssertionInfo(MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME);
      Collection<AssertionInfo> aicAnon2 =
          aim.getAssertionInfo(MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME_0705);
      boolean hasAnon =
          (aicAnon != null && !aicAnon.isEmpty()) || (aicAnon2 != null && !aicAnon2.isEmpty());
      boolean hasNonAnon =
          (aicNonAnon != null && !aicNonAnon.isEmpty())
              || (aicNonAnon2 != null && !aicNonAnon2.isEmpty());

      if (hasAnonymous && hasNonAnon && !hasAnon) {
        message.put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
        if (isSOAP12(message)) {
          SoapFault soap12Fault =
              new SoapFault(
                  "Found anonymous address but non-anonymous required",
                  Soap12.getInstance().getSender());
          soap12Fault.addSubCode(
              new QName(Names.WSA_NAMESPACE_NAME, "OnlyNonAnonymousAddressSupported"));
          throw soap12Fault;
        }

        throw new SoapFault(
            "Found anonymous address but non-anonymous required",
            new QName(Names.WSA_NAMESPACE_NAME, "OnlyNonAnonymousAddressSupported"));
      } else if (!onlyAnonymous && !hasNonAnon && hasAnon) {
        message.put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
        if (isSOAP12(message)) {
          SoapFault soap12Fault =
              new SoapFault(
                  "Found non-anonymous address but only anonymous supported",
                  Soap12.getInstance().getSender());
          soap12Fault.addSubCode(
              new QName(Names.WSA_NAMESPACE_NAME, "OnlyAnonymousAddressSupported"));
          throw soap12Fault;
        }

        throw new SoapFault(
            "Found non-anonymous address but only anonymous supported",
            new QName(Names.WSA_NAMESPACE_NAME, "OnlyAnonymousAddressSupported"));
      }
    }
  }