All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.dev.codeserver.ModuleState Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * Copyright 2011 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.codeserver;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.json.JsonArray;
import com.google.gwt.dev.json.JsonObject;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Contains everything that the code server knows about a GWT app (module), including how
 * to recompile it and where the compiler output is.
 */
class ModuleState {
  private final AtomicReference current = new AtomicReference();
  private final Recompiler recompiler;
  private final TreeLogger logger;

  ModuleState(Recompiler recompiler, TreeLogger logger, boolean noPrecompile)
      throws UnableToCompleteException {
    this.recompiler = recompiler;
    this.logger = logger;

    CompileDir compileDir;
    if (noPrecompile) {
      compileDir = recompiler.noCompile();
    } else {
      Map defaultProps = new HashMap();
      defaultProps.put("user.agent", "safari");
      defaultProps.put("locale", "en");
      defaultProps.put("compiler.useSourceMaps", "true");
      compileDir = recompiler.compile(defaultProps);
    }
    current.set(compileDir);
  }

  /**
   * Recompiles the module with the given binding properties. If successful, this changes the
   * location of the output directory. (The log file changes both on success and on failure.
   *
   * @param bindingProperties The properties used to compile. (Chooses the permutation.)
   * @return true if the compile finished successfully.
   */
  boolean recompile(Map bindingProperties) {
    try {
      current.set(recompiler.compile(bindingProperties));
      return true;
    } catch (UnableToCompleteException e) {
      logger.log(TreeLogger.Type.WARN, "continuing to serve previous version");
      return false;
    }
  }

  /**
   * Returns the name of this module (after renaming).
   */
  String getModuleName() {
    return recompiler.getModuleName();
  }

  /**
   * Returns the source map file from the most recent recompile.
   * @throws RuntimeException if unable
   */
  File findSourceMap() {
    String moduleName = recompiler.getModuleName();
    File symbolMapsDir = current.get().findSymbolMapDir(moduleName);
    if (symbolMapsDir == null) {
      throw new RuntimeException("Can't find symbolMaps dir for " + moduleName);
    }

    File[] sourceMapFiles = symbolMapsDir.listFiles(new FilenameFilter() {
      @Override
      public boolean accept(File dir, String name) {
        return name.matches(".*_sourceMap0.json");
      }
    });

    if (sourceMapFiles == null) {
      throw new RuntimeException("Can't list contents of symbolMaps dir: " + symbolMapsDir);
    }

    if (sourceMapFiles.length > 1) {
      throw new RuntimeException("Multiple fragment 0 sourcemaps found. Too many permutations.");
    }

    if (sourceMapFiles.length == 0) {
      throw new RuntimeException("No sourcemaps found. Not enabled?");
    }

    return new File(symbolMapsDir, sourceMapFiles[0].getName());
  }

  /**
   * Finds a source file (or other resource) that's either in this module's source path, or
   * is a generated file.
   * @param path location of the file relative to its directory in the classpath, or (if
   *   it starts with "gen/"), a generated file.
   * @return bytes in the file, or null if there's no such source file.
   */
  InputStream openSourceFile(String path) throws IOException {

    if (path.startsWith("gen/")) {
      // generated file?
      String rest = path.substring("gen/".length());
      File fileInGenDir = new File(getGenDir(), rest);
      if (!fileInGenDir.isFile()) {
        return null;
      }
      return new BufferedInputStream(new FileInputStream(fileInGenDir));
    } else {
      // regular source file?
      URL resource = recompiler.getResourceLoader().getResource(path);
      if (resource == null) {
        return null;
      }
      return resource.openStream();
    }
  }

  /**
   * Returns the location of a file in the compiler's output directory from the
   * last time this module was recompiled. The location will change after a successful
   * recompile.
   * @param urlPath The path to the file. This should be a relative path beginning
   * with the module name (after renaming).
   * @return The location of the file, which might not actually exist.
   */
  File getOutputFile(String urlPath) {
    return new File(current.get().getWarDir(), urlPath);
  }

  /**
   * Returns the log file from the last time this module was recompiled. This changes
   * after every call to {@link #recompile}.
   */
  File getCompileLog() {
    return recompiler.getLastLog();
  }

  File getGenDir() {
    return current.get().getGenDir();
  }

  File getWarDir() {
    return current.get().getWarDir();
  }

  /**
   * Returns a file out of the "extras" directory.
   * @param path relative path of the file, not including the module name.
   * @return The location of the file, which might not actually exist.
   */
  File getExtraFile(String path) {
    File prefix = new File(current.get().getExtraDir(), getModuleName());
    return new File(prefix, path);
  }

  JsonObject getTemplateVariables() {
    JsonObject result = new JsonObject();
    result.put("moduleName", getModuleName());
    result.put("files", listModuleFiles());
    return result;
  }

  private JsonArray listModuleFiles() {
    File[] files = new File(getWarDir(), getModuleName()).listFiles();
    if (files == null) {
      return new JsonArray();
    }
    Arrays.sort(files);

    JsonArray result = new JsonArray();
    for (File file : files) {
      if (file.isFile()) {
        JsonObject map = new JsonObject();
        map.put("name", file.getName());
        map.put("link", file.getName());
        result.add(map);
      }
    }
    return result;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy