Package com.google.gdt.eclipse.designer.hosted.tdz

Source Code of com.google.gdt.eclipse.designer.hosted.tdz.HostedModeSupport

/*******************************************************************************
* Copyright 2011 Google Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* 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.gdt.eclipse.designer.hosted.tdz;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.List;
import java.util.Map;



import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.swt.widgets.Display;
import org.osgi.framework.Bundle;

import com.google.gdt.eclipse.designer.hosted.HostedModeException;
import com.google.gdt.eclipse.designer.hosted.IBrowserShell;
import com.google.gdt.eclipse.designer.hosted.IBrowserShellFactory;
import com.google.gdt.eclipse.designer.hosted.IHostedModeSupport;
import com.google.gdt.eclipse.designer.hosted.ILogSupport;
import com.google.gdt.eclipse.designer.hosted.IModuleDescription;
import com.google.gdt.eclipse.designer.hosted.classloader.GWTSharedClassLoader;
import com.google.gdt.eclipse.designer.hosted.tdz.log.LogSupport;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.cfg.BindingProperty;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.cfg.Properties;
import com.google.gwt.dev.cfg.Property;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.shell.ArtifactAcceptor;
import com.google.gwt.dev.shell.CompilingClassLoader;
import com.google.gwt.dev.shell.ModuleSpace;
import com.google.gwt.dev.shell.ModuleSpaceHost;
import com.google.gwt.dev.shell.ShellModuleSpaceHost;

import org.eclipse.wb.core.utils.external.ExternalFactoriesHelper;
import org.eclipse.wb.internal.core.utils.IOUtils2;
import org.eclipse.wb.internal.core.utils.reflect.ProjectClassLoader;


/**
* Implementation for {@link IHostedModeSupport} for GWT 2.0. Also used as {@link IBrowserShellHost} while
* creating {@link ModuleSpace} for current platform.
*
* @author mitin_aa
*/
public final class HostedModeSupport implements IHostedModeSupport, IBrowserShellHost {
  private static GWTSharedClassLoader m_gwtSharedClassLoader;
  private final ClassLoader m_parentClassLoader;
  private final IModuleDescription m_moduleDescription;
  private final BrowserShell m_browserShell;
  private final IJavaProject m_javaProject;
  private ProjectClassLoader m_devClassLoader;
  private ShellModuleSpaceHost m_moduleSpaceHost;
  private File m_shellDirectory;
  private final LogSupport m_logSupport;
  private ModuleDef m_moduleDef;
  private TypeOracle m_typeOracle;
  ////////////////////////////////////////////////////////////////////////////
  //
  // Constructor
  //
  ////////////////////////////////////////////////////////////////////////////
  public HostedModeSupport(ClassLoader parentClassLoader, IModuleDescription moduleDescription) throws Exception {
    m_parentClassLoader = parentClassLoader;
    m_moduleDescription = moduleDescription;
    m_javaProject = moduleDescription.getJavaProject();
    // Logger
    m_logSupport = new LogSupport(TreeLogger.TRACE, m_javaProject);
    // Class loaders
    createClassLoaders();
    // Browser shell
    m_browserShell = (BrowserShell) createBrowserShell();
    m_browserShell.setHost(this);
  }
  ////////////////////////////////////////////////////////////////////////////
  //
  // ClassLoaders
  //
  ////////////////////////////////////////////////////////////////////////////
  /**
   * Creates the special {@link ClassLoader}'s to work with GWT "dev" classes and "user" classes.
   */
  private void createClassLoaders() throws Exception {
    m_devClassLoader = ProjectClassLoader.create(getSharedClassLoader(), m_javaProject);
    {
      Bundle bundle = Platform.getBundle("com.google.gdt.eclipse.designer.hosted.2_0.super");
      URL rootEntry = bundle.getEntry("");
      rootEntry = FileLocator.toFileURL(rootEntry);
      m_devClassLoader.addURL(rootEntry);
    }
  }
  ////////////////////////////////////////////////////////////////////////////
  //
  // IHostedModeSupport
  //
  ////////////////////////////////////////////////////////////////////////////
  public void startup(String browserStartupUrl, String moduleName, IProgressMonitor monitor, int timeout)
      throws Exception {
    CompilingClassLoader.parentClassLoader = m_parentClassLoader;
    try {
      //long l = System.currentTimeMillis();
      m_browserShell.setUrl(browserStartupUrl, moduleName, timeout, new Runnable() {
        public void run() {
          runMessagesLoop();
        }
      });
      //System.out.println("\tstartup time: " + (System.currentTimeMillis() - l));
    } finally {
      CompilingClassLoader.parentClassLoader = null;
    }
  }
  public void dispose() {
    m_browserShell.dispose();
    // dispose if initialized (may be not if Module loading failed)
    if (m_moduleSpaceHost != null) {
      m_moduleSpaceHost.getModuleSpace().dispose();
    }
    // dispose for project; if the same project used in another editor
    // it would be added again by activating the project.
    m_gwtSharedClassLoader.dispose(m_moduleDescription);
    m_logSupport.dispose();
    m_moduleSpaceHost = null;
    // clear static caches
    try {
      Class<?> clazz = m_gwtSharedClassLoader.loadClass("com.google.gwt.i18n.rebind.ClearStaticData");
      Method method = clazz.getDeclaredMethod("clear");
      method.setAccessible(true);
      method.invoke(null);
    } catch (Throwable e) {
    }
    try {
      Class<?> clazz =
          m_gwtSharedClassLoader.loadClass("com.google.gwt.uibinder.rebind.model.OwnerFieldClass");
      Field mapField = clazz.getDeclaredField("FIELD_CLASSES");
      mapField.setAccessible(true);
      Map<?, ?> map = (Map<?, ?>) mapField.get(null);
      map.clear();
    } catch (Throwable e) {
    }
  }
  public IBrowserShell getBrowserShell() {
    return m_browserShell;
  }
  public ClassLoader getClassLoader() {
    return m_moduleSpaceHost.getClassLoader();
  }
  public ClassLoader getDevClassLoader() {
    return m_devClassLoader;
  }
  public Object findJType(String name) {
    return m_typeOracle.findType(name);
  }
  private ClassLoader getSharedClassLoader() throws Exception {
    // shared class loader for gwt-user.jar
    if (m_gwtSharedClassLoader == null) {
      m_gwtSharedClassLoader = new GWTSharedClassLoader(ModuleDef.class.getClassLoader(), new URL[]{});
    }
    activate();
    return m_gwtSharedClassLoader;
  }
  public void invalidateRebind(String typeName) {
  }
  public void activate() throws Exception {
    m_gwtSharedClassLoader.setActiveProject(m_moduleDescription);
    ModuleSpace.setLogger(getLogger());
  }
  public byte[] getGeneratedResource(String resourceName) throws Exception {
    File resourceFile = new File(m_shellDirectory, resourceName);
    if (!resourceFile.exists()) {
      return null;
    }
    return IOUtils2.readBytes(resourceFile);
  }
  public ILogSupport getLogSupport() {
    return m_logSupport;
  }
  ////////////////////////////////////////////////////////////////////////////
  //
  // BrowserShell
  //
  ////////////////////////////////////////////////////////////////////////////
  /**
   * Creates and returns the {@link IBrowserShell} instance for current platform using external factory.
   */
  @SuppressWarnings("unchecked")
  private IBrowserShell createBrowserShell() throws Exception {
    List<IBrowserShellFactory> factories =
        ExternalFactoriesHelper.getElementsInstances(
          IBrowserShellFactory.class,
          "com.google.gdt.eclipse.designer.hosted.2_0.browserShellFactory",
          "factory");
    for (IBrowserShellFactory factory : factories) {
      IBrowserShell shell = factory.create();
      if (shell != null) {
        return shell;
      }
    }
    // no shell has been created by factories
    if (isWindows64()) {
      // special message for windows
      throw new HostedModeException(HostedModeException.WIN32_NO_WINDOWS_64);
    }
    throw new HostedModeException(HostedModeException.UNSUPPORTED_OS);
  }
  /**
   * @return <code>true</code> while running Windows 64-bit.
   */
  private boolean isWindows64() {
    String osName = System.getProperty("os.name");
    String archName = System.getProperty("os.arch");
    if (!StringUtils.isEmpty(osName) && !StringUtils.isEmpty(archName)) {
      return osName.startsWith("Windows") && archName.indexOf("64") != -1;
    }
    return false;
  }
  /**
   * Forces an outstanding messages to be processed
   */
  public void runMessagesLoop() {
    try {
      while (Display.getCurrent().readAndDispatch()) {
        // wait
      }
    } catch (Throwable e) {
    }
  }
  ////////////////////////////////////////////////////////////////////////////
  //
  // IBrowserShellHost
  //
  ////////////////////////////////////////////////////////////////////////////
  //private final Set<String> alreadySeenModules = new HashSet<String>();
  /**
   * Load a module.
   *
   * @param moduleName
   *            a Name of the module to load.
   * @param outDir
   * @return the loaded module.
   */
  private ModuleDef loadModule(String moduleName) throws Exception {
    //boolean assumeFresh = !alreadySeenModules.contains(moduleName);
    ModuleDef moduleDef =
        ModuleDefLoader.loadFromClassPath(getLogger(), moduleName, true/*!assumeFresh*/);
    //alreadySeenModules.add(moduleName);
    assert moduleDef != null : "Required module state is absent";
    return moduleDef;
  }
  public ModuleSpaceHost createModuleSpaceHost(final String moduleName) throws Exception {
    ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(m_devClassLoader);
    try {
      // Try to find an existing loaded version of the module def.
      //
      String outDir = getTemporaryDirectoryName(m_javaProject);
      m_moduleDef = loadModule(moduleName);
      assert m_moduleDef != null;
      fixUserAgentProperty(m_moduleDef);
      // TODO uncomment, if want to see/debug generators, like UiBinder
      //File genDir = new File(outDir);
      File genDir = null;
      // Create a sandbox for the module.
      m_shellDirectory =
          new File(outDir, ".tmp" + File.separator + "shell" + File.separator + moduleName);
      CompilationState compilationState = m_moduleDef.getCompilationState(getLogger());
      m_typeOracle = compilationState.getTypeOracle();
      m_moduleSpaceHost =
          new ShellModuleSpaceHost(getLogger(),
            compilationState,
            m_moduleDef,
            genDir,
            m_shellDirectory,
            new ArtifactAcceptor() {
              public void accept(TreeLogger logger, ArtifactSet newlyGeneratedArtifacts)
                  throws UnableToCompleteException {
                // TODO: does we need this?
              }
            });
      return m_moduleSpaceHost;
    } finally {
      Thread.currentThread().setContextClassLoader(oldContextClassLoader);
    }
  }
  /**
   * Forcibly set 'user.agent' property to current platform.
   * http://fogbugz.instantiations.com/fogbugz/default.php?41513
   */
  private void fixUserAgentProperty(ModuleDef module) {
    Properties properties = module.getProperties();
    for (Property property : properties) {
      if ("user.agent".equals(property.getName())) {
        BindingProperty bindingProperty = (BindingProperty) property;
        bindingProperty.setAllowedValues(
          bindingProperty.getRootCondition(),
          m_browserShell.getUserAgentString());
        return;
      }
    }
  }
  public TreeLogger getLogger() {
    return (TreeLogger) m_logSupport.getLogger();
  }
  ////////////////////////////////////////////////////////////////////////////
  //
  // Utils
  //
  ////////////////////////////////////////////////////////////////////////////
  public static String getTemporaryDirectoryName(IJavaProject javaProject) {
    String logDir = javaProject.getProject().getLocation().toOSString() + File.separator + ".gwt";
    File logDirFile = new File(logDir);
    logDirFile.mkdirs();
    return logDir;
  }
  ////////////////////////////////////////////////////////////////////////////
  //
  // IHostedModeSupport, invocations of native code.
  //
  ////////////////////////////////////////////////////////////////////////////
  @SuppressWarnings("rawtypes")
  public boolean invokeNativeBoolean(String string, Class[] classes, Object[] objects) {
    try {
      return m_moduleSpaceHost.getModuleSpace().invokeNativeBoolean(string, null, classes, objects);
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
  }
  @SuppressWarnings("rawtypes")
  public String invokeNativeString(String string, Class[] classes, Object[] objects) {
    try {
      return (String) m_moduleSpaceHost.getModuleSpace().invokeNativeObject(
        string,
        null,
        classes,
        objects);
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
  }
  @SuppressWarnings("rawtypes")
  public void invokeNativeVoid(String string, Class[] classes, Object[] objects) {
    try {
      m_moduleSpaceHost.getModuleSpace().invokeNativeVoid(string, null, classes, objects);
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
  }
}
TOP

Related Classes of com.google.gdt.eclipse.designer.hosted.tdz.HostedModeSupport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.