Patch refactors SessionHandler and BrowserChannelClient to enable OOPHM clients
other than HtmlUnit. Removes need for UnsupportedOperationException and adds
generics to SessionHandler.
Patch by: t.broyer@gmail.com
Review by: amitmanjhi, jat
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7603 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java b/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
index 98569c6..be5c3b3 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
@@ -15,7 +15,6 @@
*/
package com.google.gwt.dev.shell;
-import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.SpecialDispatchId;
import com.google.gwt.dev.shell.BrowserChannel.Value.ValueType;
@@ -198,7 +197,7 @@
/**
* Hook interface for responding to messages.
*/
- public abstract static class SessionHandler {
+ public abstract static class SessionHandler<T extends BrowserChannel> {
/**
* Wrapper to return both a return value/exception and a flag as to whether
@@ -244,37 +243,7 @@
}
}
- public abstract void freeValue(BrowserChannel channel, int[] ids);
-
- public abstract ExceptionOrReturnValue getProperty(BrowserChannel channel,
- int refId, int dispId);
-
- public abstract ExceptionOrReturnValue invoke(BrowserChannel channel,
- Value thisObj, int dispId, Value[] args);
-
- /**
- * Load a new instance of a module.
- *
- * @param channel
- * @param moduleName
- * @param userAgent
- * @param url top-level URL of the main page, null if using an old plugin
- * @param tabKey opaque key of the tab, may be empty if the plugin can't
- * distinguish tabs or null if using an old plugin
- * @param sessionKey opaque key for this session, null if using an old plugin
- * @param userAgentIcon byte array containing an icon (which fits within
- * 24x24) representing the user agent or null if unavailable
- * @return a TreeLogger to use for the module's logs, or null if the module
- * load failed
- */
- public abstract TreeLogger loadModule(BrowserChannel channel,
- String moduleName, String userAgent, String url, String tabKey,
- String sessionKey, byte[] userAgentIcon);
-
- public abstract ExceptionOrReturnValue setProperty(BrowserChannel channel,
- int refId, int dispId, Value newValue);
-
- public abstract void unloadModule(BrowserChannel channel, String moduleName);
+ public abstract void freeValue(T channel, int[] ids);
}
/**
@@ -1639,101 +1608,6 @@
+ socket.getPort();
}
- public Value invoke(String methodName, Value vthis, Value[] vargs,
- SessionHandler handler) throws IOException, BrowserChannelException {
- new InvokeOnClientMessage(this, methodName, vthis, vargs).send();
- final ReturnMessage msg = reactToMessagesWhileWaitingForReturn(handler);
- return msg.returnValue;
- }
-
- /**
- * React to messages from the other side, where no return value is expected.
- *
- * @param handler
- * @throws RemoteDeathError
- */
- public void reactToMessages(SessionHandler handler) {
- do {
- try {
- getStreamToOtherSide().flush();
- MessageType messageType = Message.readMessageType(
- getStreamFromOtherSide());
- switch (messageType) {
- case FREE_VALUE:
- final FreeMessage freeMsg = FreeMessage.receive(this);
- handler.freeValue(this, freeMsg.getIds());
- break;
- case INVOKE:
- InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
- ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
- imsg.getMethodDispatchId(), imsg.getArgs());
- sendFreedValues();
- ReturnMessage.send(this, result);
- break;
- case INVOKE_SPECIAL:
- handleInvokeSpecial(handler);
- break;
- case QUIT:
- return;
- default:
- throw new RemoteDeathError(new BrowserChannelException(
- "Invalid message type " + messageType));
- }
- } catch (IOException e) {
- throw new RemoteDeathError(e);
- } catch (BrowserChannelException e) {
- throw new RemoteDeathError(e);
- }
- } while (true);
- }
-
- /**
- * React to messages from the other side, where a return value is expected.
- *
- * @param handler
- * @throws BrowserChannelException
- * @throws RemoteDeathError
- */
- public ReturnMessage reactToMessagesWhileWaitingForReturn(
- SessionHandler handler) throws BrowserChannelException, RemoteDeathError {
- do {
- try {
- getStreamToOtherSide().flush();
- MessageType messageType = Message.readMessageType(
- getStreamFromOtherSide());
- switch (messageType) {
- case FREE_VALUE:
- final FreeMessage freeMsg = FreeMessage.receive(this);
- handler.freeValue(this, freeMsg.getIds());
- break;
- case RETURN:
- return ReturnMessage.receive(this);
- case INVOKE:
- InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
- ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
- imsg.getMethodDispatchId(), imsg.getArgs());
- sendFreedValues();
- ReturnMessage.send(this, result);
- break;
- case INVOKE_SPECIAL:
- handleInvokeSpecial(handler);
- break;
- case QUIT:
- // if we got an unexpected QUIT here, the remote plugin probably
- // realized it was dying and had time to close the socket properly.
- throw new RemoteDeathError(null);
- default:
- throw new BrowserChannelException("Invalid message type "
- + messageType + " received waiting for return.");
- }
- } catch (IOException e) {
- throw new RemoteDeathError(e);
- } catch (BrowserChannelException e) {
- throw new RemoteDeathError(e);
- }
- } while (true);
- }
-
protected DataInputStream getStreamFromOtherSide() {
return streamFromOtherSide;
}
@@ -1797,6 +1671,19 @@
return value;
}
+ protected void sendFreedValues() throws IOException {
+ Set<Integer> freed = objectRefFactory.getRefIdsForCleanup();
+ int n = freed.size();
+ if (n > 0) {
+ int[] ids = new int[n];
+ int i = 0;
+ for (Integer id : freed) {
+ ids[i++] = id;
+ }
+ FreeMessage.send(this, ids);
+ }
+ }
+
protected void writeValue(DataOutputStream stream, Value value)
throws IOException {
if (value.isNull()) {
@@ -1827,39 +1714,4 @@
assert false;
}
}
-
- private void handleInvokeSpecial(SessionHandler handler) throws IOException,
- BrowserChannelException {
- final InvokeSpecialMessage ismsg = InvokeSpecialMessage.receive(this);
- Value[] args = ismsg.getArgs();
- ExceptionOrReturnValue retExc = null;
- switch (ismsg.getDispatchId()) {
- case GetProperty:
- assert args.length == 2;
- retExc = handler.getProperty(this, args[0].getInt(), args[1].getInt());
- break;
- case SetProperty:
- assert args.length == 3;
- retExc = handler.setProperty(this, args[0].getInt(), args[1].getInt(),
- args[2]);
- break;
- default:
- throw new HostedModeException("Unexpected InvokeSpecial method "
- + ismsg.getDispatchId());
- }
- ReturnMessage.send(this, retExc);
- }
-
- private void sendFreedValues() throws IOException {
- Set<Integer> freed = objectRefFactory.getRefIdsForCleanup();
- int n = freed.size();
- if (n > 0) {
- int[] ids = new int[n];
- int i = 0;
- for (Integer id : freed) {
- ids[i++] = id;
- }
- FreeMessage.send(this, ids);
- }
- }
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelClient.java b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelClient.java
index 6a7f56a..bae89b7 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelClient.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelClient.java
@@ -25,10 +25,26 @@
/**
* Implementation of the BrowserChannel for the client side.
- *
*/
public class BrowserChannelClient extends BrowserChannel {
+ /**
+ * Hook interface for responding to messages from the server.
+ */
+ public abstract static class SessionHandlerClient extends
+ SessionHandler<BrowserChannelClient> {
+
+ public abstract Object getSynchronizationObject();
+
+ public abstract String getUserAgent();
+
+ public abstract ExceptionOrReturnValue invoke(BrowserChannelClient channel,
+ Value thisObj, String methodName, Value[] args);
+
+ public abstract void loadJsni(BrowserChannelClient channel,
+ String jsniString);
+ }
+
private static class ClientObjectRefFactory implements ObjectRefFactory {
private final RemoteObjectTable<JavaObjectRef> remoteObjectTable;
@@ -55,7 +71,7 @@
}
}
- private final HtmlUnitSessionHandler htmlUnitSessionHandler;
+ private final SessionHandlerClient handler;
private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
private final String moduleName;
private final String tabKey;
@@ -67,7 +83,7 @@
public BrowserChannelClient(String addressParts[], String url,
String sessionKey, String moduleName, String versionString,
- HtmlUnitSessionHandler htmlUnitSessionHandler) throws IOException {
+ SessionHandlerClient sessionHandlerClient) throws IOException {
super(new Socket(addressParts[0], Integer.parseInt(addressParts[1])),
new ClientObjectRefFactory());
connected = true;
@@ -79,7 +95,7 @@
logger.setMaxDetail(TreeLogger.WARN);
logger.log(TreeLogger.SPAM, "BrowserChannelClient, versionString: "
+ versionString);
- this.htmlUnitSessionHandler = htmlUnitSessionHandler;
+ this.handler = sessionHandlerClient;
}
public boolean disconnectFromHost() throws IOException {
@@ -97,7 +113,7 @@
/**
* @return the negotiated protocol version -- only valid after {@link #init}
- * has returned.
+ * has returned.
*/
public int getProtocolVersion() {
return protocolVersion;
@@ -117,12 +133,12 @@
return false;
}
logger.log(TreeLogger.DEBUG, "sending " + MessageType.LOAD_MODULE
- + " message, userAgent: " + htmlUnitSessionHandler.getUserAgent());
+ + " message, userAgent: " + handler.getUserAgent());
ReturnMessage returnMessage = null;
- synchronized (htmlUnitSessionHandler.getHtmlPage()) {
+ synchronized (handler.getSynchronizationObject()) {
new LoadModuleMessage(this, url, tabKey, sessionKey, moduleName,
- htmlUnitSessionHandler.getUserAgent()).send();
- returnMessage = reactToMessages(htmlUnitSessionHandler, true);
+ handler.getUserAgent()).send();
+ returnMessage = reactToMessages(handler, true);
}
logger.log(TreeLogger.DEBUG, "loaded module, returnValue: "
+ returnMessage.getReturnValue() + ", isException: "
@@ -131,8 +147,7 @@
}
public ReturnMessage reactToMessagesWhileWaitingForReturn(
- HtmlUnitSessionHandler handler) throws IOException,
- BrowserChannelException {
+ SessionHandlerClient handler) throws IOException, BrowserChannelException {
ReturnMessage returnMessage = reactToMessages(handler, true);
return returnMessage;
}
@@ -167,9 +182,8 @@
return true;
}
- private ReturnMessage reactToMessages(
- HtmlUnitSessionHandler htmlUnitSessionHandler, boolean expectReturn)
- throws IOException, BrowserChannelException {
+ private ReturnMessage reactToMessages(SessionHandlerClient handler,
+ boolean expectReturn) throws IOException, BrowserChannelException {
while (true) {
ExceptionOrReturnValue returnValue;
MessageType type = Message.readMessageType(getStreamFromOtherSide());
@@ -179,21 +193,8 @@
switch (type) {
case INVOKE:
InvokeOnClientMessage invokeMessage = InvokeOnClientMessage.receive(this);
- returnValue = htmlUnitSessionHandler.invoke(this,
- invokeMessage.getThis(), invokeMessage.getMethodName(),
- invokeMessage.getArgs());
- htmlUnitSessionHandler.sendFreeValues(this);
- new ReturnMessage(this, returnValue.isException(),
- returnValue.getReturnValue()).send();
- break;
- case INVOKE_SPECIAL:
- InvokeSpecialMessage invokeSpecialMessage = InvokeSpecialMessage.receive(this);
- logger.log(TreeLogger.DEBUG, type + " message " + ", thisRef: "
- + invokeSpecialMessage.getArgs());
- returnValue = htmlUnitSessionHandler.invokeSpecial(this,
- invokeSpecialMessage.getDispatchId(),
- invokeSpecialMessage.getArgs());
- htmlUnitSessionHandler.sendFreeValues(this);
+ returnValue = handler.invoke(this, invokeMessage.getThis(),
+ invokeMessage.getMethodName(), invokeMessage.getArgs());
new ReturnMessage(this, returnValue.isException(),
returnValue.getReturnValue()).send();
break;
@@ -201,18 +202,18 @@
FreeMessage freeMessage = FreeMessage.receive(this);
logger.log(TreeLogger.DEBUG, type + " message "
+ freeMessage.getIds());
- htmlUnitSessionHandler.freeValue(this, freeMessage.getIds());
+ handler.freeValue(this, freeMessage.getIds());
// no response
break;
case LOAD_JSNI:
LoadJsniMessage loadJsniMessage = LoadJsniMessage.receive(this);
String jsniString = loadJsniMessage.getJsni();
- htmlUnitSessionHandler.loadJsni(this, jsniString);
+ handler.loadJsni(this, jsniString);
// no response
break;
case REQUEST_ICON:
RequestIconMessage.receive(this);
- // no need for icon here
+ // no need for icon here
UserAgentIconMessage.send(this, null);
break;
case RETURN:
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
index 682ce65..f81101b 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.HelpInfo;
+import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
import com.google.gwt.dev.shell.JsValue.DispatchObject;
import java.io.IOException;
@@ -34,6 +35,41 @@
*/
public class BrowserChannelServer extends BrowserChannel
implements Runnable {
+
+ /**
+ * Hook interface for responding to messages from the client.
+ */
+ public abstract static class SessionHandlerServer extends SessionHandler<BrowserChannelServer> {
+ public abstract ExceptionOrReturnValue getProperty(BrowserChannelServer channel,
+ int refId, int dispId);
+
+ public abstract ExceptionOrReturnValue invoke(BrowserChannelServer channel,
+ Value thisObj, int dispId, Value[] args);
+
+ /**
+ * Load a new instance of a module.
+ *
+ * @param channel
+ * @param moduleName
+ * @param userAgent
+ * @param url top-level URL of the main page, null if using an old plugin
+ * @param tabKey opaque key of the tab, may be empty if the plugin can't
+ * distinguish tabs or null if using an old plugin
+ * @param sessionKey opaque key for this session, null if using an old plugin
+ * @param userAgentIcon byte array containing an icon (which fits within
+ * 24x24) representing the user agent or null if unavailable
+ * @return a TreeLogger to use for the module's logs, or null if the module
+ * load failed
+ */
+ public abstract TreeLogger loadModule(BrowserChannelServer channel,
+ String moduleName, String userAgent, String url, String tabKey,
+ String sessionKey, byte[] userAgentIcon);
+
+ public abstract ExceptionOrReturnValue setProperty(BrowserChannelServer channel,
+ int refId, int dispId, Value newValue);
+
+ public abstract void unloadModule(BrowserChannelServer channel, String moduleName);
+ }
private static class ServerObjectRefFactory implements ObjectRefFactory {
@@ -71,7 +107,7 @@
private static final Object cacheLock = new Object();
- private final SessionHandler handler;
+ private final SessionHandlerServer handler;
private final boolean ignoreRemoteDeath;
@@ -95,7 +131,7 @@
* @throws IOException
*/
public BrowserChannelServer(TreeLogger initialLogger, Socket socket,
- SessionHandler handler, boolean ignoreRemoteDeath) throws IOException {
+ SessionHandlerServer handler, boolean ignoreRemoteDeath) throws IOException {
super(socket, new ServerObjectRefFactory());
this.handler = handler;
this.ignoreRemoteDeath = ignoreRemoteDeath;
@@ -104,7 +140,7 @@
// @VisibleForTesting
BrowserChannelServer(TreeLogger initialLogger, InputStream inputStream,
- OutputStream outputStream, SessionHandler handler,
+ OutputStream outputStream, SessionHandlerServer handler,
boolean ignoreRemoteDeath) {
super(inputStream, outputStream, new ServerObjectRefFactory());
this.handler = handler;
@@ -141,6 +177,12 @@
return protocolVersion;
}
+ public ReturnMessage invoke(String methodName, Value vthis, Value[] vargs,
+ SessionHandlerServer handler) throws IOException, BrowserChannelException {
+ new InvokeOnClientMessage(this, methodName, vthis, vargs).send();
+ return reactToMessagesWhileWaitingForReturn(handler);
+ }
+
/**
* @param ccl
* @param jsthis
@@ -217,6 +259,94 @@
}
}
+ /**
+ * React to messages from the other side, where no return value is expected.
+ *
+ * @param handler
+ * @throws RemoteDeathError
+ */
+ public void reactToMessages(SessionHandlerServer handler) {
+ do {
+ try {
+ getStreamToOtherSide().flush();
+ MessageType messageType = Message.readMessageType(
+ getStreamFromOtherSide());
+ switch (messageType) {
+ case FREE_VALUE:
+ final FreeMessage freeMsg = FreeMessage.receive(this);
+ handler.freeValue(this, freeMsg.getIds());
+ break;
+ case INVOKE:
+ InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
+ ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
+ imsg.getMethodDispatchId(), imsg.getArgs());
+ sendFreedValues();
+ ReturnMessage.send(this, result);
+ break;
+ case INVOKE_SPECIAL:
+ handleInvokeSpecial(handler);
+ break;
+ case QUIT:
+ return;
+ default:
+ throw new RemoteDeathError(new BrowserChannelException(
+ "Invalid message type " + messageType));
+ }
+ } catch (IOException e) {
+ throw new RemoteDeathError(e);
+ } catch (BrowserChannelException e) {
+ throw new RemoteDeathError(e);
+ }
+ } while (true);
+ }
+
+ /**
+ * React to messages from the other side, where a return value is expected.
+ *
+ * @param handler
+ * @throws BrowserChannelException
+ * @throws RemoteDeathError
+ */
+ public ReturnMessage reactToMessagesWhileWaitingForReturn(
+ SessionHandlerServer handler) throws BrowserChannelException, RemoteDeathError {
+ do {
+ try {
+ getStreamToOtherSide().flush();
+ MessageType messageType = Message.readMessageType(
+ getStreamFromOtherSide());
+ switch (messageType) {
+ case FREE_VALUE:
+ final FreeMessage freeMsg = FreeMessage.receive(this);
+ handler.freeValue(this, freeMsg.getIds());
+ break;
+ case RETURN:
+ return ReturnMessage.receive(this);
+ case INVOKE:
+ InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
+ ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
+ imsg.getMethodDispatchId(), imsg.getArgs());
+ sendFreedValues();
+ ReturnMessage.send(this, result);
+ break;
+ case INVOKE_SPECIAL:
+ handleInvokeSpecial(handler);
+ break;
+ case QUIT:
+ // if we got an unexpected QUIT here, the remote plugin probably
+ // realized it was dying and had time to close the socket properly.
+ throw new RemoteDeathError(null);
+ default:
+ throw new BrowserChannelException("Invalid message type "
+ + messageType + " received waiting for return.");
+ }
+ } catch (IOException e) {
+ throw new RemoteDeathError(e);
+ } catch (BrowserChannelException e) {
+ throw new RemoteDeathError(e);
+ }
+ } while (true);
+ }
+
public void run() {
try {
processConnection();
@@ -516,6 +646,28 @@
"No alternate transports supported");
}
+ private void handleInvokeSpecial(SessionHandlerServer handler) throws IOException,
+ BrowserChannelException {
+ final InvokeSpecialMessage ismsg = InvokeSpecialMessage.receive(this);
+ Value[] args = ismsg.getArgs();
+ ExceptionOrReturnValue retExc = null;
+ switch (ismsg.getDispatchId()) {
+ case GetProperty:
+ assert args.length == 2;
+ retExc = handler.getProperty(this, args[0].getInt(), args[1].getInt());
+ break;
+ case SetProperty:
+ assert args.length == 3;
+ retExc = handler.setProperty(this, args[0].getInt(), args[1].getInt(),
+ args[2]);
+ break;
+ default:
+ throw new HostedModeException("Unexpected InvokeSpecial method "
+ + ismsg.getDispatchId());
+ }
+ ReturnMessage.send(this, retExc);
+ }
+
private void init(TreeLogger initialLogger) {
this.logger = initialLogger;
Thread thread = new Thread(this);
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java b/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
index 02b10c4..284a0a8 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
@@ -17,7 +17,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
+import com.google.gwt.dev.shell.BrowserChannelServer.SessionHandlerServer;
import java.io.IOException;
import java.net.BindException;
@@ -32,7 +32,6 @@
*/
public class BrowserListener {
-
/**
* Get a query parameter to be added to the URL that specifies the address
* of this listener.
@@ -59,7 +58,7 @@
* @param handler
*/
public BrowserListener(final TreeLogger logger, String bindAddress,
- int port, final SessionHandler handler) {
+ int port, final SessionHandlerServer handler) {
try {
listenSocket = new ServerSocket();
listenSocket.setReuseAddress(true);
diff --git a/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java b/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
index a2a415c..987ca66 100644
--- a/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
+++ b/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
@@ -18,9 +18,9 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.shell.BrowserChannel.JavaObjectRef;
import com.google.gwt.dev.shell.BrowserChannel.JsObjectRef;
-import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
import com.google.gwt.dev.shell.BrowserChannel.Value;
import com.google.gwt.dev.shell.BrowserChannel.Value.ValueType;
+import com.google.gwt.dev.shell.BrowserChannelClient.SessionHandlerClient;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.gargoylesoftware.htmlunit.ScriptResult;
@@ -37,16 +37,13 @@
import net.sourceforge.htmlunit.corejs.javascript.Undefined;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
-import java.util.Set;
/**
- * Handle session tasks for HtmlUnit. TODO (amitmanjhi): refactor
- * SessionHandler.
+ * Handle session tasks for HtmlUnit.
*/
-public class HtmlUnitSessionHandler extends SessionHandler {
+public class HtmlUnitSessionHandler extends SessionHandlerClient {
private class ToStringMethod extends ScriptableObject implements Function {
@@ -93,17 +90,14 @@
* The htmlPage is also used to synchronize calls to Java code.
*/
private HtmlPage htmlPage;
- private Set<Integer> javaObjectsToFree;
-
private JavaScriptEngine jsEngine;
-
private IdentityHashMap<Scriptable, Integer> jsObjectToRef;
- private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
-
- private int nextRefId = 1;
+ private int nextRefId;
private Map<Integer, Scriptable> refToJsObject;
private SessionData sessionData;
+ private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
+
private final ToStringMethod toStringMethod = new ToStringMethod();
private final Window window;
@@ -117,7 +111,6 @@
+ htmlPage);
jsObjectToRef = new IdentityHashMap<Scriptable, Integer>();
- javaObjectsToFree = new HashSet<Integer>();
nextRefId = 1;
refToJsObject = new HashMap<Integer, Scriptable>();
@@ -126,7 +119,7 @@
}
@Override
- public void freeValue(BrowserChannel channel, int[] ids) {
+ public void freeValue(BrowserChannelClient channel, int[] ids) {
for (int id : ids) {
Scriptable scriptable = refToJsObject.remove(id);
if (scriptable != null) {
@@ -135,10 +128,6 @@
}
}
- public HtmlPage getHtmlPage() {
- return htmlPage;
- }
-
public JavaObject getOrCreateJavaObject(int refId, Context context) {
JavaObject javaObject = javaObjectCache.get(refId);
if (javaObject == null) {
@@ -148,30 +137,22 @@
return javaObject;
}
- @Override
- public ExceptionOrReturnValue getProperty(BrowserChannel channel, int refId,
- int dispId) {
- throw new UnsupportedOperationException(
- "getProperty should not be called on the client-side");
+ public HtmlPage getSynchronizationObject() {
+ return htmlPage;
}
public Object getToStringTearOff(Context jsContext) {
return toStringMethod;
}
+ @Override
public String getUserAgent() {
return "HtmlUnit-"
+ jsEngine.getWebClient().getBrowserVersion().getUserAgent();
}
@Override
- public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisObj,
- int dispId, Value[] args) {
- throw new UnsupportedOperationException(
- "should not be called on the client side");
- }
-
- public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisObj,
+ public ExceptionOrReturnValue invoke(BrowserChannelClient channel, Value thisObj,
String methodName, Value[] args) {
logger.log(TreeLogger.DEBUG, "INVOKE: thisObj: " + thisObj
+ ", methodName: " + methodName + ", args: " + args);
@@ -236,26 +217,13 @@
result));
}
- @SuppressWarnings("unused")
- public ExceptionOrReturnValue invokeSpecial(BrowserChannel channel,
- SpecialDispatchId specialDispatchId, Value[] args) {
- throw new UnsupportedOperationException(
- "InvokeSpecial must not be called on the client side");
- }
-
- public void loadJsni(BrowserChannel channel, String jsniString) {
+ @Override
+ public void loadJsni(BrowserChannelClient channel, String jsniString) {
logger.log(TreeLogger.SPAM, "LOAD_JSNI: " + jsniString);
ScriptResult scriptResult = htmlPage.executeJavaScript(jsniString);
logger.log(TreeLogger.INFO, "LOAD_JSNI: scriptResult=" + scriptResult);
}
- @Override
- public TreeLogger loadModule(BrowserChannel channel, String moduleName,
- String userAgent, String url, String tabKey, String sessionKey,
- byte[] userAgentIcon) {
- throw new UnsupportedOperationException("loadModule must not be called");
- }
-
public Value makeValueFromJsval(Context jsContext, Object value) {
if (value == Undefined.instance) {
return new Value();
@@ -291,38 +259,10 @@
return new Value(value);
}
- // TODO: check synchronization and multi-threading
- public void sendFreeValues(BrowserChannel channel) {
- int size = javaObjectsToFree.size();
- if (size == 0) {
- return;
- }
- int ids[] = new int[size];
- int index = 0;
- for (int id : javaObjectsToFree) {
- ids[index++] = id;
- }
- if (ServerMethods.freeJava(channel, this, ids)) {
- javaObjectsToFree.clear();
- }
- }
-
- @Override
- public ExceptionOrReturnValue setProperty(BrowserChannel channel, int refId,
- int dispId, Value newValue) {
- throw new UnsupportedOperationException(
- "setProperty should not be called on the client-side");
- }
-
public void setSessionData(SessionData sessionData) {
this.sessionData = sessionData;
}
- @Override
- public void unloadModule(BrowserChannel channel, String moduleName) {
- throw new UnsupportedOperationException("unloadModule must not be called");
- }
-
/*
* Returning java objects works. No need to return NativeNumber, NativeString,
* NativeBoolean, or Undefined.
@@ -370,5 +310,4 @@
}
return currentUrl;
}
-
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/JavaObject.java b/dev/core/src/com/google/gwt/dev/shell/JavaObject.java
index c66d285..9a4a0ea 100644
--- a/dev/core/src/com/google/gwt/dev/shell/JavaObject.java
+++ b/dev/core/src/com/google/gwt/dev/shell/JavaObject.java
@@ -45,17 +45,17 @@
}
static ExceptionOrReturnValue getReturnFromJavaMethod(Context cx,
- HtmlUnitSessionHandler sessionHandler, BrowserChannel channel,
+ HtmlUnitSessionHandler sessionHandler, BrowserChannelClient channel,
int dispatchId, Value thisValue, Value valueArgs[]) {
- synchronized (sessionHandler.getHtmlPage()) {
+ synchronized (sessionHandler.getSynchronizationObject()) {
try {
new InvokeOnServerMessage(channel, dispatchId, thisValue, valueArgs).send();
} catch (IOException e) {
return DEFAULT_VALUE;
}
try {
- ReturnMessage returnMessage = ((BrowserChannelClient) channel).reactToMessagesWhileWaitingForReturn(sessionHandler);
+ ReturnMessage returnMessage = channel.reactToMessagesWhileWaitingForReturn(sessionHandler);
return new ExceptionOrReturnValue(returnMessage.isException(),
returnMessage.getReturnValue());
} catch (IOException e) {
diff --git a/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java b/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
index 65c6120..243185c 100644
--- a/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
+++ b/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
@@ -17,8 +17,8 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.ModuleHandle;
-import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
import com.google.gwt.dev.shell.BrowserChannel.Value;
+import com.google.gwt.dev.shell.BrowserChannelServer.SessionHandlerServer;
import com.google.gwt.dev.shell.JsValue.DispatchMethod;
import com.google.gwt.dev.shell.JsValue.DispatchObject;
import com.google.gwt.dev.util.PerfLogger;
@@ -31,7 +31,7 @@
/**
*
*/
-public class OophmSessionHandler extends SessionHandler {
+public class OophmSessionHandler extends SessionHandlerServer {
private BrowserWidgetHost host;
@@ -53,23 +53,21 @@
}
@Override
- public void freeValue(BrowserChannel channel, int[] ids) {
- BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
- ServerObjectsTable localObjects = serverChannel.getJavaObjectsExposedInBrowser();
+ public void freeValue(BrowserChannelServer channel, int[] ids) {
+ ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
for (int id : ids) {
localObjects.free(id);
}
}
@Override
- public ExceptionOrReturnValue getProperty(BrowserChannel channel, int refId,
+ public ExceptionOrReturnValue getProperty(BrowserChannelServer channel, int refId,
int dispId) {
- BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
- ModuleSpace moduleSpace = moduleMap.get(serverChannel);
- ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+ ModuleSpace moduleSpace = moduleMap.get(channel);
+ ModuleHandle moduleHandle = moduleHandleMap.get(channel);
assert moduleSpace != null && moduleHandle != null;
TreeLogger logger = moduleHandle.getLogger();
- ServerObjectsTable localObjects = serverChannel.getJavaObjectsExposedInBrowser();
+ ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
try {
JsValueOOPHM obj = new JsValueOOPHM();
DispatchObject dispObj;
@@ -81,14 +79,14 @@
+ ccl.getClassInfoByDispId(dispId).getMember(dispId) + "]) on "
+ obj.toString(), null);
JsValueOOPHM jsval = (JsValueOOPHM) dispObj.getField(dispId);
- Value retVal = serverChannel.convertFromJsValue(localObjects, jsval);
+ Value retVal = channel.convertFromJsValue(localObjects, jsval);
branch.log(TreeLogger.SPAM, "result is " + retVal, null);
return new ExceptionOrReturnValue(false, retVal);
} catch (Throwable t) {
JsValueOOPHM jsval = new JsValueOOPHM();
JsValueGlue.set(jsval, moduleSpace.getIsolatedClassLoader(),
t.getClass(), t);
- Value retVal = serverChannel.convertFromJsValue(localObjects, jsval);
+ Value retVal = channel.convertFromJsValue(localObjects, jsval);
return new ExceptionOrReturnValue(true, retVal);
}
}
@@ -97,12 +95,11 @@
* Invoke a method on a server object in from client code.
*/
@Override
- public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisVal,
+ public ExceptionOrReturnValue invoke(BrowserChannelServer channel, Value thisVal,
int methodDispatchId, Value[] args) {
- BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
- ServerObjectsTable localObjects = serverChannel.getJavaObjectsExposedInBrowser();
- ModuleSpace moduleSpace = moduleMap.get(serverChannel);
- ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+ ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
+ ModuleSpace moduleSpace = moduleMap.get(channel);
+ ModuleHandle moduleHandle = moduleHandleMap.get(channel);
assert moduleSpace != null && moduleHandle != null;
TreeLogger logger = moduleHandle.getLogger();
CompilingClassLoader cl = moduleSpace.getIsolatedClassLoader();
@@ -113,7 +110,7 @@
}
JsValueOOPHM jsThis = new JsValueOOPHM();
- serverChannel.convertToJsValue(cl, localObjects, thisVal, jsThis);
+ channel.convertToJsValue(cl, localObjects, thisVal, jsThis);
TreeLogger branch = TreeLogger.NULL;
if (logger.isLoggable(TreeLogger.SPAM)) {
@@ -136,7 +133,7 @@
JsValueOOPHM[] jsArgs = new JsValueOOPHM[args.length];
for (int i = 0; i < args.length; ++i) {
jsArgs[i] = new JsValueOOPHM();
- serverChannel.convertToJsValue(cl, localObjects, args[i], jsArgs[i]);
+ channel.convertToJsValue(cl, localObjects, args[i], jsArgs[i]);
branch.log(TreeLogger.SPAM, " arg " + i + " = " + jsArgs[i].toString(),
null);
}
@@ -160,27 +157,26 @@
JsValueGlue.set(jsRetVal, moduleSpace.getIsolatedClassLoader(),
t.getClass(), t);
}
- Value retVal = serverChannel.convertFromJsValue(localObjects, jsRetVal);
+ Value retVal = channel.convertFromJsValue(localObjects, jsRetVal);
return new ExceptionOrReturnValue(exception, retVal);
}
@Override
- public synchronized TreeLogger loadModule(BrowserChannel channel,
+ public synchronized TreeLogger loadModule(BrowserChannelServer channel,
String moduleName, String userAgent, String url, String tabKey,
String sessionKey, byte[] userAgentIcon) {
PerfLogger.start("OophmSessionHandler.loadModule " + moduleName);
- BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
ModuleHandle moduleHandle = host.createModuleLogger(moduleName, userAgent,
- url, tabKey, sessionKey, serverChannel, userAgentIcon);
+ url, tabKey, sessionKey, channel, userAgentIcon);
TreeLogger logger = moduleHandle.getLogger();
- moduleHandleMap.put(serverChannel, moduleHandle);
+ moduleHandleMap.put(channel, moduleHandle);
ModuleSpace moduleSpace = null;
try {
// Attach a new ModuleSpace to make it programmable.
ModuleSpaceHost msh = host.createModuleSpaceHost(moduleHandle,
moduleName);
- moduleSpace = new ModuleSpaceOOPHM(msh, moduleName, serverChannel);
- moduleMap.put(serverChannel, moduleSpace);
+ moduleSpace = new ModuleSpaceOOPHM(msh, moduleName, channel);
+ moduleMap.put(channel, moduleSpace);
PerfLogger.start("ModuleSpace.onLoad");
moduleSpace.onLoad(logger);
moduleHandle.getLogger().log(TreeLogger.INFO,
@@ -197,8 +193,8 @@
moduleSpace.dispose();
}
moduleHandle.unload();
- moduleMap.remove(serverChannel);
- moduleHandleMap.remove(serverChannel);
+ moduleMap.remove(channel);
+ moduleHandleMap.remove(channel);
return null;
} finally {
PerfLogger.end();
@@ -208,14 +204,13 @@
}
@Override
- public ExceptionOrReturnValue setProperty(BrowserChannel channel, int refId,
+ public ExceptionOrReturnValue setProperty(BrowserChannelServer channel, int refId,
int dispId, Value newValue) {
- BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
- ModuleSpace moduleSpace = moduleMap.get(serverChannel);
- ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+ ModuleSpace moduleSpace = moduleMap.get(channel);
+ ModuleHandle moduleHandle = moduleHandleMap.get(channel);
assert moduleSpace != null && moduleHandle != null;
TreeLogger logger = moduleHandle.getLogger();
- ServerObjectsTable localObjects = serverChannel.getJavaObjectsExposedInBrowser();
+ ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
try {
JsValueOOPHM obj = new JsValueOOPHM();
DispatchObject dispObj;
@@ -225,7 +220,7 @@
logger.log(TreeLogger.SPAM, "Client special invoke of setProperty(id="
+ dispId + ", newValue=" + newValue + ") on " + obj.toString(), null);
JsValueOOPHM jsval = new JsValueOOPHM();
- serverChannel.convertToJsValue(moduleSpace.getIsolatedClassLoader(),
+ channel.convertToJsValue(moduleSpace.getIsolatedClassLoader(),
localObjects, newValue, jsval);
dispObj.setField(dispId, jsval);
return new ExceptionOrReturnValue(false, newValue);
@@ -233,16 +228,15 @@
JsValueOOPHM jsval = new JsValueOOPHM();
JsValueGlue.set(jsval, moduleSpace.getIsolatedClassLoader(),
t.getClass(), t);
- Value retVal = serverChannel.convertFromJsValue(localObjects, jsval);
+ Value retVal = channel.convertFromJsValue(localObjects, jsval);
return new ExceptionOrReturnValue(true, retVal);
}
}
@Override
- public void unloadModule(BrowserChannel channel, String moduleName) {
- BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
- ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
- ModuleSpace moduleSpace = moduleMap.get(serverChannel);
+ public void unloadModule(BrowserChannelServer channel, String moduleName) {
+ ModuleHandle moduleHandle = moduleHandleMap.get(channel);
+ ModuleSpace moduleSpace = moduleMap.get(channel);
if (moduleSpace == null || moduleHandle == null) {
topLogger.log(TreeLogger.ERROR, "Unload request without a module loaded",
null);
@@ -254,7 +248,7 @@
+ ")", null);
moduleSpace.dispose();
moduleHandle.unload();
- moduleMap.remove(serverChannel);
- moduleHandleMap.remove(serverChannel);
+ moduleMap.remove(channel);
+ moduleHandleMap.remove(channel);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/ServerMethods.java b/dev/core/src/com/google/gwt/dev/shell/ServerMethods.java
index e1051d3..d342874 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ServerMethods.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ServerMethods.java
@@ -20,6 +20,7 @@
import com.google.gwt.dev.shell.BrowserChannel.ReturnMessage;
import com.google.gwt.dev.shell.BrowserChannel.Value;
import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.SpecialDispatchId;
+import com.google.gwt.dev.shell.BrowserChannelClient.SessionHandlerClient;
import java.io.IOException;
@@ -34,9 +35,9 @@
* @param ids ID of object to free
* @return false if an error occurred
*/
- static boolean freeJava(BrowserChannel channel,
- HtmlUnitSessionHandler handler, int ids[]) {
- if (!((BrowserChannelClient) channel).isConnected()) {
+ static boolean freeJava(BrowserChannelClient channel,
+ SessionHandlerClient handler, int ids[]) {
+ if (!channel.isConnected()) {
// ignoring freeJava after disconnect.
return true;
}
@@ -55,9 +56,9 @@
* @param dispatchId dispatch ID of field
* @return the value of the property, undef if none (or on error)
*/
- static Value getProperty(BrowserChannel channel,
- HtmlUnitSessionHandler handler, int objectRef, int dispatchId) {
- if (!((BrowserChannelClient) channel).isConnected()) {
+ static Value getProperty(BrowserChannelClient channel,
+ SessionHandlerClient handler, int objectRef, int dispatchId) {
+ if (!channel.isConnected()) {
// ignoring getProperty() after disconnect
return new Value();
}
@@ -67,11 +68,10 @@
args[1] = new Value();
args[1].setInt(dispatchId);
- synchronized (handler.getHtmlPage()) {
+ synchronized (handler.getSynchronizationObject()) {
try {
new InvokeSpecialMessage(channel, SpecialDispatchId.GetProperty, args).send();
- // TODO: refactor in order to remove cast.
- ReturnMessage returnMessage = ((BrowserChannelClient) channel).reactToMessagesWhileWaitingForReturn(handler);
+ ReturnMessage returnMessage = channel.reactToMessagesWhileWaitingForReturn(handler);
if (!returnMessage.isException()) {
return returnMessage.getReturnValue();
}
@@ -90,8 +90,8 @@
* @param value value to store in the property
* @return false if an error occurred
*/
- static boolean setProperty(BrowserChannel channel,
- HtmlUnitSessionHandler handler, int objectRef, int dispatchId, Value value) {
+ static boolean setProperty(BrowserChannelClient channel,
+ SessionHandlerClient handler, int objectRef, int dispatchId, Value value) {
Value args[] = new Value[3];
for (int i = 0; i < args.length; i++) {
args[i] = new Value();
@@ -99,10 +99,10 @@
args[0].setInt(objectRef);
args[1].setInt(dispatchId);
args[2] = value;
- synchronized (handler.getHtmlPage()) {
+ synchronized (handler.getSynchronizationObject()) {
try {
new InvokeSpecialMessage(channel, SpecialDispatchId.SetProperty, args).send();
- ReturnMessage returnMessage = ((BrowserChannelClient) channel).reactToMessagesWhileWaitingForReturn(handler);
+ ReturnMessage returnMessage = channel.reactToMessagesWhileWaitingForReturn(handler);
if (!returnMessage.isException()) {
return true;
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/SessionData.java b/dev/core/src/com/google/gwt/dev/shell/SessionData.java
index 82281c3..8f04d27 100644
--- a/dev/core/src/com/google/gwt/dev/shell/SessionData.java
+++ b/dev/core/src/com/google/gwt/dev/shell/SessionData.java
@@ -19,20 +19,19 @@
* A class to encapsulate data needed by {@code JavaObject}.
*/
public class SessionData {
- private final BrowserChannel browserChannel;
+ private final BrowserChannelClient browserChannel;
private final HtmlUnitSessionHandler sessionHandler;
- public SessionData(HtmlUnitSessionHandler sessionHandler, BrowserChannel browserChannel) {
+ public SessionData(HtmlUnitSessionHandler sessionHandler, BrowserChannelClient browserChannel) {
this.sessionHandler = sessionHandler;
this.browserChannel = browserChannel;
}
- public BrowserChannel getChannel() {
+ public BrowserChannelClient getChannel() {
return browserChannel;
}
public HtmlUnitSessionHandler getSessionHandler() {
return sessionHandler;
}
-
}
diff --git a/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java b/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java
index d981c37..eb90b23 100644
--- a/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java
+++ b/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java
@@ -24,9 +24,9 @@
import com.google.gwt.dev.shell.BrowserChannel.QuitMessage;
import com.google.gwt.dev.shell.BrowserChannel.RequestIconMessage;
import com.google.gwt.dev.shell.BrowserChannel.ReturnMessage;
-import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
import com.google.gwt.dev.shell.BrowserChannel.UserAgentIconMessage;
import com.google.gwt.dev.shell.BrowserChannel.Value;
+import com.google.gwt.dev.shell.BrowserChannelServer.SessionHandlerServer;
import junit.framework.TestCase;
@@ -52,7 +52,7 @@
public TestBrowserChannelServer(TreeLogger logger,
InputStream inputStream, OutputStream outputStream,
- SessionHandler handler) throws IOException {
+ SessionHandlerServer handler) {
super(logger, inputStream, outputStream, handler, true);
}
@@ -101,7 +101,7 @@
* A SessionHandler which keeps track of parameters from the LoadModule
* message, but mocks out everything else.
*/
- private static class TestSessionHandler extends SessionHandler {
+ private static class TestSessionHandler extends SessionHandlerServer {
private String loadedModule;
private String userAgent;
@@ -112,7 +112,7 @@
private String moduleName;
@Override
- public void freeValue(BrowserChannel channel, int[] ids) {
+ public void freeValue(BrowserChannelServer channel, int[] ids) {
}
public String getLoadedModule() {
@@ -124,7 +124,7 @@
}
@Override
- public ExceptionOrReturnValue getProperty(BrowserChannel channel,
+ public ExceptionOrReturnValue getProperty(BrowserChannelServer channel,
int refId, int dispId) {
return new ExceptionOrReturnValue(false, new Value());
}
@@ -150,13 +150,13 @@
}
@Override
- public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisObj,
+ public ExceptionOrReturnValue invoke(BrowserChannelServer channel, Value thisObj,
int dispId, Value[] args) {
return new ExceptionOrReturnValue(false, new Value());
}
@Override
- public TreeLogger loadModule(BrowserChannel channel, String moduleName,
+ public TreeLogger loadModule(BrowserChannelServer channel, String moduleName,
String userAgent, String url, String tabKey, String sessionKey,
byte[] userAgentIcon) {
loadedModule = moduleName;
@@ -170,13 +170,13 @@
}
@Override
- public ExceptionOrReturnValue setProperty(BrowserChannel channel,
+ public ExceptionOrReturnValue setProperty(BrowserChannelServer channel,
int refId, int dispId, Value newValue) {
return new ExceptionOrReturnValue(false, new Value());
}
@Override
- public void unloadModule(BrowserChannel channel, String moduleName) {
+ public void unloadModule(BrowserChannelServer channel, String moduleName) {
loadedModule = null;
}
}