Package com.subgraph.vega.internal.http.proxy

Source Code of com.subgraph.vega.internal.http.proxy.HttpProxyService

/*******************************************************************************
* Copyright (c) 2011 Subgraph.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Subgraph - initial API and implementation
******************************************************************************/
package com.subgraph.vega.internal.http.proxy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.http.client.CookieStore;
import org.apache.http.impl.client.BasicCookieStore;

import com.subgraph.vega.api.analysis.IContentAnalyzer;
import com.subgraph.vega.api.analysis.IContentAnalyzerFactory;
import com.subgraph.vega.api.http.proxy.IHttpInterceptProxyEventHandler;
import com.subgraph.vega.api.http.proxy.IHttpInterceptor;
import com.subgraph.vega.api.http.proxy.IHttpProxyListener;
import com.subgraph.vega.api.http.proxy.IHttpProxyListenerConfig;
import com.subgraph.vega.api.http.proxy.IHttpProxyService;
import com.subgraph.vega.api.http.proxy.IHttpProxyServiceEventHandler;
import com.subgraph.vega.api.http.proxy.IHttpProxyTransactionManipulator;
import com.subgraph.vega.api.http.proxy.IProxyTransaction;
import com.subgraph.vega.api.http.requests.IHttpRequestEngine;
import com.subgraph.vega.api.http.requests.IHttpRequestEngineConfig;
import com.subgraph.vega.api.http.requests.IHttpRequestEngineFactory;
import com.subgraph.vega.api.model.IModel;
import com.subgraph.vega.api.model.IWorkspace;
import com.subgraph.vega.api.model.requests.IRequestOriginProxy;
import com.subgraph.vega.api.paths.IPathFinder;
import com.subgraph.vega.api.scanner.IScanner;
import com.subgraph.vega.api.scanner.IScannerConfig;
import com.subgraph.vega.api.scanner.modules.IBasicModuleScript;
import com.subgraph.vega.api.scanner.modules.IResponseProcessingModule;
import com.subgraph.vega.api.scanner.modules.IScannerModuleRegistry;
import com.subgraph.vega.internal.http.proxy.ssl.ProxySSLInitializationException;
import com.subgraph.vega.internal.http.proxy.ssl.SSLContextRepository;

public class HttpProxyService implements IHttpProxyService {
  private final Logger logger = Logger.getLogger(HttpProxyService.class.getName());
  private final List<IHttpProxyServiceEventHandler> eventHandlers;
  private boolean isRunning = false;
  private boolean isPassthrough = false;
  private IModel model;
  private IHttpRequestEngineFactory requestEngineFactory;
  private IHttpRequestEngineConfig requestEngineConfig;
  private IContentAnalyzerFactory contentAnalyzerFactory;
  private IScannerModuleRegistry moduleRepository;
  private IScanner scanner;
  private CookieStore cookieStore;
  private IPathFinder pathFinder;
  private IContentAnalyzer contentAnalyzer;
  private List<IResponseProcessingModule> responseProcessingModules;
  private IWorkspace currentWorkspace;
  private Map<String, IHttpProxyListenerConfig> listenerConfigMap = new HashMap<String, IHttpProxyListenerConfig>();
  private Map<String, HttpProxyListener> listenerMap = new ConcurrentHashMap<String, HttpProxyListener>();
  private final IHttpInterceptProxyEventHandler listenerEventHandler;
  private final ProxyTransactionManipulator transactionManipulator;
  private ProxyScanner proxyScanner;
  private HttpInterceptor interceptor;
  private SSLContextRepository sslContextRepository;
 
  public HttpProxyService() {
    eventHandlers = new ArrayList<IHttpProxyServiceEventHandler>();
    listenerEventHandler = new IHttpInterceptProxyEventHandler() {
      @Override
      public void handleRequest(IProxyTransaction transaction) {
        processTransaction(transaction);
      }
    };
    transactionManipulator = new ProxyTransactionManipulator();
  }

  public void activate() {
    interceptor = new HttpInterceptor(model);
    cookieStore = new BasicCookieStore();
    proxyScanner = new ProxyScanner(scanner, cookieStore, model);

    try {
      sslContextRepository = SSLContextRepository.createInstance(pathFinder.getVegaDirectory());
    } catch (ProxySSLInitializationException e) {
      sslContextRepository = null;
      logger.warning("Failed to initialize SSL support in proxy.  SSL interception will be disabled. ("+ e.getMessage() + ")");
    }
  }

  @Override
  public void registerEventHandler(IHttpProxyServiceEventHandler handler) {
    eventHandlers.add(handler);
  }

  @Override
  public void unregisterEventHandler(IHttpProxyServiceEventHandler handler) {
    eventHandlers.remove(handler);
  }

  @Override
  public boolean isRunning() {
    return isRunning;
  }

  @Override
  public boolean isPassthrough() {
    synchronized(this) {
      return isPassthrough;
    }
  }

  @Override
  public IHttpProxyListenerConfig createListenerConfig() {
    return new HttpProxyListenerConfig();
  }

  @Override
  public void setListenerConfigs(IHttpProxyListenerConfig[] listenerConfigs) {
    // remove existing listeners that are not in the list
    for (Iterator<Map.Entry<String, IHttpProxyListenerConfig>> iter = listenerConfigMap.entrySet().iterator(); iter.hasNext();) {
      final Map.Entry<String, IHttpProxyListenerConfig> entry = iter.next();
      final String k = entry.getKey();
      int idx;
      for (idx = 0; idx < listenerConfigs.length; idx++) {
        if (k.compareTo(((IHttpProxyListenerConfig)listenerConfigs[idx]).toString()) == 0) {
          break;
        }
      }
      if (idx == listenerConfigs.length) {
        if (isRunning != false) {
          HttpProxyListener listener = listenerMap.remove(k);
          stopListener(listener);
        }
        iter.remove();
      }
    }

    // create listeners for any new addresses
    for (int idx = 0; idx < listenerConfigs.length; idx++) {
      final IHttpProxyListenerConfig config = listenerConfigs[idx];
      final String key = config.toString();
      if (listenerConfigMap.get(key) == null) {
        listenerConfigMap.put(key, config);
        if (isRunning != false) {
          startListener(config);
        }
      }
    }

    // notify event handlers
    for (IHttpProxyServiceEventHandler handler: eventHandlers) {
      handler.notifyConfigChange(listenerMap.size());
    }
  }

  @Override
  public IHttpProxyListenerConfig[] getListenerConfigs() {
    return listenerMap.keySet().toArray(new IHttpProxyListenerConfig[0]);
  }

  @Override
  public IHttpProxyListener[] getListeners() {
    return listenerMap.values().toArray(new IHttpProxyListener[0]);
  }

  @Override
  public int getListenerConfigsCount() {
    return listenerMap.size();
  }

  @Override
  public void setPassthrough(boolean enabled) {
    synchronized(this) {
      isPassthrough = enabled;
      interceptor.setEnabled(!enabled);
    }
  }

  @Override
  public void start() {
    currentWorkspace = model.getCurrentWorkspace();
    if(currentWorkspace == null)
      throw new IllegalStateException("Cannot start proxy because no workspace is currently open");
    currentWorkspace.lock();
    isRunning = true;

    responseProcessingModules = loadModules();
    contentAnalyzer = contentAnalyzerFactory.createContentAnalyzer(currentWorkspace.getScanAlertRepository().getProxyScanInstance());
    contentAnalyzer.setResponseProcessingModules(responseProcessingModules);
    contentAnalyzer.setDefaultAddToRequestLog(true);
    contentAnalyzer.setAddLinksToModel(true);

    proxyScanner.reloadModules();
   
    for (IHttpProxyListenerConfig config: listenerConfigMap.values()) {
      startListener(config);
    }

    for (IHttpProxyServiceEventHandler handler: eventHandlers) {
      handler.notifyStart(listenerMap.size());
    }
  }

  private void startListener(IHttpProxyListenerConfig config) {
    IRequestOriginProxy requestOrigin = currentWorkspace.getRequestLog().getRequestOriginProxy(config.getInetAddress(), config.getPort());
    IHttpRequestEngine requestEngine = requestEngineFactory.createRequestEngine(IHttpRequestEngine.EngineConfigType.CONFIG_PROXY, requestEngineConfig, requestOrigin);
    requestEngine.setCookieStore(cookieStore);
    HttpProxyListener listener = new HttpProxyListener(config, transactionManipulator, interceptor, requestEngine, sslContextRepository);
    listener.registerEventHandler(listenerEventHandler);
    listenerMap.put(config.toString(), listener);
    listener.start();
    for (IHttpProxyServiceEventHandler handler: eventHandlers) {
      handler.notifyStartListener(listener);
    }
  }
 
