All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.api.ads.common.lib.soap.jaxws.JaxWsSoapContextHandler Maven / Gradle / Ivy

Go to download

Ads APIs Client Library AppEngine components. Most users do not explicitly depend on this module, but instead depend on the AppEngine module for a specific ads API, such as "dfp-appengine".

There is a newer version: 5.8.0
Show newest version
// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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 com.google.api.ads.common.lib.soap.jaxws;

import com.google.api.ads.common.lib.conf.AdsApiConfiguration;
import com.google.api.ads.common.lib.exception.ServiceException;
import com.google.api.ads.common.lib.utils.NodeExtractor;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;

import org.w3c.dom.Node;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

/**
 * SOAP Context Handler for use with JAX-WS. Responsible for logging SOAP XML
 * messages and attaching implicit headers to the outgoing messages.
 *
 * This class is not thread-safe. Every SOAP client is expected to have its own
 * instance of this class and each SOAP call made by those clients has to be
 * atomic.
 */
public class JaxWsSoapContextHandler implements SOAPHandler {

  private String lastSoapRequest;
  private String lastSoapResponse;
  private String lastRequestId;
  private String lastServiceCalled;
  private String lastOperationCalled;
  private Set soapHeaders = new HashSet();
  private final NodeExtractor nodeExtractor;
  private final ImmutableList requestIdXPathComponents;

  /**
   * @param nodeExtractor required; used to extract request ID from SOAP responses.
   */
  public JaxWsSoapContextHandler(
      NodeExtractor nodeExtractor, AdsApiConfiguration adsApiConfiguration) {
    this.nodeExtractor = nodeExtractor;
    String requestIdXPath = adsApiConfiguration.getRequestIdXPath();
    if (!Strings.isNullOrEmpty(requestIdXPath)) {
      requestIdXPathComponents = ImmutableList.copyOf(
          Splitter.on('/').split(requestIdXPath));
    } else {
      requestIdXPathComponents = ImmutableList.of();
    }
  }

  /**
   * Captures pertinent information from SOAP messages exchanged by the SOAP
   * service this handler is attached to. Also responsible for placing custom
   * (implicit) SOAP headers on outgoing messages.
   *
   * @see SOAPHandler#handleMessage(MessageContext)
   * @param context the context of the SOAP message passing through this handler
   * @return whether this SOAP interaction should continue
   */
  @Override
  public boolean handleMessage(SOAPMessageContext context) {
    if ((Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {
      SOAPMessage soapMessage = context.getMessage();
      try {
        SOAPHeader soapHeader = soapMessage.getSOAPHeader();
        if (soapHeader == null) {
          soapHeader = soapMessage.getSOAPPart().getEnvelope().addHeader();
        }

        for (SOAPElement header : soapHeaders) {
          soapHeader.addChildElement(header);
        }
      } catch (SOAPException e) {
        throw new ServiceException("Error setting SOAP headers on outbound message.", e);
      }
      captureServiceAndOperationNames(context);
    }
    captureSoapXml(context);
    return true;
  }

  /**
   * Extracts the name of the web service and SOAP operation from a message.
   *
   * @param context the context of the SOAP message passing through this handler
   */
  @VisibleForTesting
  void captureServiceAndOperationNames(SOAPMessageContext context) {
    lastServiceCalled = ((QName) context.get(MessageContext.WSDL_SERVICE)).getLocalPart();
    try {
      lastOperationCalled = context.getMessage().getSOAPBody().getFirstChild().getLocalName();
    } catch (SOAPException e) {
      lastOperationCalled = "";
      // Fail silently. The logs will be missing the operation name for this interaction.
    }
  }

  /**
   * Returns the name of the last SOAP operation through this handler.
   */
  public String getLastOperationCalled() {
    return lastOperationCalled;
  }

  /**
   * Returns the name of the last SOAP service contacted through handler.
   */
  public String getLastServiceCalled() {
    return lastServiceCalled;
  }

  /**
   * Captures pertinent information from a message representing a SOAP fault.
   *
   * @see SOAPHandler#handleFault(MessageContext)
   * @param context the context of the SOAP message passing through this handler
   * @return whether this SOAP interaction should continue
   */
  @Override
  public boolean handleFault(SOAPMessageContext context) {
      captureSoapXml(context);
      return true;
  }

  /**
   * Captures the raw XML message behind a SOAP interaction.
   *
   * @param context the context of the SOAP message passing through this handler
   */
  private void captureSoapXml(SOAPMessageContext context) {
    SOAPMessage message = context.getMessage();
    String soapXml = "";
    try {
      OutputStream outputStream = new ByteArrayOutputStream();
      message.writeTo(outputStream);
      soapXml = outputStream.toString();
      SOAPHeader soapHeader = message.getSOAPHeader();
      if ((!(Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY))
          && soapHeader != null
          && !requestIdXPathComponents.isEmpty()) {
        Node requestIdNode = nodeExtractor.extractNode(soapHeader, requestIdXPathComponents);
        if (requestIdNode != null) {
          lastRequestId = requestIdNode.getFirstChild().getNodeValue();
        }
      }
    } catch (IOException e) {
      soapXml = "Exception logging SOAP message: " + e;
    } catch (SOAPException e) {
      soapXml = "Exception logging SOAP message: " + e;
    }

    if ((Boolean) context.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {
      lastSoapRequest = soapXml;
    } else {
      lastSoapResponse = soapXml;
    }
  }

  /**
   * Returns the last SOAP request XML message handled by this object.
   */
  public String getLastRequestXml() {
    return lastSoapRequest;
  }

  /**
   * Returns the last SOAP response XML message handled by this object.
   */
  public String getLastResponseXml() {
    return lastSoapResponse;
  }
  
  /**
   * Returns the request ID from the last SOAP response XML message handled by this object.
   */
  public String getLastRequestId() {
    return lastRequestId;
  }

  /**
   * Adds a header to the list of SOAP request headers.
   *
   * @param namespace the namespace the header belongs to
   * @param headerName the name of the header element
   * @param headerValue the value of the header element
   */
  public void addHeader(String namespace, String headerName, SOAPElement headerValue) {
    this.soapHeaders.add(headerValue);
  }

  /**
   * Clears all the headers set in this handler.
   */
  public void clearHeaders() {
    this.soapHeaders.clear();
  }

  /**
   * Returns the set of SOAP headers added to this handler.
   */
  public Set getAddedHeaders() {
    return soapHeaders;
  }

  /**
   * @see SOAPHandler#getHeaders()
   */
  @Override
  public Set getHeaders() {
    return null;
  }

  /**
   * @see SOAPHandler#close(MessageContext)
   */
  @Override
  public void close(MessageContext messageContext) {}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy