Open Source Repository

Home /xwork/xwork-core-2.1.6 | Repository Home


com/opensymphony/xwork2/util/ClassPathFinder.java
/*
 * $Id: $
 *
 * Copyright 2003-2004 The Apache Software Foundation.
 *
 * 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.opensymphony.xwork2.util;

import com.opensymphony.xwork2.XWorkException;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Vector;

/**
 * This class is an utility class that will search through the classpath
 * for files whose names match the given pattern. The filename is tested
 * using the given implementation of {@link com.opensymphony.xwork2.util.PatternMatcher} by default it 
 * uses {@link com.opensymphony.xwork2.util.WildcardHelper}
 *
 @version $Rev: $ $Date: $
 */
public class ClassPathFinder {
  
  /**
     * The String pattern to test against.
     */
  private String pattern ;
  
  private int[] compiledPattern ;
  
  /**
     * The PatternMatcher implementation to use
     */
  private PatternMatcher<int[]> patternMatcher = new WildcardHelper();
  
  private Vector<String> compared = new Vector<String>();
  
  /**
   * retrieves the pattern in use
   */
  public String getPattern() {
    return pattern;
  }

  /**
   * sets the String pattern for comparing filenames
   @param pattern
   */
  public void setPattern(String pattern) {
    this.pattern = pattern;
  }

  /**
     * Builds a {@link java.util.Vector} containing Strings which each name a file
     * who's name matches the pattern set by setPattern(String). The classpath is 
     * searched recursively, so use with caution.
     *
     @return Vector<String> containing matching filenames
     */
  public Vector<String> findMatches() {
    Vector<String> matches = new Vector<String>();
    URLClassLoader cl = getURLClassLoader();
    if (cl == null ) {
      throw new XWorkException("unable to attain an URLClassLoader";
    }
    URL[] parentUrls = cl.getURLs();
    compiledPattern = (int[]) patternMatcher.compilePattern(pattern);
    for (URL url : parentUrls) {
      if (!"file".equals(url.getProtocol())) {
        continue ;
      }
      URI entryURI ;
      try {
        entryURI = url.toURI();
      catch (URISyntaxException e) {
        continue;
      }
      File entry = new File(entryURI;
      Vector<String> results = checkEntries(entry.list(), entry, "");
      if (results != null ) {
        matches.addAll(results);
      }
    }
    return matches;
  }
  
  private Vector<String> checkEntries(String[] entries, File parent, String prefix) {
    
    if (entries == null ) {
      return null;
    }
    
    Vector<String> matches = new Vector<String>();
    for (String listEntry : entries) {
      File tempFile ;
      if (!"".equals(prefix) ) {
        tempFile = new File(parent, prefix + "/" + listEntry);
      }
      else {
        tempFile = new File(parent, listEntry);
      }
      if (tempFile.isDirectory() && 
          !(".".equals(listEntry|| "..".equals(listEntry)) ) {
        if  (!"".equals(prefix) ) {
          matches.addAll(checkEntries(tempFile.list(), parent, prefix + "/" + listEntry));
        }
        else {
          matches.addAll(checkEntries(tempFile.list(), parent, listEntry));
        }
      }
      else {
        
        String entryToCheck ;
        if ("".equals(prefix)) {
          entryToCheck = listEntry ;
        }
        else {
          entryToCheck = prefix + "/" + listEntry ;
        }
        
        if (compared.contains(entryToCheck) ) {
          continue;
        }
        else {
          compared.add(entryToCheck;
        }
        
        boolean doesMatch = patternMatcher.match(new HashMap<String,String>(), entryToCheck, compiledPattern);
        if (doesMatch) {
          matches.add(entryToCheck);
        }
      }
    }
    return matches ;
  }

  /**
   * sets the PatternMatcher implementation to use when comparing filenames
   @param patternMatcher
   */
  public void setPatternMatcher(PatternMatcher<int[]> patternMatcher) {
    this.patternMatcher = patternMatcher;
  }

  private URLClassLoader getURLClassLoader() {
    URLClassLoader ucl = null;
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    
    if((loader instanceof URLClassLoader)) {
      loader = ClassPathFinder.class.getClassLoader();
      if (loader instanceof URLClassLoader) {
        ucl = (URLClassLoaderloader ;
      }
    }
    else {
      ucl = (URLClassLoaderloader;
    }
    
    return ucl ;
  }
}