Package com.google.gwt.dev.shell

Source Code of com.google.gwt.dev.shell.StandardRebindOracle$Rebinder

/*
* Copyright 2007 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 com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.cfg.Rule;
import com.google.gwt.dev.cfg.Rules;
import com.google.gwt.dev.cfg.StaticPropertyOracle;
import com.google.gwt.dev.jdt.CacheManager;
import com.google.gwt.dev.jdt.RebindOracle;
import com.google.gwt.dev.util.Util;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
* Implements rebind logic in terms of a variety of other well-known oracles.
*/
public class StandardRebindOracle implements RebindOracle {

  /**
   * Makes the actual deferred binding decision by examining rules.
   */
  private final class Rebinder {

    private final StandardGeneratorContext genCtx;

    private final Set usedRules = new HashSet();

    private final List usedTypeNames = new ArrayList();

    public Rebinder(TypeOracle typeOracle, PropertyOracle propOracle) {
      genCtx = new StandardGeneratorContext(typeOracle, propOracle, genDir,
          outDir, cacheManager);
    }

    public String rebind(TreeLogger logger, String typeName)
        throws UnableToCompleteException {

      String result = tryRebind(logger, typeName);
      if (result == null) {
        result = typeName;
      }

      // Announce the newly-generated types.
      //
      JClassType[] genTypes = genCtx.finish(logger);
      if (genTypes.length > 0) {
        onGeneratedTypes(result, genTypes);
      }

      return result;
    }

    private String tryRebind(TreeLogger logger, String typeName)
        throws UnableToCompleteException {
      if (usedTypeNames.contains(typeName)) {
        // Found a cycle.
        //
        String[] cycle = (String[]) Util.toArray(String.class, usedTypeNames);
        Messages.UNABLE_TO_REBIND_DUE_TO_CYCLE_IN_RULES.log(logger, cycle, null);
        throw new UnableToCompleteException();
      }

      // Remember that we've seen this one.
      //
      usedTypeNames.add(typeName);

      // Make the rebind decision.
      //
      if (rules.isEmpty()) {
        logger.log(TreeLogger.DEBUG,
            "No rules are defined, so no substitution can occur", null);
        return null;
      }

      for (Iterator iter = rules.iterator(); iter.hasNext();) {
        Rule rule = (Rule) iter.next();

        // Branch the logger.
        //
        TreeLogger branch = Messages.TRACE_CHECKING_RULE.branch(logger, rule,
            null);

        if (rule.isApplicable(branch, genCtx, typeName)) {
          // See if this rule has already been used. This is needed to prevent
          // infinite loops with 'when-assignable' conditions.
          //
          if (!usedRules.contains(rule)) {
            usedRules.add(rule);
            Messages.TRACE_RULE_MATCHED.log(logger, null);

            // Invoke the rule.
            //
            return rule.realize(logger, genCtx, typeName);

          } else {
            // We are skipping this rule because it has already been used
            // in a previous iteration.
            //
          }
        } else {
          Messages.TRACE_RULE_DID_NOT_MATCH.log(logger, null);
        }
      }

      // No matching rule for this type.
      //
      return null;
    }
  }

  private final CacheManager cacheManager;

  private final File genDir;

  private final File outDir;

  private final PropertyOracle propOracle;

  private final Rules rules;

  private final TypeOracle typeOracle;

  public StandardRebindOracle(TypeOracle typeOracle, PropertyOracle propOracle,
      Rules rules, File genDir, File moduleOutDir, CacheManager cacheManager) {
    this.typeOracle = typeOracle;
    this.propOracle = propOracle;
    this.rules = rules;
    this.genDir = genDir;
    this.outDir = moduleOutDir;
    if (cacheManager != null) {
      this.cacheManager = cacheManager;
    } else {
      this.cacheManager = new CacheManager(typeOracle);
    }
  }

  public StandardRebindOracle(TypeOracle typeOracle,
      StaticPropertyOracle propOracle, Rules rules, File genDir,
      File moduleOutDir) {
    // This is a path used for non-hosted mode execution; therefore no caching.
    this(typeOracle, propOracle, rules, genDir, moduleOutDir, null);
  }

  public String rebind(TreeLogger logger, String typeName)
      throws UnableToCompleteException {

    logger = Messages.TRACE_TOPLEVEL_REBIND.branch(logger, typeName, null);

    Rebinder rebinder = new Rebinder(typeOracle, propOracle);
    String result = rebinder.rebind(logger, typeName);

    Messages.TRACE_TOPLEVEL_REBIND_RESULT.log(logger, result, null);

    return result;
  }

  protected void onGeneratedTypes(String result, JClassType[] genTypes) {
  }

}
TOP

Related Classes of com.google.gwt.dev.shell.StandardRebindOracle$Rebinder

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.