org.apache.tools.ant.taskdefs.MakeUrl

public class MakeUrl extends Task {

    /**
     * name of the property to set
     */
    private String property;

    /**
     * name of a file to turn into a URL
     */
    private File file;

    /**
     * separator char
     */
    private String separator = " ";

    /**
     * filesets of nested files to add to this url
     */
    private List filesets = new LinkedList();

    /**
     * paths to add
     */
    private List paths = new LinkedList();

    /**
     * validation flag
     */
    private boolean validate = true;

    /** Missing file */
    public static final String ERROR_MISSING_FILE = "A source file is missing :";
    /** No property defined */
    public static final String ERROR_NO_PROPERTY = "No property defined";
    /** No files defined */
    public static final String ERROR_NO_FILES = "No files defined";

    /**
     * set the name of a property to fill with the URL
     *
     * @param property the name of the property.
     */
    public void setProperty(String property) {
        this.property = property;
    }

    /**
     * the name of a file to be converted into a URL
     *
     * @param file the file to be converted.
     */
    public void setFile(File file) {
        this.file = file;
    }

    /**
     * a fileset of jar files to include in the URL, each
     * separated by the separator
     *
     * @param fileset the fileset to be added.
     */
    public void addFileSet(FileSet fileset) {
        filesets.add(fileset);
    }

    /**
     * set the separator for the multi-url option.
     *
     * @param separator the separator to use.
     */
    public void setSeparator(String separator) {
        this.separator = separator;
    }

    /**
     * set this flag to trigger validation that every named file exists.
     * Optional: default=true
     *
     * @param validate a boolean value.
     */
    public void setValidate(boolean validate) {
        this.validate = validate;
    }

    /**
     * add a path to the URL. All elements in the path
     * will be converted to individual URL entries
     *
     * @param path a path value.
     */
    public void addPath(Path path) {
        paths.add(path);
    }

    /**
     * convert the filesets to urls.
     *
     * @return null for no files
     */
    private String filesetsToURL() {
        if (filesets.isEmpty()) {
            return "";
        }
        int count = 0;
        StringBuffer urls = new StringBuffer();
        ListIterator list = filesets.listIterator();
        while (list.hasNext()) {
            FileSet set = (FileSet) list.next();
            DirectoryScanner scanner = set.getDirectoryScanner(getProject());
            String[] files = scanner.getIncludedFiles();
            for (int i = 0; i < files.length; i++) {
                File f = new File(scanner.getBasedir(), files[i]);
                validateFile(f);
                String asUrl = toURL(f);
                urls.append(asUrl);
                log(asUrl, Project.MSG_DEBUG);
                urls.append(separator);
                count++;
            }
        }
        return stripTrailingSeparator(urls, count);
    }

    /**
     * convert the string buffer to a string, potentially stripping
     * out any trailing separator
     *
     * @param urls  URL buffer
     * @param count number of URL entries
     * @return trimmed string, or empty string
     */
    private String stripTrailingSeparator(StringBuffer urls,
                                          int count) {
        if (count > 0) {
            urls.delete(urls.length() - separator.length(), urls.length());
            return new String(urls);
        } else {
            return "";
        }
    }

    /**
     * convert all paths to URLs
     *
     * @return the paths as a separated list of URLs
     */
    private String pathsToURL() {
        if (paths.isEmpty()) {
            return "";
        }
        int count = 0;
        StringBuffer urls = new StringBuffer();
        ListIterator list = paths.listIterator();
        while (list.hasNext()) {
            Path path = (Path) list.next();
            String[] elements = path.list();
            for (int i = 0; i < elements.length; i++) {
                File f = new File(elements[i]);
                validateFile(f);
                String asUrl = toURL(f);
                urls.append(asUrl);
                log(asUrl, Project.MSG_DEBUG);
                urls.append(separator);
                count++;
            }
        }
        return stripTrailingSeparator(urls, count);
    }

    /**
     * verify that the file exists, if {@link #validate} is set
     *
     * @param fileToCheck file that may need to exist
     * @throws BuildException with text beginning {@link #ERROR_MISSING_FILE}
     */
    private void validateFile(File fileToCheck) {
        if (validate && !fileToCheck.exists()) {
            throw new BuildException(ERROR_MISSING_FILE + fileToCheck.toString());
        }
    }

