/* Copyright (C) 2009 Rachel Engel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package com.isecpartners.gizmo; import java.util.ArrayList; import java.util.concurrent.LinkedBlockingQueue; /** * This class forwards messages from the various message handlers to the gui. There are usually * any number of client handlers running in the background that need to forward their responses * to the gui. To put some order around this, they post the messages they handle to a synchronized * queue in this class, which in turn forwards the requests on to the display. */ public class MessageForwarder implements Runnable { /** The protocol handlers for various protocol types are kept here (httphandler is one instance) * These handlers are responsible for keeping track of request/response pairs that are currently * being processed. */ ArrayList<HTTPHandler> handlers = new ArrayList<HTTPHandler>(); /** When a protocol handler is created, it's passed into the message forwarder for processing * through use of this queue. */ LinkedBlockingQueue<HTTPHandler> handlerQueue = new LinkedBlockingQueue<HTTPHandler>(); /** When request/response pairs have been processed and are ready to be displayed in the gui, * they get put on this queue, and shuffled off to the gui by the loop below */ LinkedBlockingQueue<HTTPMessage> request_queue = new LinkedBlockingQueue<HTTPMessage>(); private Object lock; private GizmoView screen; /** * @param lock The lock to use. * @param screen The screen to write to. */ MessageForwarder(Object lock, GizmoView screen) { this.lock = lock; this.screen = screen; } /** * @param handler The handler to add to the queue. */ public void addHandler(HTTPHandler handler) { handlerQueue.add(handler); handler.setLock(lock); } /** * TODO: Explain this method. */ public void run() { // XXX: Is this not the same as screen? while (true) { try { while (! request_queue.isEmpty()) { // XXX: request_queue is a queue of HTTPMessages, not // HttpRequests. HttpRequest next = (HttpRequest) request_queue.take(); if (next == null) { continue; } if (GizmoView.getView().intercepting() && GizmoView.getView().matchRequest(next.contents())) { screen.addIntercept(next, next.getURL() + "\n"); } else { if (! next.isSent()) { synchronized (next) { next.notifyAll(); } next.fetchResponse(true); } else { screen.append(next, "\n", next.getURL() + "\n"); screen.append(next.getResponse(), "\n\n"); } } } } catch (Exception e) { System.out.println(e); } while (request_queue.isEmpty()) { synchronized (lock) { try { lock.wait(); } catch (Exception e) { System.out.println(e); } } } } } /** * @param request The request to add to the queue. */ void addMessage(HttpRequest request) { request_queue.add(request); } }