com.eviware.soapui.impl.wsdl.monitor.jettyproxy.TunnelServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.eviware.soapui.impl.wsdl.monitor.jettyproxy.TunnelServlet.java

Source

/*
 *  soapUI, copyright (C) 2004-2011 eviware.com 
 *
 *  soapUI is free software; you can redistribute it and/or modify it under the 
 *  terms of version 2.1 of the GNU Lesser General Public License as published by 
 *  the Free Software Foundation.
 *
 *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
 *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 *  See the GNU Lesser General Public License for more details at gnu.org.
 */

package com.eviware.soapui.impl.wsdl.monitor.jettyproxy;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Enumeration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.mortbay.util.IO;

import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.LaunchForm;
import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.SecurityTabForm;
import com.eviware.soapui.impl.wsdl.monitor.CaptureInputStream;
import com.eviware.soapui.impl.wsdl.monitor.JProxyServletWsdlMonitorMessageExchange;
import com.eviware.soapui.impl.wsdl.monitor.SoapMonitor;
import com.eviware.soapui.impl.wsdl.submit.transports.http.ExtendedHttpMethod;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedGetMethod;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPostMethod;
import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
import com.eviware.soapui.impl.wsdl.support.http.ProxyUtils;
import com.eviware.soapui.impl.wsdl.support.http.SoapUIHostConfiguration;
import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
import com.eviware.soapui.support.types.StringToStringsMap;
import com.eviware.soapui.support.xml.XmlUtils;

public class TunnelServlet extends ProxyServlet {
    private String sslEndPoint;
    private int sslPort = 443;
    private String prot = "https://";

    public TunnelServlet(SoapMonitor soapMonitor, String sslEndpoint) {
        super(soapMonitor);

        if (!sslEndpoint.startsWith("https")) {
            this.prot = "http://";
        }
        int prefix = sslEndpoint.indexOf("://");
        int c = sslEndpoint.indexOf(prefix, ':');
        if (c > 0) {
            this.sslPort = Integer.parseInt(sslEndpoint.substring(c + 1));
            this.sslEndPoint = sslEndpoint.substring(prefix, c);
        } else {
            if (prefix > 0)
                this.sslEndPoint = sslEndpoint.substring(prefix + 3);
        }
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.context = config.getServletContext();
    }

    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        monitor.fireOnRequest(request, response);
        if (response.isCommitted())
            return;

        ExtendedHttpMethod postMethod;

        // for this create ui server and port, properties.
        InetSocketAddress inetAddress = new InetSocketAddress(sslEndPoint, sslPort);
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        if (httpRequest.getMethod().equals("GET"))
            postMethod = new ExtendedGetMethod();
        else
            postMethod = new ExtendedPostMethod();

        JProxyServletWsdlMonitorMessageExchange capturedData = new JProxyServletWsdlMonitorMessageExchange(project);
        capturedData.setRequestHost(httpRequest.getRemoteHost());
        capturedData.setRequestHeader(httpRequest);
        capturedData.setTargetURL(this.prot + inetAddress.getHostName());

        CaptureInputStream capture = new CaptureInputStream(httpRequest.getInputStream());

        // copy headers
        Enumeration<?> headerNames = httpRequest.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String hdr = (String) headerNames.nextElement();
            String lhdr = hdr.toLowerCase();

            if ("host".equals(lhdr)) {
                Enumeration<?> vals = httpRequest.getHeaders(hdr);
                while (vals.hasMoreElements()) {
                    String val = (String) vals.nextElement();
                    if (val.startsWith("127.0.0.1")) {
                        postMethod.addRequestHeader(hdr, sslEndPoint);
                    }
                }
                continue;
            }

            Enumeration<?> vals = httpRequest.getHeaders(hdr);
            while (vals.hasMoreElements()) {
                String val = (String) vals.nextElement();
                if (val != null) {
                    postMethod.addRequestHeader(hdr, val);
                }
            }

        }

        if (postMethod instanceof ExtendedPostMethod)
            ((ExtendedPostMethod) postMethod)
                    .setRequestEntity(new InputStreamRequestEntity(capture, request.getContentType()));

        HostConfiguration hostConfiguration = new HostConfiguration();

        httpRequest.getProtocol();
        hostConfiguration.getParams().setParameter(SoapUIHostConfiguration.SOAPUI_SSL_CONFIG,
                settings.getString(SecurityTabForm.SSLTUNNEL_KEYSTOREPATH, "") + " "
                        + settings.getString(SecurityTabForm.SSLTUNNEL_KEYSTOREPASSWORD, ""));
        hostConfiguration.setHost(new URI(this.prot + sslEndPoint, true));

        hostConfiguration = ProxyUtils.initProxySettings(settings, httpState, hostConfiguration, prot + sslEndPoint,
                new DefaultPropertyExpansionContext(project));

        if (sslEndPoint.indexOf("/") < 0)
            postMethod.setPath("/");
        else
            postMethod.setPath(sslEndPoint.substring(sslEndPoint.indexOf("/"), sslEndPoint.length()));

        monitor.fireBeforeProxy(request, response, postMethod, hostConfiguration);

        if (settings.getBoolean(LaunchForm.SSLTUNNEL_REUSESTATE)) {
            if (httpState == null)
                httpState = new HttpState();
            HttpClientSupport.getHttpClient().executeMethod(hostConfiguration, postMethod, httpState);
        } else {
            HttpClientSupport.getHttpClient().executeMethod(hostConfiguration, postMethod);
        }
        capturedData.stopCapture();

        capturedData.setRequest(capture.getCapturedData());
        capturedData.setRawResponseBody(postMethod.getResponseBody());
        capturedData.setResponseHeader(postMethod);
        capturedData.setRawRequestData(getRequestToBytes(request.toString(), postMethod, capture));
        capturedData.setRawResponseData(
                getResponseToBytes(response.toString(), postMethod, capturedData.getRawResponseBody()));

        monitor.fireAfterProxy(request, response, postMethod, capturedData);

        StringToStringsMap responseHeaders = capturedData.getResponseHeaders();
        // copy headers to response
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        for (String name : responseHeaders.keySet()) {
            for (String header : responseHeaders.get(name))
                httpResponse.addHeader(name, header);

        }

        IO.copy(new ByteArrayInputStream(capturedData.getRawResponseBody()), httpResponse.getOutputStream());

        postMethod.releaseConnection();

        synchronized (this) {
            monitor.addMessageExchange(capturedData);
        }

        capturedData = null;
    }

    private byte[] getResponseToBytes(String footer, ExtendedHttpMethod postMethod, byte[] res) {
        String response = footer;

        Header[] headers = postMethod.getResponseHeaders();
        for (Header header : headers) {
            response += header.toString();
        }
        response += "\n";
        response += XmlUtils.prettyPrintXml(new String(res));

        return response.getBytes();
    }

    private byte[] getRequestToBytes(String footer, ExtendedHttpMethod postMethod, CaptureInputStream capture) {
        String request = footer;

        // Header[] headers = postMethod.getRequestHeaders();
        // for (Header header : headers)
        // {
        // request += header.toString();
        // }
        request += "\n";
        request += XmlUtils.prettyPrintXml(new String(capture.getCapturedData()));

        return request.getBytes();
    }

}