Package com.ibm.sbt.service.basic

Source Code of com.ibm.sbt.service.basic.ProxyService

/*
* © Copyright IBM Corp. 2012
*
* 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.ibm.sbt.service.basic;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;

import com.ibm.commons.util.StringUtil;
import com.ibm.commons.util.io.ByteStreamCache;
import com.ibm.commons.util.io.ReaderInputStream;
import com.ibm.commons.util.io.StreamUtil;
import com.ibm.commons.util.io.TraceOutputStream;
import com.ibm.commons.util.io.WriterOutputStream;
import com.ibm.commons.util.io.base64.Base64;
import com.ibm.commons.util.io.json.JsonGenerator;
import com.ibm.commons.util.io.json.JsonJavaFactory;
import com.ibm.commons.util.io.json.JsonJavaObject;
import com.ibm.commons.util.profiler.Profiler;
import com.ibm.commons.util.profiler.ProfilerAggregator;
import com.ibm.commons.util.profiler.ProfilerType;
import com.ibm.sbt.service.debug.DebugProxyHook;
import com.ibm.sbt.service.debug.DebugServiceHookFactory;
import com.ibm.sbt.service.debug.DebugServiceHookFactory.Type;

/**
* Basic proxy.
* <p>
* This is the base class handling proxy requests. It has to be instanciated and called
* from a servlet, or from a proxy handler from the library.
* </p>
* @author Dan Dumont
* @author Philippe Riand
*/
public class ProxyService {

  /// TODO: use a group here...
  private static boolean TRACE = false;

  private static final ProfilerType profilerRequest           = new ProfilerType("Proxy request, "); //$NON-NLS-1$
 
 
  /**
   * The wrapper for cookie domain and path.  These are stored in the cookie value
   * when the cookie is passed to the browser.  So that the proxy domain and path
   * can be used when the cookie is passed back to the browser.
   */
  private static final String PASSTHRUID               = "sbtsdkck";

  private DebugProxyHook debugHook;
 
  public ProxyService() {
  }

  public DebugProxyHook getDebugHook() {
    return debugHook;
  }
 
  public int getSocketReadTimeout() {
    return 120; // default, in seconds
  }

  protected DefaultHttpClient getClient(HttpServletRequest request, int timeout) {
    // Should we manage a connection pool here?
    //BasicHttpParams params = new BasicHttpParams();
    //params.setRedirecting(params, false);
    //DefaultHttpClient httpClient = new DefaultHttpClient(params);
    Object timedObject = ProxyProfiler.getTimedObject();
    DefaultHttpClient httpClient = new DefaultHttpClient();
    ProxyProfiler.profileTimedRequest(timedObject, "httpclient creation");
    return httpClient;
   
  }

  //
  // Security options - defensive mode by default
  //
  protected void checkRequestAllowed(HttpServletRequest request) throws ServletException {
    Object timedObject = ProxyProfiler.getTimedObject();
    String method = request.getMethod();
    if(!isMethodAllowed(method)) {
      throw new ServletException(StringUtil.format("Invalid request method {0}",method));
    }
    ProxyProfiler.profileTimedRequest(timedObject, "checkRequestAllowed");
  }

  protected boolean isMethodAllowed(String method) throws ServletException {
    return false;
  }
  protected boolean forwardHeaders(HttpRequestBase method, HttpServletRequest request) {
    return true;
  }
  protected boolean isHeaderAllowed(String headerName) throws ServletException {
    // content-length header will be automatically added by the HTTP client
    // host header causes request failures when it does not match the proxy host see x-forwaded-for comment above
      // Origin is added by chrome / safari in post/put/delete same-origin requests.
    if(StringUtil.equalsIgnoreCase(headerName, "content-length")
        || StringUtil.equalsIgnoreCase(headerName, "host") || StringUtil.equalsIgnoreCase(headerName, "origin")) {
      return false;
    }
    return true;
  }
  protected boolean forwardCookies(HttpRequestBase method, HttpServletRequest request) {
    return true;
  }
  protected boolean isCookieAllowed(String cookieName) throws ServletException {
    //if(cookieName.equalsIgnoreCase("JSESSIONID")) {
    //    return false;
    //}
    return true;
  }
  protected boolean isMimeTypeAllowed(String cookieName) throws ServletException {
    return true;
  }

