/*
* 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 java.util.regex.Matcher;
import java.util.regex.Pattern;
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.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 Browser 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 Browser browser) {
this.browser = browser;
try {
browserFunction = new BrowserFunction(browser, "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(Browser 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 = 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) {
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();
}
}
}