  private void stopListener(IHttpProxyListener listener) {
    listener.unregisterEventHandler(listenerEventHandler);
    listener.stop();
    for (IHttpProxyServiceEventHandler handler: eventHandlers) {
      handler.notifyStopListener(listener);
    }
  }
 
  private List<IResponseProcessingModule> loadModules() {
    if(responseProcessingModules == null) {
      return moduleRepository.getResponseProcessingModules();
    } else {
      return moduleRepository.updateResponseProcessingModules(responseProcessingModules);
    }
  }

  private void processTransaction(IProxyTransaction transaction) {
    synchronized(this) {
      if(transaction.getResponse() == null || contentAnalyzer == null || isPassthrough) {
        return;
      }
    }
    try {
      if(proxyScanner.isEnabled()) {
        proxyScanner.processRequest(transaction.getRequest());
      }
      contentAnalyzer.processResponse(transaction.getResponse());
    } catch (RuntimeException e) {
      logger.log(Level.WARNING, "Exception processing transaction response: "+ e.getMessage(), e);
    }
  }
  @Override
  public void stop() {
    if(currentWorkspace == null)
      throw new IllegalStateException("No workspace is open");
    isRunning = false;
    proxyScanner.setEnabled(false);

    for (Iterator<Map.Entry<String, HttpProxyListener>> iter = listenerMap.entrySet().iterator(); iter.hasNext();) {
      final Map.Entry<String, HttpProxyListener> entry = iter.next();
      stopListener(entry.getValue());
      iter.remove();
    }
    listenerMap.clear();

    contentAnalyzer = null;
    currentWorkspace.unlock();

    for (IHttpProxyServiceEventHandler handler: eventHandlers) {
      handler.notifyStop();
    }
  }

  @Override
  public IHttpProxyTransactionManipulator getTransactionManipulator() {
    return transactionManipulator;
  }

  @Override
  public IHttpInterceptor getInterceptor() {
    return interceptor;
  }

  protected void setModel(IModel model) {
    this.model = model;
  }

  protected void unsetModel(IModel model) {
    this.model = null;
  }

  protected void setContentAnalyzerFactory(IContentAnalyzerFactory factory) {
    this.contentAnalyzerFactory = factory;
  }
 
  protected void unsetContentAnalyzerFactory(IContentAnalyzerFactory factory) {
    this.contentAnalyzerFactory = null;
  }

  protected void setRequestEngineFactory(IHttpRequestEngineFactory factory) {
    this.requestEngineFactory = factory;
    requestEngineConfig = requestEngineFactory.createConfig();
  }

  protected void unsetRequestEngineFactory(IHttpRequestEngineFactory factory) {
    this.requestEngineFactory = null;
    requestEngineConfig = null;
  }
 
  protected void setModuleRepository(IScannerModuleRegistry moduleRepository) {
    this.moduleRepository = moduleRepository;
  }
 
  protected void unsetModuleRepository(IScannerModuleRegistry moduleRepository) {
    this.moduleRepository = null;
  }

  protected void setPathFinder(IPathFinder pathFinder) {
    this.pathFinder = pathFinder;
  }

  protected void unsetPathFinder(IPathFinder pathFinder) {
    this.pathFinder = null;
  }
 
  protected void setScanner(IScanner scanner) {
    this.scanner = scanner;
  }
 
  protected void unsetScanner(IScanner scanner) {
    this.scanner = null;
  }

  @Override
  public List<IResponseProcessingModule> getResponseProcessingModules() {
    responseProcessingModules = loadModules();
    if(responseProcessingModules == null) {
      return Collections.emptyList();
    } else {
      return responseProcessingModules;
    }
  }

  @Override
  public boolean isProxyScanEnabled() {
    return proxyScanner.isEnabled();
  }

  @Override
  public void setProxyScanEnabled(boolean enabled) {
    proxyScanner.setEnabled(enabled);
  }

  @Override
  public IScannerConfig getProxyScanConfig() {
    return proxyScanner.getConfig();
  }

  @Override
  public List<IBasicModuleScript> getProxyScanModules() {
    return proxyScanner.getInjectionModules();
  }
}
TOP

Related Classes of com.subgraph.vega.internal.http.proxy.HttpProxyService

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.