Package com.google.gwt.dev

Source Code of com.google.gwt.dev.Link

/*
* 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;

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.linker.SelectionProperty;
import com.google.gwt.core.ext.linker.impl.StandardCompilationResult;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
import com.google.gwt.dev.CompileTaskRunner.CompileTask;
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.StaticPropertyOracle;
import com.google.gwt.dev.jjs.JJSOptions;
import com.google.gwt.dev.jjs.PermutationResult;
import com.google.gwt.dev.jjs.impl.CodeSplitter;
import com.google.gwt.dev.util.FileBackedObject;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerExtraDir;
import com.google.gwt.dev.util.arg.ArgHandlerWarDir;
import com.google.gwt.dev.util.arg.OptionExtraDir;
import com.google.gwt.dev.util.arg.OptionOutDir;
import com.google.gwt.dev.util.arg.OptionWarDir;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Performs the last phase of compilation, merging the compilation outputs.
*/
public class Link {
  /**
   * Options for Link.
   */
  @Deprecated
  public interface LegacyLinkOptions extends CompileTaskOptions, OptionOutDir {
  }

  /**
   * Options for Link.
   */
  public interface LinkOptions extends CompileTaskOptions, OptionExtraDir,
      OptionWarDir, LegacyLinkOptions {
  }

  static class ArgProcessor extends CompileArgProcessor {
    @SuppressWarnings("deprecation")
    public ArgProcessor(LinkOptions options) {
      super(options);
      registerHandler(new ArgHandlerExtraDir(options));
      registerHandler(new ArgHandlerWarDir(options));
      registerHandler(new ArgHandlerOutDirDeprecated(options));
    }

    @Override
    protected String getName() {
      return Link.class.getName();
    }
  }

  /**
   * Concrete class to implement link options.
   */
  static class LinkOptionsImpl extends CompileTaskOptionsImpl implements
      LinkOptions {

    private File extraDir;
    private File warDir;
    private File outDir;

    public LinkOptionsImpl() {
    }

    public LinkOptionsImpl(LinkOptions other) {
      copyFrom(other);
    }

    public void copyFrom(LinkOptions other) {
      super.copyFrom(other);
      setExtraDir(other.getExtraDir());
      setWarDir(other.getWarDir());
      setOutDir(other.getOutDir());
    }

    public File getExtraDir() {
      return extraDir;
    }

    @Deprecated
    public File getOutDir() {
      return outDir;
    }

    public File getWarDir() {
      return warDir;
    }

    public void setExtraDir(File extraDir) {
      this.extraDir = extraDir;
    }

    @Deprecated
    public void setOutDir(File outDir) {
      this.outDir = outDir;
    }

    public void setWarDir(File warDir) {
      this.warDir = warDir;
    }
  }

  public static void legacyLink(TreeLogger logger, ModuleDef module,
      ArtifactSet generatedArtifacts, Permutation[] permutations,
      List<FileBackedObject<PermutationResult>> resultFiles, File outDir,
      JJSOptions precompileOptions) throws UnableToCompleteException {
    StandardLinkerContext linkerContext = new StandardLinkerContext(logger,
        module, precompileOptions);
    ArtifactSet artifacts = doLink(logger, linkerContext, generatedArtifacts,
        permutations, resultFiles);
    doProduceLegacyOutput(logger, artifacts, linkerContext, module, outDir);
  }

  public static void link(TreeLogger logger, ModuleDef module,
      ArtifactSet generatedArtifacts, Permutation[] permutations,
      List<FileBackedObject<PermutationResult>> resultFiles, File outDir,
      File extrasDir, JJSOptions precompileOptions)
      throws UnableToCompleteException {
    StandardLinkerContext linkerContext = new StandardLinkerContext(logger,
        module, precompileOptions);
    ArtifactSet artifacts = doLink(logger, linkerContext, generatedArtifacts,
        permutations, resultFiles);
    doProduceOutput(logger, artifacts, linkerContext, module, outDir, extrasDir);
  }

  public static void main(String[] args) {
    /*
     * NOTE: main always exits with a call to System.exit to terminate any
     * non-daemon threads that were started in Generators. Typically, this is to
     * shutdown AWT related threads, since the contract for their termination is
     * still implementation-dependent.
     */
    final LinkOptions options = new LinkOptionsImpl();

    if (new ArgProcessor(options).processArgs(args)) {
      CompileTask task = new CompileTask() {
        public boolean run(TreeLogger logger) throws UnableToCompleteException {
          return new Link(options).run(logger);
        }
      };
      if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
        // Exit w/ success code.
        System.exit(0);
      }
    }
    // Exit w/ non-success code.
    System.exit(1);
  }

  private static ArtifactSet doLink(TreeLogger logger,
      StandardLinkerContext linkerContext, ArtifactSet generatedArtifacts,
      Permutation[] perms, List<FileBackedObject<PermutationResult>> resultFiles)
      throws UnableToCompleteException {
    if (perms.length != resultFiles.size()) {
      throw new IllegalArgumentException(
          "Mismatched resultFiles.length and permutation count");
    }

    for (int i = 0; i < perms.length; ++i) {
      finishPermuation(logger, perms[i], resultFiles.get(i), linkerContext);
    }

    linkerContext.addOrReplaceArtifacts(generatedArtifacts);
    return linkerContext.invokeLink(logger);
  }

  private static void doProduceLegacyOutput(TreeLogger logger,
      ArtifactSet artifacts, StandardLinkerContext linkerContext,
      ModuleDef module, File outDir) throws UnableToCompleteException {
    File moduleOutDir = new File(outDir, module.getName());
    File moduleExtraDir = new File(outDir, module.getName() + "-aux");
    Util.recursiveDelete(moduleOutDir, true);
    Util.recursiveDelete(moduleExtraDir, true);
    linkerContext.produceOutputDirectory(logger, artifacts, moduleOutDir);
    linkerContext.produceExtraDirectory(logger, artifacts, moduleExtraDir);
    logger.log(TreeLogger.INFO, "Link succeeded");
  }

  private static void doProduceOutput(TreeLogger logger, ArtifactSet artifacts,
      StandardLinkerContext linkerContext, ModuleDef module, File outDir,
      File extraDir) throws UnableToCompleteException {
    String outPath = outDir.getPath();
    if (!outDir.isDirectory()
        && (outPath.endsWith(".war") || outPath.endsWith(".jar") || outPath.endsWith(".zip"))) {
      linkerContext.produceOutputZip(logger, artifacts, outDir,
          module.getName() + '/');
    } else {
      File moduleOutDir = new File(outDir, module.getName());
      Util.recursiveDelete(moduleOutDir, true);
      linkerContext.produceOutputDirectory(logger, artifacts, moduleOutDir);
    }

    if (extraDir != null) {
      String extraPath = extraDir.getPath();
      if (!extraDir.isDirectory()
          && (extraPath.endsWith(".war") || extraPath.endsWith(".jar") || extraPath.endsWith(".zip"))) {
        linkerContext.produceExtraZip(logger, artifacts, extraDir,
            module.getName() + '/');
      } else {
        File moduleExtraDir = new File(extraDir, module.getName());
        Util.recursiveDelete(moduleExtraDir, true);
        linkerContext.produceExtraDirectory(logger, artifacts, moduleExtraDir);
      }
    }
    logger.log(TreeLogger.INFO, "Link succeeded");
  }

  private static void finishPermuation(TreeLogger logger, Permutation perm,
      FileBackedObject<PermutationResult> resultFile,
      StandardLinkerContext linkerContext) throws UnableToCompleteException {
    StandardCompilationResult compilation = linkerContext.getCompilation(
        logger, resultFile);
    StaticPropertyOracle[] propOracles = perm.getPropertyOracles();
    for (StaticPropertyOracle propOracle : propOracles) {
      BindingProperty[] orderedProps = propOracle.getOrderedProps();
      String[] orderedPropValues = propOracle.getOrderedPropValues();
      Map<SelectionProperty, String> unboundProperties = new HashMap<SelectionProperty, String>();
      for (int i = 0; i < orderedProps.length; i++) {
        SelectionProperty key = linkerContext.getProperty(orderedProps[i].getName());
        if (key.tryGetValue() != null) {
          /*
           * The view of the Permutation doesn't include properties with defined
           * values.
           */
          continue;
        } else if (key.isDerived()) {
          /*
           * The property provider does not need to be invoked, because the
           * value is determined entirely by other properties.
           */
          continue;
        }
        unboundProperties.put(key, orderedPropValues[i]);
      }
      compilation.addSelectionPermutation(unboundProperties);
    }
    logScriptSize(logger, perm.getId(), compilation);
  }

  /**
   * Logs the total script size for this permutation, as calculated by
   * {@link CodeSplitter#totalScriptSize(int[])}.
   */
  private static void logScriptSize(TreeLogger logger, int permId,
      StandardCompilationResult compilation) {
    if (!logger.isLoggable(TreeLogger.TRACE)) {
      return;
    }

    String[] javaScript = compilation.getJavaScript();

    int[] jsLengths = new int[javaScript.length];
    for (int i = 0; i < javaScript.length; i++) {
      jsLengths[i] = javaScript[i].length();
    }

    int totalSize = CodeSplitter.totalScriptSize(jsLengths);

    logger.log(TreeLogger.TRACE, "Permutation " + permId + " (strong name "
        + compilation.getStrongName() + ") has an initial download size of "
        + javaScript[0].length() + " and total script size of " + totalSize);
  }

  private final LinkOptionsImpl options;

  public Link(LinkOptions options) {
    this.options = new LinkOptionsImpl(options);
  }

  public boolean run(TreeLogger logger) throws UnableToCompleteException {
    for (String moduleName : options.getModuleNames()) {
      File compilerWorkDir = options.getCompilerWorkDir(moduleName);
      Collection<PrecompilationFile> precomps;
      try {
        precomps = PrecompilationFile.scanJarFile(new File(compilerWorkDir,
            Precompile.PRECOMPILE_FILENAME));
      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Failed to scan "
            + Precompile.PRECOMPILE_FILENAME, e);
        return false;
      }

      ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, moduleName);

      if (precomps.isEmpty()) {
        logger.log(TreeLogger.ERROR, "No precompilation files found in '"
            + compilerWorkDir.getAbsolutePath()
            + "'; please run Precompile first");
        return false;
      }

      List<Permutation> permsList = new ArrayList<Permutation>();
      ArtifactSet generatedArtifacts = new ArtifactSet();
      JJSOptions precompileOptions = null;

      for (PrecompilationFile precompilationFile : precomps) {
        Precompilation precompilation;
        try {
          precompilation = precompilationFile.newInstance(logger);
        } catch (UnableToCompleteException e) {
          return false;
        }
        permsList.addAll(Arrays.asList(precompilation.getPermutations()));
        generatedArtifacts.addAll(precompilation.getGeneratedArtifacts());
        precompileOptions = precompilation.getUnifiedAst().getOptions();
      }

      Permutation[] perms = permsList.toArray(new Permutation[permsList.size()]);

      List<FileBackedObject<PermutationResult>> resultFiles = new ArrayList<FileBackedObject<PermutationResult>>(
          perms.length);
      for (int i = 0; i < perms.length; ++i) {
        File f = CompilePerms.makePermFilename(compilerWorkDir,
            perms[i].getId());
        if (!f.exists()) {
          logger.log(TreeLogger.ERROR, "File not found '" + f.getAbsolutePath()
              + "'; please compile all permutations");
          return false;
        }
        resultFiles.add(new FileBackedObject<PermutationResult>(
            PermutationResult.class, f));
      }

      TreeLogger branch = logger.branch(TreeLogger.INFO, "Linking module "
          + module.getName());
      StandardLinkerContext linkerContext = new StandardLinkerContext(branch,
          module, precompileOptions);

      ArtifactSet artifacts = doLink(branch, linkerContext, generatedArtifacts,
          perms, resultFiles);

      if (options.getOutDir() == null) {
        doProduceOutput(branch, artifacts, linkerContext, module,
            options.getWarDir(), options.getExtraDir());
      } else {
        doProduceLegacyOutput(branch, artifacts, linkerContext, module,
            options.getOutDir());
      }
    }
    return true;
  }
}
TOP

Related Classes of com.google.gwt.dev.Link

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.