com.google.gwt.dev.shell.OophmSessionHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.dev.shell.OophmSessionHandler.java

Source

/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.shell;

import java.lang.reflect.Member;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.ModuleHandle;
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.log.speedtracer.DevModeEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;

/**
 *
 */
public class OophmSessionHandler extends SessionHandlerServer {
    private BrowserWidgetHost host;

    private Map<BrowserChannelServer, ModuleSpace> moduleMap = Collections
            .synchronizedMap(new HashMap<BrowserChannelServer, ModuleSpace>());

    private Map<BrowserChannelServer, ModuleHandle> moduleHandleMap = Collections
            .synchronizedMap(new HashMap<BrowserChannelServer, ModuleHandle>());

    private final TreeLogger topLogger;

    /**
     * Listens for new connections from browsers.
     *
     * @param topLogger
     *            logger to use for non-module-related messages
     * @param host
     *            BrowserWidgetHost instance
     */
    public OophmSessionHandler(TreeLogger topLogger, BrowserWidgetHost host) {
        this.host = host;
        this.topLogger = topLogger;
    }

    @Override
    public void freeValue(BrowserChannelServer channel, int[] ids) {
        ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
        for (int id : ids) {
            localObjects.free(id);
        }
    }

    @Override
    public ExceptionOrReturnValue getProperty(BrowserChannelServer channel, int refId, int dispId) {
        ModuleSpace moduleSpace = moduleMap.get(channel);
        ModuleHandle moduleHandle = moduleHandleMap.get(channel);
        assert moduleSpace != null && moduleHandle != null;
        TreeLogger logger = moduleHandle.getLogger();
        ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
        try {
            JsValueOOPHM obj = new JsValueOOPHM();
            DispatchObject dispObj;
            CompilingClassLoader ccl = moduleSpace.getIsolatedClassLoader();
            obj.setWrappedJavaObject(ccl, localObjects.get(refId));
            dispObj = obj.getJavaObjectWrapper();
            TreeLogger branch = logger.branch(TreeLogger.SPAM, "Client special invoke of getProperty(" + dispId
                    + " [" + ccl.getClassInfoByDispId(dispId).getMember(dispId) + "]) on " + obj.toString(), null);
            JsValueOOPHM jsval = (JsValueOOPHM) dispObj.getField(dispId);
            Value retVal = channel.convertFromJsValue(localObjects, jsval);
            if (logger.isLoggable(TreeLogger.SPAM)) {
                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 = channel.convertFromJsValue(localObjects, jsval);
            return new ExceptionOrReturnValue(true, retVal);
        }
    }

    /**
     * Invoke a method on a server object in from client code.
     */
    @Override
    public ExceptionOrReturnValue invoke(BrowserChannelServer channel, Value thisVal, int methodDispatchId,
            Value[] args) {
        Event jsToJavaCallEvent = SpeedTracerLogger.start(channel.getDevModeSession(),
                DevModeEventType.JS_TO_JAVA_CALL);
        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();
        // Treat dispatch id 0 as toString()
        if (methodDispatchId == 0) {
            methodDispatchId = cl.getDispId("java.lang.Object::toString()");
        }
        JsValueOOPHM jsThis = new JsValueOOPHM();
        channel.convertToJsValue(cl, localObjects, thisVal, jsThis);
        if (SpeedTracerLogger.jsniCallLoggingEnabled()) {
            DispatchClassInfo clsInfo = cl.getClassInfoByDispId(methodDispatchId);
            if (clsInfo != null) {
                Member member = clsInfo.getMember(methodDispatchId);
                if (member != null) {
                    jsToJavaCallEvent.addData("name", member.toString());
                }
            }
        }
        TreeLogger branch = TreeLogger.NULL;
        if (logger.isLoggable(TreeLogger.SPAM)) {
            StringBuffer logMsg = new StringBuffer();
            logMsg.append("Client invoke of ");
            logMsg.append(methodDispatchId);
            DispatchClassInfo classInfo = cl.getClassInfoByDispId(methodDispatchId);
            if (classInfo != null) {
                Member member = classInfo.getMember(methodDispatchId);
                if (member != null) {
                    logMsg.append(" (");
                    logMsg.append(member.getName());
                    logMsg.append(")");
                }
            }
            logMsg.append(" on ");
            logMsg.append(jsThis.toString());
            branch = logger.branch(TreeLogger.SPAM, logMsg.toString(), null);
        }
        JsValueOOPHM[] jsArgs = new JsValueOOPHM[args.length];
        for (int i = 0; i < args.length; ++i) {
            jsArgs[i] = new JsValueOOPHM();
            channel.convertToJsValue(cl, localObjects, args[i], jsArgs[i]);
            if (logger.isLoggable(TreeLogger.SPAM)) {
                branch.log(TreeLogger.SPAM, " arg " + i + " = " + jsArgs[i].toString(), null);
            }
        }
        JsValueOOPHM jsRetVal = new JsValueOOPHM();
        JsValueOOPHM jsMethod;
        DispatchObject dispObj;
        if (jsThis.isWrappedJavaObject()) {
            // If this is a wrapped object, get get the method off it.
            dispObj = jsThis.getJavaObjectWrapper();
        } else {
            // Look it up on the static dispatcher.
            dispObj = (DispatchObject) moduleSpace.getStaticDispatcher();
        }
        jsMethod = (JsValueOOPHM) dispObj.getField(methodDispatchId);
        DispatchMethod dispMethod = jsMethod.getWrappedJavaFunction();
        boolean exception;
        try {
            exception = dispMethod.invoke(jsThis, jsArgs, jsRetVal);
        } catch (Throwable t) {
            exception = true;
            JsValueGlue.set(jsRetVal, moduleSpace.getIsolatedClassLoader(), t.getClass(), t);
        }
        Value retVal = channel.convertFromJsValue(localObjects, jsRetVal);
        jsToJavaCallEvent.end();
        return new ExceptionOrReturnValue(exception, retVal);
    }

    @Override
    public synchronized TreeLogger loadModule(BrowserChannelServer channel, String moduleName, String userAgent,
            String url, String tabKey, String sessionKey, byte[] userAgentIcon) {
        Event moduleInit = SpeedTracerLogger.start(channel.getDevModeSession(), DevModeEventType.MODULE_INIT,
                "Module Name", moduleName);
        ModuleHandle moduleHandle = host.createModuleLogger(moduleName, userAgent, url, tabKey, sessionKey, channel,
                userAgentIcon);
        TreeLogger logger = moduleHandle.getLogger();
        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, channel);
            moduleMap.put(channel, moduleSpace);
            moduleSpace.onLoad(logger);
            if (logger.isLoggable(TreeLogger.INFO)) {
                moduleHandle.getLogger().log(TreeLogger.INFO, "Module " + moduleName + " has been loaded");
            }
        } catch (Throwable e) {
            // We do catch Throwable intentionally because there are a ton of
            // things
            // that can go wrong trying to load a module, including
            // Error-derived
            // things like NoClassDefFoundError.
            //
            // moduleHandle.getLogger().log(
            // TreeLogger.ERROR,
            // "Failed to load module '" + moduleName + "' from user agent '"
            // + userAgent + "' at " + channel.getRemoteEndpoint(), e);
            moduleHandle.getLogger().log(TreeLogger.INFO, "Failed to load module '" + moduleName
                    + "' from user agent '" + userAgent + "' at " + channel.getRemoteEndpoint());
            moduleHandle.getLogger().log(TreeLogger.INFO, " --> exception: " + e.getMessage());
            // handle gwt dev plugin issue
            e.printStackTrace();
            if (moduleSpace != null) {
                moduleSpace.dispose();
            }
            moduleHandle.unload();
            moduleMap.remove(channel);
            moduleHandleMap.remove(channel);
            return null;
        } finally {
            moduleInit.end();
        }
        return moduleHandle.getLogger();
    }

    @Override
    public ExceptionOrReturnValue setProperty(BrowserChannelServer channel, int refId, int dispId, Value newValue) {
        ModuleSpace moduleSpace = moduleMap.get(channel);
        ModuleHandle moduleHandle = moduleHandleMap.get(channel);
        assert moduleSpace != null && moduleHandle != null;
        TreeLogger logger = moduleHandle.getLogger();
        ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
        try {
            JsValueOOPHM obj = new JsValueOOPHM();
            DispatchObject dispObj;
            obj.setWrappedJavaObject(moduleSpace.getIsolatedClassLoader(), localObjects.get(refId));
            dispObj = obj.getJavaObjectWrapper();
            if (logger.isLoggable(TreeLogger.SPAM)) {
                logger.log(TreeLogger.SPAM, "Client special invoke of setProperty(id=" + dispId + ", newValue="
                        + newValue + ") on " + obj.toString(), null);
            }
            JsValueOOPHM jsval = new JsValueOOPHM();
            channel.convertToJsValue(moduleSpace.getIsolatedClassLoader(), localObjects, newValue, jsval);
            dispObj.setField(dispId, jsval);
            return new ExceptionOrReturnValue(false, newValue);
        } catch (Throwable t) {
            JsValueOOPHM jsval = new JsValueOOPHM();
            JsValueGlue.set(jsval, moduleSpace.getIsolatedClassLoader(), t.getClass(), t);
            Value retVal = channel.convertFromJsValue(localObjects, jsval);
            return new ExceptionOrReturnValue(true, retVal);
        }
    }

    @Override
    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);
            return;
        }
        moduleHandle.getLogger().log(TreeLogger.INFO,
                "Unloading module " + moduleSpace.getModuleName() + " (" + moduleName + ")", null);
        moduleSpace.dispose();
        moduleHandle.unload();
        moduleMap.remove(channel);
        moduleHandleMap.remove(channel);
    }
}