blob: 5838abdef3694a229f156ea63fba9e9b8547a2b9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* 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}
*/
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<>();
/**
* @return the pattern in use
*/
public String getPattern() {
return pattern;
}
/**
* @param pattern the String pattern for comparing filenames
*/
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&lt;String&gt; containing matching filenames
*/
public Vector<String> findMatches() {
Vector<String> matches = new Vector<>();
URL[] parentUrls = getClassLoaderURLs();
compiledPattern = 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);
if (entry.isFile() && entry.toString().endsWith(".jar")) {
try {
ZipInputStream zip = new ZipInputStream(new FileInputStream(entry));
for (ZipEntry zipEntry = zip.getNextEntry(); zipEntry != null; zipEntry = zip.getNextEntry()) {
boolean doesMatch = patternMatcher.match(new HashMap<String, String>(), zipEntry.getName(), compiledPattern);
if (doesMatch) {
matches.add(zipEntry.getName());
}
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
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<>();
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 ;
}
/**
* @param patternMatcher the PatternMatcher implementation to use when comparing filenames
*/
public void setPatternMatcher(PatternMatcher<int[]> patternMatcher) {
this.patternMatcher = patternMatcher;
}
private URL[] getClassLoaderURLs() {
URL[] urls;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (!(loader instanceof URLClassLoader)) {
loader = ClassPathFinder.class.getClassLoader();
}
if (loader instanceof URLClassLoader) {
urls = ((URLClassLoader) loader).getURLs();
} else { //jdk9 or later
try {
urls = Collections.list(loader.getResources("")).toArray(new URL[0]);
} catch (IOException e) {
throw new XWorkException("unable to get ClassLoader URLs", e);
}
}
return urls;
}
}