/******************************************************************************* * 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.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.protocol.HttpContext; import com.subgraph.vega.api.http.proxy.IProxyTransaction; import com.subgraph.vega.api.http.proxy.IProxyTransactionEventHandler; import com.subgraph.vega.api.http.requests.IHttpRequestEngine; import com.subgraph.vega.api.http.requests.IHttpResponse; public class ProxyTransaction implements IProxyTransaction { private final IHttpRequestEngine requestEngine; private final HttpContext context; private IProxyTransactionEventHandler eventHandler; private HttpUriRequest request; private IHttpResponse response; private HttpInterceptor interceptor; private boolean isPending = false; private boolean doForward = false; private Lock lock = new ReentrantLock(); private Condition cv = lock.newCondition(); ProxyTransaction(IHttpRequestEngine requestEngine, HttpContext context) { this.requestEngine = requestEngine; this.context = context; } public IHttpRequestEngine getRequestEngine() { return requestEngine; } public HttpContext getContext() { return context; } public synchronized void setResponse(IHttpResponse response) { this.response = response; } public void await() throws InterruptedException { lock.lock(); try { while (isPending == true) { cv.await(); } } catch (InterruptedException e) { try { if (interceptor != null) { interceptor.notifyHandled(this); interceptor = null; } } finally { isPending = false; doForward = false; } throw e; } finally { try { if (interceptor != null) { interceptor.notifyHandled(this); interceptor = null; } } finally { lock.unlock(); } } } public synchronized void setPending(HttpInterceptor interceptor) { this.interceptor = interceptor; isPending = true; doForward = false; } public synchronized void setUnqueued() { interceptor = null; } public synchronized boolean getForward() { return doForward; } @Override public synchronized void setEventHandler(IProxyTransactionEventHandler eventHandler) { this.eventHandler = eventHandler; } @Override public synchronized void setRequest(HttpUriRequest request) { this.request = request; } @Override public synchronized boolean hasRequest() { return (request != null); } @Override public synchronized HttpUriRequest getRequest() { return request; } @Override public synchronized boolean hasResponse() { return (response != null); } @Override public synchronized IHttpResponse getResponse() { return response; } @Override public void doForward() { lock.lock(); try { if (isPending == true) { isPending = false; doForward = true; cv.signal(); } } finally { lock.unlock(); } } @Override public void doDrop() { lock.lock(); try { if (isPending == true) { isPending = false; doForward = false; cv.signal(); } } finally { lock.unlock(); } } /** * Signal that the pending transaction is about to be forwarded. */ public synchronized void signalForward() { if (eventHandler != null) { eventHandler.notifyForward(); } } /** * Signal that the transaction is complete. * * @param dropped Boolean indicating whether the transaction was dropped. */ public synchronized void signalComplete(boolean dropped) { if (eventHandler != null) { eventHandler.notifyComplete(dropped); } } }