  public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Object timedObject = ProxyProfiler.getTimedObject();
    if (Profiler.isEnabled()) {
      StringBuffer b = request.getRequestURL();
      String url = b.toString();
      ProfilerAggregator agg = Profiler.startProfileBlock(profilerRequest, request.getMethod().toUpperCase() + " " + url);
      long ts = Profiler.getCurrentTime();
      try {
        serviceProxy(request, response);
      } finally {
        Profiler.endProfileBlock(agg, ts);
      }
    }
    else {
      serviceProxy(request, response);
    }
    ProxyProfiler.profileTimedRequest(timedObject, "service request");
  }
  protected void serviceProxy(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.debugHook = (DebugProxyHook)DebugServiceHookFactory.get().get(Type.PROXY,request,response);
    if(debugHook!=null) {
      request = debugHook.getRequestWrapper();
      response = debugHook.getResponseWrapper();
    }
    try {
      try {
        initProxy(request, response);
        try {
          checkRequestAllowed(request);
          String smethod = request.getMethod();
          DefaultHttpClient client = getClient(request, getSocketReadTimeout());
          URI url = getRequestURI(request);
          HttpRequestBase method = createMethod(smethod, url, request);
          if (prepareForwardingMethod(method, request, client)) {
            HttpResponse clientResponse = executeMethod(client, method);
            prepareResponse(method, request, response, clientResponse, true);
          }
          response.flushBuffer();
        } catch (Exception e) {
          writeErrorResponse("Unexpected Exception", new String[] {"exception"},new String[] {e.toString()}, response, request);
        }finally {
          termProxy(request, response);
        }
      } catch (Exception e) {
        writeErrorResponse("Unexpected Exception", new String[] {"exception"},new String[] {e.toString()}, response, request);
      }
    } finally {
      if(debugHook!=null) {
        debugHook.terminate();
        debugHook = null;
      }
    }
  }

  private HttpRequestBase prepareMethodWithUpdatedContent(
      HttpRequestBase method, HttpServletRequest request) throws ServletException {
    // PHIL, 2/28/2013
    // We should use the length when available, for HTTP 1.1
    // -> it optimizes with HTTP 1.1
    // -> it prevents the HTTP client to use Transfert-Encoding: chunked, which doesn't
    //    seem to work will all HTTP servers (ex: Domino)
    // A browser should anyway provide the length.
    long length = -1;
    String slength = request.getHeader("Content-Length");
    if(StringUtil.isNotEmpty(slength)) {
      length = Long.parseLong(slength);
    }
    try {
      // When no length is specified, the HTTP client core forces Transfert-Encoding: chunked
      // The code bellow shows a workaround, although we should avoid that
      if(false) {
        if(length<0) {
          ByteStreamCache bs = new ByteStreamCache();
          bs.copyFrom(request.getInputStream());
          HttpEntity payloadEntity = new InputStreamEntity(bs.getInputStream(), bs.getLength());
          ((HttpEntityEnclosingRequest) method).setEntity(payloadEntity);
          return method;
        }
      }
      // Regular code
      HttpEntity payloadEntity = new InputStreamEntity(request.getInputStream(), length);
      ((HttpEntityEnclosingRequest) method).setEntity(payloadEntity);
    }catch(Exception e){
      throw new ServletException("Error while parsing the payload");
    }
    return method;
  }

  protected void initProxy(HttpServletRequest request, HttpServletResponse response) throws ServletException {
  }

  protected void termProxy(HttpServletRequest request, HttpServletResponse response) throws ServletException {
  }

  protected HttpRequestBase createMethod(String smethod, URI uri,HttpServletRequest request) throws ServletException {
    Object timedObject = ProxyProfiler.getTimedObject();
    if(getDebugHook()!=null) {
      getDebugHook().getDumpRequest().setMethod(smethod);
      getDebugHook().getDumpRequest().setUrl(uri.toString());
    }
    if (smethod.equalsIgnoreCase("get")) {
      HttpGet method = new HttpGet(uri);
      ProxyProfiler.profileTimedRequest(timedObject, "create HttpGet");
      return method;
    } else if (smethod.equalsIgnoreCase("put")) {
      HttpPut method = new HttpPut(uri);
      method = (HttpPut) prepareMethodWithUpdatedContent(method, request);
      ProxyProfiler.profileTimedRequest(timedObject, "create HttpPut");
      return method;
    } else if (smethod.equalsIgnoreCase("post")) {
      HttpPost method = new HttpPost(uri);
      method = (HttpPost) prepareMethodWithUpdatedContent(method, request);
      ProxyProfiler.profileTimedRequest(timedObject, "create HttpPost");
      return method;
    } else if (smethod.equalsIgnoreCase("delete")) {
      HttpDelete method = new HttpDelete(uri);
      ProxyProfiler.profileTimedRequest(timedObject, "create HttpDelete");
      return method;
    } else if (smethod.equalsIgnoreCase("head")) {
      HttpHead method = new HttpHead(uri);
      ProxyProfiler.profileTimedRequest(timedObject, "create HttpHead");
      return method;
    } else if (smethod.equalsIgnoreCase("options")) {
      HttpOptions method = new HttpOptions(uri);
      ProxyProfiler.profileTimedRequest(timedObject, "create HttpOptions");
      return method;
    } else {
      ProxyProfiler.profileTimedRequest(timedObject, "failed creating method");
      throw new ServletException("Illegal method, should be GET, PUT, POST, DELETE or HEAD");
    }
  }

  protected boolean prepareForwardingMethod(HttpRequestBase method, HttpServletRequest request, DefaultHttpClient client) throws ServletException {
    boolean retval =   (!forwardCookies(method, request) || prepareForwardingCookies(method, request, client))
    && (!forwardHeaders(method, request) || prepareForwardingHeaders(method, request));
    return retval;
  }

  protected boolean prepareForwardingCookies(HttpRequestBase method, HttpServletRequest request, DefaultHttpClient httpClient) throws ServletException {
    Object timedObject = ProxyProfiler.getTimedObject();
    Cookie[] cookies = request.getCookies();
    BasicCookieStore cs = new BasicCookieStore();
    httpClient.setCookieStore(cs);
    if (cookies != null) {
      for (Cookie cookie : cookies) {
        if (cookie != null) {
          String cookiename = cookie.getName();
          if(StringUtil.isNotEmpty(cookiename)) {
            String cookieval = cookie.getValue();
            if (cookiename.startsWith(PASSTHRUID)) {
              cookiename = cookiename.substring(PASSTHRUID.length());
              if(isCookieAllowed(cookiename)) {
                String[] parts = decodeCookieNameAndPath(cookiename);
                if (parts!=null && parts.length==3) {
                  cookiename = parts[0];
                  String path = parts[1];
                  String domain = parts[2];

                  // Got stored domain now see if it matches destination
                  BasicClientCookie methodcookie = new BasicClientCookie(cookiename,cookieval);
                  methodcookie.setDomain(domain);
                  methodcookie.setPath(path);
                  cs.addCookie(methodcookie);
                  if(getDebugHook()!=null) {
                    getDebugHook().getDumpRequest().addCookie(methodcookie.getName(), methodcookie.toString());
                  }
                }
              }
            } else if(isCookieAllowed(cookiename)) {
              BasicClientCookie methodcookie = new BasicClientCookie(cookiename,cookieval);
              String domain = cookie.getDomain();
              if (domain == null) {
                try {
                  domain = method.getURI().getHost();
                  domain = domain.substring(domain.indexOf('.'));
                } catch (Exception e) {
                  domain = "";
                }
              }
              methodcookie.setDomain(domain);
              String path = cookie.getPath();
              if (path == null) {
                path = "/";
              }
              methodcookie.setPath(path);
              cs.addCookie(methodcookie);
              if(getDebugHook()!=null) {
                getDebugHook().getDumpRequest().addCookie(methodcookie.getName(), methodcookie.toString());
              }
            }
          }
        }
      }
    }
    ProxyProfiler.profileTimedRequest(timedObject, "perpareForwardingCookie");
    return true;
  }

  @SuppressWarnings("unchecked")
  protected boolean prepareForwardingHeaders(HttpRequestBase method, HttpServletRequest request) throws ServletException {
    Object timedObject = ProxyProfiler.getTimedObject();
    // Forward any headers that should be forwarded. Except cookies.
    StringBuffer xForwardedForHeader = new StringBuffer();
    for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements();) {
      String headerName = e.nextElement();
      // Ignore cookie - treat them separately
      if (headerName.equalsIgnoreCase("cookie")) { // $NON-NLS-1$
        continue;
      }
      String headerValue = request.getHeader(headerName);
      // This is to be investigated - Should the X-Forwarded-For being passed? Ryan.
      //            if(headerName.equalsIgnoreCase("X-Forwarded-For") || headerName.equalsIgnoreCase("host")) {
      //                addXForwardedForHeader(method, headerValue, xForwardedForHeader);
      //                continue;
      //            }
      // Ensure that the header is allowed
      if(isHeaderAllowed(headerName)) {
        method.addHeader(headerName, headerValue);
        if(getDebugHook()!=null) {
          getDebugHook().getDumpRequest().addHeader(headerName, headerValue);
        }
      }
    }
    String xForward = xForwardedForHeader.toString();
    if(StringUtil.isNotEmpty(xForward)) {
      method.addHeader("X-Forwarded-For", xForward);
      if(getDebugHook()!=null) {
        getDebugHook().getDumpRequest().addHeader("X-Forwarded-For", xForward);
      }
    }
    ProxyProfiler.profileTimedRequest(timedObject, "prepareForwardingHeaders");
    return true;
  }

  /**
   * Adds a host to the x-Forwarded-For header.  This method is called a host or
   * x-Forwarded-For header is encountered on the proxied request.
   * @param method The request being made by the proxy.
   * @param headerValue The header value from the proxied request.
   * @param xForwardedForHeader The current valye of the x-Forward-For header that will be
   * added to the request made by the proxy.
   */
  protected void addXForwardedForHeader(HttpRequestBase method, String headerValue,
      StringBuffer xForwardedForHeader) {
    String[] forwards = headerValue.trim().split(",");
    for (String forward : forwards) {
      String host = forward.trim();
      if(!host.equals("")) {
        if(xForwardedForHeader.length() == 0) {
          xForwardedForHeader.append(host);
        } else {
          xForwardedForHeader.append("," + host);
        }
      }
    }
  }

  public HttpResponse executeMethod(HttpClient client, HttpRequestBase method) throws ServletException {
    try {
      Object timedObject = ProxyProfiler.getTimedObject();
      HttpResponse response = client.execute(method);
      ProxyProfiler.profileTimedRequest(timedObject, "remote call");
      return response;
    } catch(IOException ex) {
      throw new ServletException(ex);
    }
  }

  public void prepareResponse(HttpRequestBase method, HttpServletRequest request, HttpServletResponse response, HttpResponse clientResponse, boolean isCopy) throws ServletException {
    Object timedObject = ProxyProfiler.getTimedObject();
    try {
      int statusCode = clientResponse.getStatusLine().getStatusCode();
      if(statusCode == 401 || statusCode == 403){
        clientResponse.setHeader("WWW-Authenticate", "");
      }
      response.setStatus(statusCode);
      if(getDebugHook()!=null) {
        getDebugHook().getDumpResponse().setStatus(statusCode);
      }

      // Passed back all heads, but process cookies differently.
      Header[] headers = clientResponse.getAllHeaders();
      for (Header header : headers) {
        String headername = header.getName();

        if (headername.equalsIgnoreCase("Set-Cookie") ) { // $NON-NLS-1$
          if(forwardCookies(method, request)) {
            // If cookie, have to rewrite domain/path for browser.
            String setcookieval = header.getValue();
 
            if (setcookieval != null) {
              String thisserver = request.getServerName();
 
              String thisdomain;
              if (thisserver.indexOf('.') == -1) {
                thisdomain = "";
              }
              else {
                thisdomain = thisserver.substring(thisserver.indexOf('.'));
              }
              String domain = null;
 
              // path info = /protocol/server/path-on-server
              //Matcher m = cookiePathPattern.matcher(request.getPathInfo());
              String thispath = request.getContextPath() + request.getServletPath();
              String path = null;
 
              String[][] cookparams = getCookieStrings(setcookieval);
 
              for (int j = 1; j < cookparams.length; j++) {
                if ("domain".equalsIgnoreCase(cookparams[j][0])) { // $NON-NLS-1$
                  domain = cookparams[j][1];
                  cookparams[j][1] = null;
                } else if ("path".equalsIgnoreCase(cookparams[j][0])) { // $NON-NLS-1$
                  path = cookparams[j][1];
                  cookparams[j][1] = null;
                }
              }
 
              if (domain == null) {
                domain = method.getURI().getHost();
              }
 
              // Set cookie name
              String encoded = encodeCookieNameAndPath(cookparams[0][0], path, domain);
              if(encoded!=null) {
                String newcookiename = PASSTHRUID + encoded;
 
                StringBuilder newset = new StringBuilder(newcookiename);
                newset.append('=');
                newset.append(cookparams[0][1]);
 
                for (int j = 1; j < cookparams.length; j++) {
                  String settingname = cookparams[j][0];
                  String settingvalue = cookparams[j][1];
                  if (settingvalue != null) {
                    newset.append("; ").append(settingname); // $NON-NLS-1$
                    newset.append('=').append(settingvalue); // $NON-NLS-1$
                  }
                }
 
                newset.append("; domain=").append(thisdomain); // $NON-NLS-1$
                newset.append("; path=").append(thispath); // $NON-NLS-1$
 
                String newsetcookieval = newset.toString();
                // this implementation of HttpServletRequest seems to have issues... setHeader works as I would
                // expect addHeader to.
                response.setHeader(headername, newsetcookieval);
                if(getDebugHook()!=null) {
                  getDebugHook().getDumpResponse().addCookie(headername, newsetcookieval);
                }
              }
            }
          }
        }
        else if (!headername.equalsIgnoreCase("Transfer-Encoding")) { // $NON-NLS-1$
          String headerval = header.getValue();

          if (headername.equalsIgnoreCase("content-type")) {
            int loc = headerval.indexOf(';');
            String type;
            if (loc > 0) {
              type = headerval.substring(0, loc).trim();
            } else {
              type = headerval;
            }
            if (!isMimeTypeAllowed(type)) {
              isCopy = false;
              break;
            } else {
              response.setHeader(headername, headerval);
              if(getDebugHook()!=null) {
                getDebugHook().getDumpResponse().addHeader(headername, headerval);
              }
            }
          } else if ( (statusCode == 401 || statusCode == 403&& headername.equalsIgnoreCase("WWW-Authenticate")) { // $NON-NLS-1$
            if (headerval.indexOf("Basic") != -1) { // $NON-NLS-1$
              String pathInfo = request.getPathInfo();
              String[] pathParts = (pathInfo.startsWith("/") ? pathInfo.substring(1) : pathInfo).split("/");
              if (pathParts.length > 1) {
                StringBuilder strb = new StringBuilder("Basic realm=\""); // $NON-NLS-1$
                strb.append(request.getContextPath());
                strb.append(request.getServletPath());
                strb.append('/');
                strb.append(pathParts[0]);
                strb.append('/');
                strb.append(pathParts[1]);
                strb.append('"');
                headerval = strb.toString();
                response.setHeader(headername, headerval);
                if(getDebugHook()!=null) {
                  getDebugHook().getDumpResponse().addHeader(headername, headerval);
                }
              }
            }
          } else {
            response.setHeader(headername, headerval);
            if(getDebugHook()!=null) {
              getDebugHook().getDumpResponse().addHeader(headername, headerval);
            }
          }
        }
      }

      // Need to move response body over too
      if(statusCode == HttpServletResponse.SC_NO_CONTENT || statusCode == HttpServletResponse.SC_NOT_MODIFIED) {
        response.setHeader("Content-Length", "0");
        if(getDebugHook()!=null) {
          getDebugHook().getDumpResponse().addHeader("Content-Length", "0");
        }
      } else if(isCopy) {
        HttpEntity entity = clientResponse.getEntity();
        InputStream inStream = entity.getContent();
        if (inStream != null) {
          OutputStream os = response.getOutputStream();
          if(TRACE) {
            OutputStream tos = new TraceOutputStream(os, System.out, false);
            os = tos;
          }
          StreamUtil.copyStream(inStream, os);
          os.flush();
        }
        else {
          response.setHeader("Content-Length", "0");
          if(getDebugHook()!=null) {
            getDebugHook().getDumpResponse().addHeader("Content-Length", "0");
          }
        }
      }
    } catch(IOException ex) {
      throw new ServletException(ex);
    }
    ProxyProfiler.profileTimedRequest(timedObject, "prepareResponse");
  }

  protected void writeErrorResponse(String errorMessage, String[] parameters, String[] values, HttpServletResponse response, HttpServletRequest request) throws ServletException {
    writeErrorResponse(404, errorMessage, parameters, values, response, request);
  }
  public static void writeErrorResponse(int httpstatus, String errorMessage, String[] parameters, String[]values,
      HttpServletResponse response, HttpServletRequest request) throws ServletException {
    JsonJavaObject o = new JsonJavaObject();
    o.putString("Message", errorMessage);
    List<JsonJavaObject> params = new ArrayList<JsonJavaObject>();
    if (parameters != null && parameters.length > 0) {
      for (int i = 0; i < parameters.length; i++) {
        JsonJavaObject e = new JsonJavaObject();
        e.putString(parameters[i],values[i]);
        params.add(e);
      }
    }
    o.putObject("Parameters", params);

    try {
      response.setStatus(httpstatus);
      //response.setStatus(HttpServletResponse.SC_FORBIDDEN);
      response.addHeader("content-type", "application/json"); // $NON-NLS-1$ $NON-NLS-2$
      response.addHeader("Server", "SBT"); // $NON-NLS-1$ $NON-NLS-2$
      response.addHeader("Connection", "close"); // $NON-NLS-1$ $NON-NLS-2$
      response.addDateHeader("Date", System.currentTimeMillis()); // $NON-NLS-1$
      response.getOutputStream().print(JsonGenerator.toJson(JsonJavaFactory.instanceEx, o));
    }catch (Exception e) {}
  }

  private String[][] getCookieStrings(String set_cookie) {
    String[] pairs = set_cookie.split(";");
    String[][] ret = new String[pairs.length][];

    for (int i = 0; i < pairs.length; i++) {
      String p = pairs[i];
      ret[i] = new String[2];

      int eqloc = p.indexOf('=');
      if (eqloc < 0) {
        ret[i][0] = p;
        ret[i][1] = null;
      }
      else {
        ret[i][0] = p.substring(0, eqloc).trim();
        ret[i][1] = p.substring(eqloc + 1).trim();
      }
    }

    return ret;
  }

  protected URI getRequestURI(HttpServletRequest request) throws ServletException {
    try {
      Object timedObject = ProxyProfiler.getTimedObject();
      String orgUrl = getRequestURIPath(request);
      String queryargs = getRequestURLQueryString(request);
      if(StringUtil.isNotEmpty(queryargs)) {
        orgUrl += '?' + queryargs;
      }
      URI url = new URI(orgUrl);
      ProxyProfiler.profileTimedRequest(timedObject, "get request uri");
      return url;
    } catch (URISyntaxException ex) {
      throw new ServletException(ex);
    }
  }
  protected String getRequestURIPath(HttpServletRequest request) throws ServletException {
    String pathinfo = request.getPathInfo();
    int pos = pathinfo.indexOf("/http/"); // $NON-NLS-1$
    if (pos == -1) {
      pos = pathinfo.indexOf("/https/"); // $NON-NLS-1$
    }
    if (pos > 0) {
      pathinfo = pathinfo.substring(pos);
    }
    String orgUrl = pathinfo.substring(1).replaceFirst("\\/", "://");
    return orgUrl;
  }

  protected String getRequestURLQueryString(HttpServletRequest request) throws ServletException {
    String queryargs = request.getQueryString();
    return queryargs;
  }


  private static String encodeBase64(byte[] b) {
    try {
      StringWriter sw = new StringWriter();
      Base64.OutputStream b64 = new Base64.OutputStream(new WriterOutputStream(sw));

      int len = b.length;
      for( int i=0; i<len; i++) {
        int c = b[i];
        b64.write(c);
      }
      b64.flushBuffer();

      return sw.toString();
    } catch(IOException ex) {
      ex.printStackTrace();
      return null;
    }
  }
  private static byte[] decodeBase64(String s) {
    try {
      Base64.InputStream b64 = new Base64.InputStream(new ReaderInputStream(new StringReader(s)));
      ByteBuffer bb = ByteBuffer.allocate(1024*4); // max cookie size
      int byt;
      while( (byt = b64.read()) >= 0)  {
        bb.put((byte) (byt&0xFF));
      }
      return bb.array();
    } catch(IOException ex) {
      ex.printStackTrace();
      return null;
    }
  }

  protected static String encodeCookieNameAndPath(String name, String path, String domain) throws ServletException {
    try {
      String s = new StringBuilder(name)
      .append(';')
      .append(path)
      .append(';')
      .append(domain)
      .toString();
      String encoded = URLEncoder.encode(s, "UTF-8");
      return encoded;
    } catch (UnsupportedEncodingException e) {
      return null;
    }
  }
  protected static String[] decodeCookieNameAndPath(String encoded) throws ServletException {
    try {
      String s = URLDecoder.decode(encoded, "UTF-8");
      return StringUtil.splitString(s, ';');
    } catch (UnsupportedEncodingException e) {
      return null;
    }
  }



  //    protected static String encodeCookieNameAndPath(String name, String path, String domain) throws ServletException {
  //        final ByteBuffer bb = ByteBuffer.allocate(1024*4); // max cookie size
  //        final byte[] buffer = new byte[512];
  //        final Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, true);
  //        String ret = null;
  //        try {
  //            // Join name and path strings with ';' and get the UTF-8 bytes.
  //            byte[] in = new StringBuilder(name)
  //                            .append(';')
  //                            .append(path)
  //                            .append(';')
  //                            .append(domain)
  //                            .toString().getBytes("UTF-8");
  //            deflater.setInput(in);
  //            deflater.finish();
  //            int written = 0;
  //
  //            // Deflate the byte array into out
  //            while ( (written = deflater.deflate(buffer)) == buffer.length ) {
  //                bb.put(buffer, bb.position(), written);
  //            }
  //            bb.put(buffer, bb.position(), written);
  //            byte[] out = new byte[bb.position()];
  //            System.arraycopy(bb.array(), 0, out, 0, out.length);
  //
  //            // Base64Encode the out byte array and replace unsafe characters.
  //            // Replace padding '=' with a single number of how many padding chars there were.
  //            ret = encodeBase64(out).replaceAll("\\s", "").replaceAll("[/]", "_").replaceAll("[+]", "-"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
  //            int i = ret.indexOf('=');
  //            if (i < 0)
  //                i = ret.length();
  //            int len = ret.length() - i;
  //            ret = ret.substring(0, i);
  //            ret = ret + len;
  //        } catch (Throwable t) {}
  //        return ret;
  //    }
  //    protected static String[] decodeCookieNameAndPath(String encoded) throws ServletException {
  //        final Inflater inflater = new Inflater(true);
  //        final ByteBuffer bb = ByteBuffer.allocate(1024*4); // max cookie size
  //        final byte[] buffer = new byte[512];
  //
  //        String[] ret = null;
  //        try {
  //            // Replace the safe characters with the proper Base64 alphabet characters.
  //            encoded = encoded.replaceAll("[_]", "/").replaceAll("[-]", "_"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
  //
  //            // Replace the padding digit with the correct number of padding characters.
  //            int len = 0;
  //            try {
  //                len = Integer.parseInt(encoded.substring(encoded.length() - 1));
  //                encoded = encoded.substring(0, encoded.length() - 1);
  //            } catch (Exception e) {
  //            }
  //            final String padding = "==="; // $NON-NLS-1$
  //            encoded = encoded + padding.substring(0, len);
  //
  //            // Base64Decode the string into a byte array 'in'.
  //            byte[] in = decodeBase64(encoded);
  //            inflater.setInput(in);
  //
  //            // Inflate 'in' into the byte buffer.
  //            int written = 0;
  //            while ( (written = inflater.inflate(buffer)) == buffer.length ) {
  //                bb.put(buffer, bb.position(), written);
  //            }
  //            bb.put(buffer, bb.position(), written);
  //
  //            // Make a new string from the inflated bytebuffer, using UTF-8 charset
  //            String namepath = new String(bb.array(), 0, bb.position(), "UTF-8");
  //
  //            // split the name/path pair into the return array value.
  //            ret = namepath.split(";");
  //        } catch (Throwable t) {}
  //        return ret;
  //    }
}
TOP

Related Classes of com.ibm.sbt.service.basic.ProxyService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.