/* * Created on Jun 29, 2006 10:16:26 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.browser.msg; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.browser.*; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher; import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener; import com.aelitis.azureus.ui.swt.browser.BrowserWrapper; import com.aelitis.azureus.util.JSONUtils; import com.aelitis.azureus.util.UrlFilter; /** * Dispatches messages to listeners registered with unique IDs. */ public class MessageDispatcherSWT implements BrowserMessageDispatcher { private ClientMessageContext context; private Map<String, BrowserMessageListener> listeners = new HashMap<String, BrowserMessageListener>(); private BrowserWrapper browser; private BrowserFunction browserFunction; /** * Registers itself as a listener to receive sequence number reset message. */ public MessageDispatcherSWT(ClientMessageContext context) { this.context = context; } public void registerBrowser(final BrowserWrapper browser) { this.browser = browser; try { browserFunction = new BrowserFunction(browser.getBrowser(), "sendMessageToAZ") { public Object function(Object[] args) { if (args == null) { context.debug("sendMessageToAZ: arguments null on " + browser.getUrl()); return null; } if (args.length != 3 && args.length != 2) { context.debug("sendMessageToAZ: # arguments not 2 or 3 (" + args.length + ") on " + browser.getUrl()); return null; } if (!(args[0] instanceof String)) { context.debug("sendMessageToAZ: Param 1 not String"); return null; } if (!(args[1] instanceof String)) { context.debug("sendMessageToAZ: Param 2 not String"); return null; } Map<?, ?> params = Collections.EMPTY_MAP; if (args.length == 3) { if (!(args[2] instanceof String)) { context.debug("sendMessageToAZ: Param 3 not String"); return null; } params = JSONUtils.decodeJSON((String)args[2]); } BrowserMessage message = new BrowserMessage((String) args[0], (String) args[1], params); message.setReferer(browser.getUrl()); dispatch(message); return null; } }; } catch (Throwable t) { Debug.out(t); } } /** * Detaches this dispatcher from the given {@link Browser}. * This dispatcher listens for dispose events from the browser * and calls this method in response. * * @param browser {@link Browser} which will no longer send messages */ public void deregisterBrowser(BrowserWrapper browser) { if (browserFunction != null && !browserFunction.isDisposed()) { browserFunction.dispose(); } } /** * Registers the given listener for the given ID. * * @param id unique identifier used when dispatching messages * @param listener receives messages targetted at the given ID * * @throws IllegalStateException * if another listener is already registered under the same ID */ public synchronized void addListener(BrowserMessageListener listener) { String id = listener.getId(); BrowserMessageListener registered = listeners.get(id); if (registered != null) { if (registered != listener) { throw new IllegalStateException("Listener " + registered.getClass().getName() + " already registered for ID " + id); } } else { listener.setContext(context); listeners.put(id, listener); } } /** * Deregisters the listener with the given ID. * * @param id unique identifier of the listener to be removed */ public synchronized void removeListener(BrowserMessageListener listener) { removeListener(listener.getId()); } /** * Deregisters the listener with the given ID. * * @param id unique identifier of the listener to be removed */ public synchronized void removeListener(String id) { BrowserMessageListener removed; synchronized( this ){ removed = listeners.remove(id); } if (removed == null) { // throw new IllegalStateException("No listener is registered for ID " + id); } else { removed.setContext(null); } } // @see com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcher#getListener(java.lang.String) public BrowserMessageListener getListener(String id) { synchronized( this ){ return listeners.get(id); } } // @see com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcher#dispatch(com.aelitis.azureus.core.messenger.browser.BrowserMessage) public void dispatch(final BrowserMessage message) { if (message == null) { return; } String referer = message.getReferer(); if (referer != null && !UrlFilter.getInstance().urlCanRPC(referer)) { context.debug("blocked " + message + "\n " + referer); return; } context.debug("Received " + message); if (browser != null && !browser.isDisposed() && Utils.isThisThreadSWT()) { context.debug(" browser url: " + browser.getUrl()); } // handle messages for dispatcher and context regardless of sequence number String listenerId = message.getListenerId(); if ("lightbox-browser".equals(listenerId)) { listenerId = "display"; } final BrowserMessageListener listener = getListener(listenerId); if (listener == null) { context.debug("No listener registered with ID " + listenerId); } else { new AEThread2("dispatch for " + listenerId, true) { public void run() { listener.handleMessage(message); message.complete(true, true, null); } }.start(); } } }