    /**
     * Create the url
     *
     * @throws org.apache.tools.ant.BuildException
     *          if something goes wrong with the build
     */
    public void execute() throws BuildException {
        validate();
        if (getProject().getProperty(property) != null) {
            return;
        }
        String url;
        String filesetURL = filesetsToURL();
        if (file != null) {
            validateFile(file);
            url = toURL(file);
            if (filesetURL.length() > 0) {
                url = url + separator + filesetURL;
            }
        } else {
            url = filesetURL;
        }
        String pathURL = pathsToURL();
        if (pathURL.length() > 0) {
            if (url.length() > 0) {
                url = url + separator + pathURL;
            } else {
                url = pathURL;
            }
        }
        log("Setting " + property + " to URL " + url, Project.MSG_VERBOSE);
        getProject().setNewProperty(property, url);
    }

    /**
     * check for errors
     * @throws BuildException if we are not configured right
     */
    private void validate() {
        if (property == null) {
            throw new BuildException(ERROR_NO_PROPERTY);
        }
        if (file == null && filesets.isEmpty() && paths.isEmpty()) {
            throw new BuildException(ERROR_NO_FILES);
        }
    }

    /**
     * convert a file to a URL;
     *
     * @param fileToConvert
     * @return the file converted to a URL
     */
    private String toURL(File fileToConvert) {
        String url;
        url = FileUtils.getFileUtils().toURI(fileToConvert.getAbsolutePath());

        return url;

FUNC_DECL IF PARAM PARAM BINARY_OP RETURN RETURN LITERAL_ANCHOR LITERAL_ANCHOR CALL CALL CALL BINARY_OP CALL CALL

FUNC_DECL RETURN VAR_DECL PARAM ASSIGN CALL CALL CALL


class TemplateSubPatternAssociation implements Serializable, Cloneable
{

  /** Step pattern           */
  StepPattern m_stepPattern;

  /** Template pattern          */
  private String m_pattern;

  /** The template element         */
  private ElemTemplate m_template;

  /** Next pattern         */
  private TemplateSubPatternAssociation m_next = null;

  /** Flag indicating whether this is wild card pattern          */
  private boolean m_wild;

  /** Target string for this match pattern           */
  private String m_targetString;

  /**
   * Construct a match pattern from a pattern and template.
   * @param template The node that contains the template for this pattern.
   * @param pattern An executable XSLT StepPattern.
   * @param pat For now a Nodelist that contains old-style element patterns.
   */
  TemplateSubPatternAssociation(ElemTemplate template, StepPattern pattern, String pat)
  {

    m_pattern = pat;
    m_template = template;
    m_stepPattern = pattern;
    m_targetString = m_stepPattern.getTargetString();
    m_wild = m_targetString.equals("*");
  }

  /**
   * Clone this object.
   *
   * @return The cloned object.
   *
   * @throws CloneNotSupportedException
   */
  public Object clone() throws CloneNotSupportedException
  {

    TemplateSubPatternAssociation tspa =
      (TemplateSubPatternAssociation) super.clone();

    tspa.m_next = null;

    return tspa;
  }

  /**
   * Get the target string of the pattern.  For instance, if the pattern is
   * "foo/baz/boo[@daba]", this string will be "boo".
   *
   * @return The "target" string.
   */
  public final String getTargetString()
  {
    return m_targetString;
  }

  /**
   * Set Target String for this template pattern
   *
   *
   * @param key Target string to set
   */
  public void setTargetString(String key)
  {
    m_targetString = key;
  }

  /**
   * Tell if two modes match according to the rules of XSLT.
   *
   * @param m1 mode to match
   *
   * @return True if the given mode matches this template's mode
   */
  boolean matchMode(QName m1)
  {
    return matchModes(m1, m_template.getMode());
  }

  /**
   * Tell if two modes match according to the rules of XSLT.
   *
   * @param m1 First mode to match
   * @param m2 Second mode to match
   *
   * @return True if the two given modes match
   */
  private boolean matchModes(QName m1, QName m2)
  {
    return (((null == m1) && (null == m2))
            || ((null != m1) && (null != m2) && m1.equals(m2)));
  }

  /**
   * Return the mode associated with the template.
   *
   *
   * @param xctxt XPath context to use with this template
   * @param targetNode Target node
   * @return The mode associated with the template.
   *
   * @throws TransformerException
   */
  public boolean matches(XPathContext xctxt, int targetNode, QName mode)
          throws TransformerException
  {

    double score = m_stepPattern.getMatchScore(xctxt, targetNode);

    return (XPath.MATCH_SCORE_NONE != score)
           && matchModes(mode, m_template.getMode());
  }

  /**
   * Tell if the pattern for this association is a wildcard.
   *
   * @return true if this pattern is considered to be a wild match.
   */
  public final boolean isWild()
  {
    return m_wild;
  }

  /**
   * Get associated XSLT StepPattern.
   *
   * @return An executable StepPattern object, never null.
   *
   */
  public final StepPattern getStepPattern()
  {
    return m_stepPattern;
  }

  /**
   * Get the pattern string for diagnostic purposes.
   *
   * @return The pattern string for diagnostic purposes.
   *
   */
  public final String getPattern()
  {
    return m_pattern;
  }

  /**
   * Return the position of the template in document
   * order in the stylesheet.
   *
   * @return The position of the template in the overall template order.
   */
  public int getDocOrderPos()
  {
    return m_template.getUid();
  }

  /**
   * Return the import level associated with the stylesheet into which
   * this template is composed.
   *
   * @return The import level of this template.
   */
  public final int getImportLevel()
  {
    return m_template.getStylesheetComposed().getImportCountComposed();
  }

  /**
   * Get the assocated xsl:template.
   *
   * @return An ElemTemplate, never null.
   *
   */
  public final ElemTemplate getTemplate()
  {
    return m_template;
  }

  /**
   * Get the next association.
   *
   * @return A valid TemplateSubPatternAssociation, or null.
   */
  public final TemplateSubPatternAssociation getNext()
  {
    return m_next;
  }

  /**
   * Set the next element on this association
   * list, which should be equal or less in priority to
   * this association, and, if equal priority, should occur
   * before this template in document order.
   *
   * @param mp The next association to score if this one fails.
   *
   */
  public void setNext(TemplateSubPatternAssociation mp)
  {
    m_next = mp;

FUNC_DECL PARAM PARAM PARAM ASSIGN ASSIGN ASSIGN ASSIGN ASSIGN CALL CALL LITERAL_ANCHOR


/*package-private*/ class FailFast implements Iterator {
    private static final WeakHashMap MAP = new WeakHashMap();

    /**
     * Invalidate any in-use Iterators from the specified Object.
     * @param o the parent Object.
     */
    static synchronized void invalidate(Object o) {
        Set s = (Set) (MAP.get(o));
        if (s != null) {
            s.clear();
        }
    }

    private static synchronized void add(FailFast f) {
        Set s = (Set) (MAP.get(f.parent));
        if (s == null) {
            s = new HashSet();
            MAP.put(f.parent, s);
        }
        s.add(f);
    }

    private static synchronized void remove(FailFast f) {
        Set s = (Set) (MAP.get(f.parent));
        if (s != null) {
            s.remove(f);
        }
    }

    private static synchronized void failFast(FailFast f) {
        Set s = (Set) (MAP.get(f.parent));
        if (!s.contains(f)) {
            throw new ConcurrentModificationException();
        }
    }

    private Object parent;
    private Iterator wrapped;

    /**
     * Construct a new FailFast Iterator wrapping the specified Iterator
     * and dependent upon the specified parent Object.
     * @param o the parent Object.
     * @param i the wrapped Iterator.
     */
    FailFast(Object o, Iterator i) {
        if (o == null) {
            throw new IllegalArgumentException("parent object is null");
        }
        if (i == null) {
            throw new IllegalArgumentException("cannot wrap null iterator");
        }
        parent = o;
        if (i.hasNext()) {
            wrapped = i;
            add(this);
        }
    }

    /**
     * Fulfill the Iterator contract.
     * @return true if there are more elements.
     */
    public boolean hasNext() {
        if (wrapped == null) {
            return false;
        }
        failFast(this);
        return wrapped.hasNext();
    }

    /**
     * Fulfill the Iterator contract.
     * @return the next element.
     * @throws NoSuchElementException if no more elements.
     */
    public Object next() {
        if (wrapped == null || !wrapped.hasNext()) {
            throw new NoSuchElementException();
        }
        failFast(this);
        try {
            return wrapped.next();
        } finally {
            if (!wrapped.hasNext()) {
                wrapped = null;
                remove(this);
            }
        }
    }

    /**
     * Fulfill the Iterator contract.
     * @throws UnsupportedOperationException always.
     */
    public void remove() {
        throw new UnsupportedOperationException();