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

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

/*******************************************************************************
* 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.List;

import org.apache.http.HttpResponse;

import com.subgraph.vega.api.events.IEvent;
import com.subgraph.vega.api.events.IEventHandler;
import com.subgraph.vega.api.http.proxy.HttpInterceptorLevel;
import com.subgraph.vega.api.http.proxy.IHttpInterceptor;
import com.subgraph.vega.api.http.proxy.IHttpInterceptorEventHandler;
import com.subgraph.vega.api.http.proxy.IProxyTransaction;
import com.subgraph.vega.api.http.proxy.IProxyTransaction.TransactionDirection;
import com.subgraph.vega.api.model.IModel;
import com.subgraph.vega.api.model.IWorkspace;
import com.subgraph.vega.api.model.WorkspaceCloseEvent;
import com.subgraph.vega.api.model.WorkspaceOpenEvent;
import com.subgraph.vega.api.model.WorkspaceResetEvent;
import com.subgraph.vega.api.model.conditions.ConditionSetChanged;
import com.subgraph.vega.api.model.conditions.IHttpConditionManager;
import com.subgraph.vega.api.model.conditions.IHttpConditionSet;

import com.subgraph.vega.internal.http.proxy.ProxyTransaction;

public class HttpInterceptor implements IHttpInterceptor {
  private static final String propertyInterceptorLevelRequest = "vega.preferences.proxy.interceptor.level.request";
  private static final String propertyInterceptorLevelResponse = "vega.preferences.proxy.interceptor.level.response";
  private final Object interceptorLock = new Object(); /**< Lock for contents of object */
  private final List<IHttpInterceptorEventHandler> eventHandlerList;
  private HttpInterceptorLevel interceptorLevelRequest = HttpInterceptorLevel.DISABLED;
  private HttpInterceptorLevel interceptorLevelResponse = HttpInterceptorLevel.DISABLED;
  private IHttpConditionSet breakpointSetRequest;
  private IHttpConditionSet breakpointSetResponse;
  private final ArrayList<ProxyTransaction> transactionQueue = new ArrayList<ProxyTransaction>(); /**< Queue of intercepted transactions pending processing */
  private IWorkspace currentWorkspace;
  private boolean isEnabled = true;
 
  HttpInterceptor(IModel model) {
    eventHandlerList = new ArrayList<IHttpInterceptorEventHandler>();
    currentWorkspace = model.addWorkspaceListener(new IEventHandler() {
      @Override
      public void handleEvent(IEvent event) {
        if(event instanceof WorkspaceOpenEvent) {
          handleWorkspaceOpen((WorkspaceOpenEvent) event);
        } else if(event instanceof WorkspaceCloseEvent) {
          handleWorkspaceClose((WorkspaceCloseEvent) event);
        } else if (event instanceof WorkspaceResetEvent) {
          handleWorkspaceReset((WorkspaceResetEvent) event);
        }
      }
    });
    loadInterceptorLevelRequest();
    loadInterceptorLevelResponse();
    breakpointSetRequest = createConditionSet(model, true);
    breakpointSetResponse = createConditionSet(model, false);
  }

  private void handleWorkspaceOpen(WorkspaceOpenEvent event) {
    currentWorkspace = event.getWorkspace();
  }

  private void handleWorkspaceClose(WorkspaceCloseEvent event) {
    currentWorkspace = null;
  }

  private void handleWorkspaceReset(WorkspaceResetEvent event) {
    currentWorkspace = event.getWorkspace();
    loadInterceptorLevelRequest();   
    loadInterceptorLevelResponse();
  }

  private void loadInterceptorLevelRequest() {
    interceptorLevelRequest = HttpInterceptorLevel.fromValue(currentWorkspace.getIntegerProperty(propertyInterceptorLevelRequest));
    if (interceptorLevelRequest == null) {
      interceptorLevelRequest = HttpInterceptorLevel.DISABLED;
    }
  }

  private void loadInterceptorLevelResponse() {
    interceptorLevelResponse = HttpInterceptorLevel.fromValue(currentWorkspace.getIntegerProperty(propertyInterceptorLevelResponse));
    if (interceptorLevelResponse == null) {
      interceptorLevelResponse = HttpInterceptorLevel.DISABLED;
    }
  }
 
  private IHttpConditionSet createConditionSet(IModel model, boolean isRequestSet) {
    final String name = (isRequestSet) ? (IHttpConditionManager.CONDITION_SET_BREAKPOINTS_REQUEST) : (IHttpConditionManager.CONDITION_SET_BREAKPOINTS_RESPONSE);
    return model.addConditionSetTracker(name, createConditionSetChangedHandler(isRequestSet));
  }

  private IEventHandler createConditionSetChangedHandler(final boolean isRequestSet) {
    return new IEventHandler() {
      @Override
      public void handleEvent(IEvent event) {
        if(event instanceof ConditionSetChanged)
          onConditionSetChanged((ConditionSetChanged) event, isRequestSet);
      }
    };
  }

  private void onConditionSetChanged(ConditionSetChanged event, boolean isRequestSet) {
    synchronized(interceptorLock) {
      final TransactionDirection direction;
      if(isRequestSet) {
        breakpointSetRequest = event.getConditionSet();
        direction = TransactionDirection.DIRECTION_REQUEST;
      } else {
        breakpointSetResponse = event.getConditionSet();
        direction = TransactionDirection.DIRECTION_RESPONSE;
      }
      releaseOnChange(direction);
    }
  }

  private boolean intercept(ProxyTransaction transaction) {
    if (transaction.hasResponse() == false)
      return interceptByLevelAndBreakpointSet(transaction, interceptorLevelRequest, breakpointSetRequest);
    else
      return interceptByLevelAndBreakpointSet(transaction, interceptorLevelResponse, breakpointSetResponse);       
  }
 
  private boolean interceptByLevelAndBreakpointSet(ProxyTransaction transaction, HttpInterceptorLevel level, IHttpConditionSet breakpointSet) {
    switch(level) {
    case ENABLED_ALL:
      return true;
    case DISABLED:
      return false;
    case ENABLED_BREAKPOINTS:
      return interceptOnBreakpointSet(breakpointSet, transaction);
    }
    return false;
  }

  private boolean interceptOnBreakpointSet(IHttpConditionSet breakpointSet, ProxyTransaction transaction) {
    final HttpResponse response = (transaction.hasResponse()) ? (transaction.getResponse().getRawResponse()) : (null);
    synchronized(interceptorLock) {
      return (breakpointSet == null) ? (false) : (breakpointSet.matchesAny(transaction.getRequest(), response));
    }
  }

  /**
   * @return True if the transaction was intercepted and added to the queue for processing, false if it can immediately
   * be handled.
   */
  public boolean handleTransaction(ProxyTransaction transaction) {
    synchronized(interceptorLock) {
      if (isEnabled == true && eventHandlerList.size() != 0 && intercept(transaction) != false) {
        transaction.setPending(this);
        transactionQueue.add(transaction);
        int idx = transactionQueue.size() - 1;
        for (IHttpInterceptorEventHandler handler: eventHandlerList) {
          handler.notifyQueue(transaction, idx);
        }
        return true;
      }
      return false;
    }
  }

  @Override
  public void setEnabled(boolean enabled) {
    synchronized(interceptorLock) {
      if (isEnabled != enabled) {
        isEnabled = enabled;
        if (isEnabled == false) {
          forwardAll();
        }
      }
    }
  }

  @Override
  public boolean isEnabled() {
    synchronized(interceptorLock) {
      return isEnabled;
    }
  }

  @Override
  public void addEventHandler(IHttpInterceptorEventHandler eventHandler) {
    synchronized(interceptorLock) {
      eventHandlerList.add(eventHandler);
    }
  }

  @Override
  public void removeEventHandler(IHttpInterceptorEventHandler eventHandler) {
    synchronized(interceptorLock) {
      eventHandlerList.remove(eventHandler);
    }
  }

  @Override
  public void setInterceptLevel(TransactionDirection direction, HttpInterceptorLevel level) {
    synchronized(interceptorLock) {
      if (direction == TransactionDirection.DIRECTION_REQUEST) {
        interceptorLevelRequest = level;
        currentWorkspace.setIntegerProperty(propertyInterceptorLevelRequest, level.getSerializeValue());
      } else {
        interceptorLevelResponse = level;
        currentWorkspace.setIntegerProperty(propertyInterceptorLevelResponse, level.getSerializeValue());
      }
      releaseOnChange(direction);
    }
  }

  @Override
  public HttpInterceptorLevel getInterceptLevel( TransactionDirection direction) {
    synchronized(interceptorLock) {
      if (direction == TransactionDirection.DIRECTION_REQUEST) {
        return interceptorLevelRequest;
      } else {
        return interceptorLevelResponse;
      }
    }
  }

  @Override
  public int transactionQueueSize() {
    synchronized(interceptorLock) {
      return transactionQueue.size();
    }
  }

  @Override
  public IProxyTransaction[] getTransactions() {
    synchronized(interceptorLock) {
      return transactionQueue.toArray(new IProxyTransaction[transactionQueue.size()]);
    }
  }

  @Override
  public IProxyTransaction transactionQueueGet(int idx) {
    synchronized(interceptorLock) {
      if (transactionQueue.size() <= idx) {
        return null;
      }
      return transactionQueue.get(idx);
    }
  }

  /**
   * Notification that a proxy transaction queued by this interceptor was handled. The transaction is removed from the
   * transaction queue.
   *
   * @param transaction Transaction
   */
  public void notifyHandled(ProxyTransaction transaction) {
    synchronized(interceptorLock) {
      final int idx = transactionQueue.indexOf(transaction);
      transactionQueue.remove(idx);
      if (transactionQueue.size() == 0) {
        for (IHttpInterceptorEventHandler handler: eventHandlerList) {
          handler.notifyEmpty();
        }
      } else {
        for (IHttpInterceptorEventHandler handler: eventHandlerList) {
          handler.notifyRemove(idx);
        }
      }
    }
  }

  private IHttpConditionSet getBreakpointSet(TransactionDirection direction) {
    synchronized(interceptorLock) {
      if (direction == TransactionDirection.DIRECTION_REQUEST) {
        return breakpointSetRequest;
      } else {
        return breakpointSetResponse;
      }
    }
  }

  /**
   * Release transactions that no longer match interception criteria following a configuration change. Must be invoked
   * with interceptorLock synchronized.
   */
  private void releaseOnChange(TransactionDirection direction) {
    final HttpInterceptorLevel level = getInterceptLevel(direction);
    if (level != HttpInterceptorLevel.ENABLED_ALL) {
      if (level != HttpInterceptorLevel.DISABLED) {
        final IHttpConditionSet breakpointSet = getBreakpointSet(direction);
        for (int idx = 0; idx < transactionQueue.size(); idx++) {
          ProxyTransaction transaction = transactionQueue.get(idx);
          if (transaction.hasResponse() == (direction == TransactionDirection.DIRECTION_RESPONSE)) {
            if (interceptOnBreakpointSet(breakpointSet, transaction) == false) {
              transaction.doForward();
            }
          }
        }
      } else {
        for (int idx = 0; idx < transactionQueue.size(); idx++) {
          ProxyTransaction transaction = transactionQueue.get(idx);
          if (transaction.hasResponse() == (direction == TransactionDirection.DIRECTION_RESPONSE)) {
            transaction.doForward();
          }
        }
      }
    }
  }

  /**
   * Forward all pending transactions. Must be invoked with interceptorLock synchronized.
   */
  private void forwardAll() {
    for (int idx = 0; idx < transactionQueue.size(); idx++) {
      ProxyTransaction transaction = transactionQueue.get(idx);
      transaction.doDrop();
    }
  }
 
}
TOP

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

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.