Package com.google.gwt.dev.resource.impl

Source Code of com.google.gwt.dev.resource.impl.PathPrefix

/*
* 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.resource.impl;

import com.google.gwt.thirdparty.org.apache.tools.ant.types.ZipScanner;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* Represents the abstract path prefix that goes between the
* {@link ClassPathEntry} and the rest of resource's abstract path. This concept
* allows us to specify subsets of path hierarchies orthogonally from path
* roots. For example, a path root might be <code>/home/gwt/src/</code> and an
* abstract path prefix might be <code>module/client/</code>. Importantly,
* you can apply the same abstract path prefix to multiple path roots and find
* more than one set of resources residing in disjoint locations yet occupying
* the same logical hierarchy. Sorry this explanation is so abstract; it's how
* we model things like the GWT module's client source path, public path, and
* super source path.
*/
public final class PathPrefix {

  public static final PathPrefix ALL = new PathPrefix("", null);

  private final Set<String> exclusions;
  private ZipScanner exclusionScanner;
  private final List<ResourceFilter> filters;
  private final String prefix;
  private int priority = -1;
  private final boolean shouldReroot;

  /**
   * Construct a non-rerooting prefix.
   *
   * @param prefix a string prefix that (1) is the empty string or (2) begins
   *          with something other than a slash and ends with a slash
   * @param filter the resource filter to use, or <code>null</code> for no
   *          filter; note that the filter must always return the same answer
   *          for the same candidate path (doing otherwise will produce
   *          inconsistent behavior in identifying available resources)
   */
  public PathPrefix(String prefix, ResourceFilter filter) {
    this(prefix, filter, false, null);
  }

  /**
   * Construct a prefix without global exclusions.
   *
   * @param prefix a string prefix that (1) is the empty string or (2) begins
   *          with something other than a slash and ends with a slash
   * @param filter the resource filter to use, or <code>null</code> for no
   *          filter; note that the filter must always return the same answer
   *          for the same candidate path (doing otherwise will produce
   *          inconsistent behavior in identifying available resources)
   * @param shouldReroot if <code>true</code>, any matching {@link Resource}
   *          for this prefix will be rerooted to not include the initial prefix
   *          path; if <code>false</code>, the prefix will be included in a
   *          matching resource's path.
   */
  public PathPrefix(String prefix, ResourceFilter filter, boolean shouldReroot) {
    this(prefix, filter, shouldReroot, null);
  }

  /**
   * Construct a prefix.
   *
   * @param prefix a string prefix that (1) is the empty string or (2) begins
   *          with something other than a slash and ends with a slash
   * @param filter the resource filter to use, or <code>null</code> for no
   *          filter; note that the filter must always return the same answer
   *          for the same candidate path (doing otherwise will produce
   *          inconsistent behavior in identifying available resources)
   * @param shouldReroot if <code>true</code>, any matching {@link Resource}
   *          for this prefix will be rerooted to not include the initial prefix
   *          path; if <code>false</code>, the prefix will be included in a
   *          matching resource's path.
   * @param excludeList list of globs that should be removed from <i>any</i>
   *          module's resources.
   */
  public PathPrefix(String prefix, ResourceFilter filter, boolean shouldReroot,
      String[] excludeList) {
    assertValidPrefix(prefix);
    this.prefix = prefix;
    this.filters = new ArrayList<ResourceFilter>(1);
    this.filters.add(filter);
    this.shouldReroot = shouldReroot;
    this.exclusions = new HashSet<String>();
    if (excludeList != null) {
      for (String exclude : excludeList) {
        exclusions.add(exclude);
      }
    }
  }

  /**
   * Determines whether or not a given path is allowed by this path prefix by
   * checking both the prefix string and the filter.
   *
   * @param path
   * @return
   */
  public boolean allows(String path) {
    if (!path.startsWith(prefix)) {
      return false;
    }
    if (filters.size() == 0 && exclusions.size() == 0) {
      return true;
    }
    if (shouldReroot) {
      path = getRerootedPath(path);
    }

    createExcludeFilter();
    if (exclusionScanner != null && exclusionScanner.match(path)) {
      return false;
    }
    for (ResourceFilter filter : filters) {
      if (filter == null || filter.allows(path)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Equality is based on prefixes representing the same string. Importantly,
   * the filter does not affect equality.
   */
  @Override
  public boolean equals(Object obj) {
    if (obj instanceof PathPrefix) {
      if (prefix.equals(((PathPrefix) obj).prefix)) {
        return true;
      }
    }
    return false;
  }

  /**
   * The prefix.
   *
   * @return the result is guaranteed to be non-<code>null</code>, and
   *         either be the empty string or it will not begin with a slash and
   *         will end with a slash; these guarantees are very useful when
   *         concatenating paths that incorporate prefixes
   */
  public String getPrefix() {
    return prefix;
  }

  public String getRerootedPath(String path) {
    assert (path.startsWith(prefix));
    if (shouldReroot) {
      return path.substring(prefix.length());
    } else {
      return path;
    }
  }

  @Override
  public int hashCode() {
    return prefix.hashCode();
  }

  /**
   * Consolidate a given {@code PathPrefix} with this one, such that resources
   * excluded by neither prefix and included by either are allowed.
   *
   * @param pathPrefix
   */
  public void merge(PathPrefix pathPrefix) {
    assert prefix.equals(pathPrefix.prefix);
    for (ResourceFilter filter : pathPrefix.filters) {
      filters.add(filter);
    }
    exclusions.addAll(pathPrefix.exclusions);
    if (exclusionScanner != null && !exclusions.isEmpty()) {
      exclusionScanner = null// lose the stale one; we'll recreate later
    }
  }

  public boolean shouldReroot() {
    return shouldReroot;
  }

  @Override
  public String toString() {
    return prefix + (shouldReroot ? "**" : "*") + (filters.size() == 0 ? "" : "?");
  }

  int getPriority() {
    return priority;
  }

  void setPriority(int priority) {
    assert (this.priority == -1);
    this.priority = priority;
  }

  private void assertValidPrefix(String prefix) {
    assert (prefix != null);
    assert ("".equals(prefix) || (!prefix.startsWith("/") && prefix.endsWith("/"))) : "malformed prefix";
  }

  private void createExcludeFilter() {
    if (exclusionScanner == null && !exclusions.isEmpty()) {
      exclusionScanner = new ZipScanner();
      exclusionScanner.setIncludes(exclusions.toArray(new String[exclusions.size()]));
      exclusionScanner.init();
      exclusions.clear();
    }
  }
}
TOP

Related Classes of com.google.gwt.dev.resource.impl.PathPrefix

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.