426920 - jetty-start / BaseHome.listFilesRegex() and .recurseDir() do not detect filesystem loops

+ Using java.nio.files to walk directory tree and detect filesystem
  loops
+ All standard PathMatching patterns now work. ("glob:" and "regex:")
This commit is contained in:
Joakim Erdfelt 2014-03-26 19:01:05 -07:00
parent 1444ffadb8
commit dfbe5c92c6
18 changed files with 978 additions and 325 deletions

View File

@ -1,9 +1,9 @@
#
# Module to add all lib/ext/*.jar files to classpath
# Module to add all lib/ext/**.jar files to classpath
#
[lib]
regex:lib/ext/.*\.jar$
lib/ext/**.jar
[files]
lib/

View File

@ -19,21 +19,21 @@
package org.eclipse.jetty.start;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jetty.start.FS.RelativeRegexFilter;
/**
* File access for <code>${jetty.home}</code>, <code>${jetty.base}</code>, directories.
* <p>
@ -45,6 +45,9 @@ import org.eclipse.jetty.start.FS.RelativeRegexFilter;
*/
public class BaseHome
{
private final static EnumSet<FileVisitOption> SEARCH_VISIT_OPTIONS = EnumSet.of(FileVisitOption.FOLLOW_LINKS);;
private final static int MAX_SEARCH_DEPTH = 30;
private File homeDir;
private File baseDir;
@ -119,7 +122,7 @@ public class BaseHome
* <ol>
* <li>If exists relative to <code>${jetty.base}</code>, return that reference</li>
* <li>If exists relative to <code>${jetty.home}</code>, return that reference</li>
* <li>Otherwise return absolute path reference</li>
* <li>Otherwise return absolute path reference (standard java logic)</li>
* </ol>
*
* @param path
@ -151,6 +154,140 @@ public class BaseHome
return new File(rpath);
}
/**
* Get a List of {@link Path}s from a provided pattern.
* <p>
* Resolution Steps:
* <ol>
* <li>If the pattern starts with "regex:" or "glob:" then a standard {@link PathMatcher} is built using
* {@link java.nio.file.FileSystem#getPathMatcher(String)} as a file search.</li>
* <li>If pattern starts with a known filesystem root (using information from {@link java.nio.file.FileSystem#getRootDirectories()}) then this is assumed to
* be a absolute file system pattern.</li>
* <li>All other patterns are treated as relative to BaseHome information:
* <ol>
* <li>Search ${jetty.home} first</li>
* <li>Search ${jetty.base} for overrides</li>
* </ol>
* </li>
* </ol>
* <p>
* Pattern examples:
* <dl>
* <dt><code>lib/logging/*.jar</code></dt>
* <dd>Relative pattern, not recursive, search <code>${jetty.home}</code> then <code>${jetty.base}</code> for lib/logging/*.jar content</dd>
*
* <dt><code>lib/**&#47;*-dev.jar</code></dt>
* <dd>Relative pattern, recursive search <code>${jetty.home}</code> then <code>${jetty.base}</code> for files under <code>lib</code> ending in
* <code>-dev.jar</code></dd>
* </dl>
*
* <dt><code>etc/jetty.xml</code></dt>
* <dd>Relative pattern, no glob, search for <code>${jetty.home}/etc/jetty.xml</code> then <code>${jetty.base}/etc/jetty.xml</code></dd>
*
* <dt><code>glob:/opt/app/common/*-corp.jar</code></dt>
* <dd>PathMapper pattern, glob, search <code>/opt/app/common/</code> for <code>*-corp.jar</code></code></dd>
*
* </dl>
*
* <p>
* Notes:
* <ul>
* <li>FileSystem case sensitivity is implementation specific (eg: linux is case-sensitive, windows is case-insensitive).<br/>
* See {@link java.nio.file.FileSystem#getPathMatcher(String)} for more details</li>
* <li>Pattern slashes are implementation neutral (use '/' always and you'll be fine)</li>
* <li>Recursive searching is limited to 30 levels deep (not configurable)</li>
* <li>File System loops are detected and skipped</li>
* </ul>
*
* @param pattern
* the pattern to search.
* @return the collection of paths found
* @throws IOException
* if error during search operation
*/
public List<Path> getPaths(String pattern) throws IOException
{
List<Path> hits = new ArrayList<>();
if (PathMatchers.isAbsolute(pattern))
{
Path root = PathMatchers.getSearchRoot(pattern);
PathMatcher matcher = PathMatchers.getMatcher(pattern);
if (FS.isValidDirectory(root))
{
PathFinder finder = new PathFinder();
finder.setFileMatcher(matcher);
finder.setBase(root);
Files.walkFileTree(root,SEARCH_VISIT_OPTIONS,MAX_SEARCH_DEPTH,finder);
hits.addAll(finder.getHits());
}
}
else
{
Path relativePath = PathMatchers.getSearchRoot(pattern);
PathMatcher matcher = PathMatchers.getMatcher(pattern);
PathFinder finder = new PathFinder();
finder.setFileMatcher(matcher);
Path homePath = homeDir.toPath().resolve(relativePath);
if (FS.isValidDirectory(homePath))
{
finder.setBase(homePath);
Files.walkFileTree(homePath,SEARCH_VISIT_OPTIONS,MAX_SEARCH_DEPTH,finder);
}
if (isBaseDifferent())
{
Path basePath = baseDir.toPath().resolve(relativePath);
if (FS.isValidDirectory(basePath))
{
finder.setBase(basePath);
Files.walkFileTree(basePath,SEARCH_VISIT_OPTIONS,MAX_SEARCH_DEPTH,finder);
}
}
hits.addAll(finder.getHits());
}
Collections.sort(hits,new NaturalSort.Paths());
return hits;
}
/**
* Search specified Path with pattern and return hits
*
* @param dir
* the path to a directory to start search from
* @param searchDepth
* the number of directories deep to perform the search
* @param pattern
* the raw pattern to use for the search (must be relative)
* @return the list of Paths found
* @throws IOException
* if unable to search the path
*/
public List<Path> getPaths(Path dir, int searchDepth, String pattern) throws IOException
{
if (PathMatchers.isAbsolute(pattern))
{
throw new RuntimeException("Pattern cannot be absolute: " + pattern);
}
List<Path> hits = new ArrayList<>();
if (FS.isValidDirectory(dir))
{
PathMatcher matcher = PathMatchers.getMatcher(pattern);
PathFinder finder = new PathFinder();
finder.setFileMatcher(matcher);
finder.setBase(dir);
Files.walkFileTree(dir,SEARCH_VISIT_OPTIONS,searchDepth,finder);
hits.addAll(finder.getHits());
Collections.sort(hits,new NaturalSort.Paths());
}
return hits;
}
public String getHome()
{
return homeDir.getAbsolutePath();
@ -213,183 +350,6 @@ public class BaseHome
return homeDir.compareTo(baseDir) != 0;
}
/**
* Get all of the files that are in a specific relative directory.
* <p>
* If the same found path exists in both <code>${jetty.base}</code> and <code>${jetty.home}</code>, then the one in <code>${jetty.base}</code> is returned
* (it overrides the one in ${jetty.home})
*
* @param relPathToDirectory
* the relative path to the directory
* @return the list of files found.
*/
public List<File> listFiles(String relPathToDirectory)
{
return listFiles(relPathToDirectory,FS.AllFilter.INSTANCE);
}
/**
* Get all of the files that are in a specific relative directory, with applied {@link FileFilter}
* <p>
* If the same found path exists in both <code>${jetty.base}</code> and <code>${jetty.home}</code>, then the one in <code>${jetty.base}</code> is returned
* (it overrides the one in ${jetty.home})
*
* @param relPathToDirectory
* the relative path to the directory
* @param filter
* the filter to use
* @return the list of files found.
*/
public List<File> listFiles(String relPathToDirectory, FileFilter filter)
{
Objects.requireNonNull(filter,"FileFilter cannot be null");
File homePath = new File(homeDir,FS.separators(relPathToDirectory));
List<File> homeFiles = new ArrayList<>();
if (FS.canReadDirectory(homePath))
{
homeFiles.addAll(Arrays.asList(homePath.listFiles(filter)));
}
if (isBaseDifferent())
{
// merge
File basePath = new File(baseDir,FS.separators(relPathToDirectory));
List<File> ret = new ArrayList<>();
if (FS.canReadDirectory(basePath))
{
File baseFiles[] = basePath.listFiles(filter);
if (baseFiles != null)
{
for (File base : baseFiles)
{
String relpath = toRelativePath(baseDir,base);
File home = new File(homeDir,FS.separators(relpath));
if (home.exists())
{
homeFiles.remove(home);
}
ret.add(base);
}
}
}
// add any remaining home files.
ret.addAll(homeFiles);
Collections.sort(ret,new NaturalSort.Files());
return ret;
}
else
{
// simple return
Collections.sort(homeFiles,new NaturalSort.Files());
return homeFiles;
}
}
/**
* Get all of the files that are in a specific relative directory, with applied regex.
* <p>
* If the same found path exists in both <code>${jetty.base}</code> and <code>${jetty.home}</code>, then the one in <code>${jetty.base}</code> is returned
* (it overrides the one in ${jetty.home})
* <p>
* All regex paths are assumed to be in unix notation (use of <code>"/"</code> to separate paths, as <code>"\"</code> is used to escape in regex)
*
* @param regex
* the regex to use to match against the found files.
* @return the list of files found.
*/
public List<File> listFilesRegex(String regex)
{
Objects.requireNonNull(regex,"Glob cannot be null");
Pattern pattern = Pattern.compile(regex);
List<File> homeFiles = new ArrayList<>();
if (FS.canReadDirectory(homeDir))
{
StartLog.debug("Finding files in ${jetty.home} that match: %s",regex);
recurseDir(homeFiles,homeDir,new FS.RelativeRegexFilter(homeDir,pattern));
StartLog.debug("Found %,d files",homeFiles.size());
}
if (isBaseDifferent())
{
// merge
List<File> ret = new ArrayList<>();
if (FS.canReadDirectory(baseDir))
{
List<File> baseFiles = new ArrayList<>();
StartLog.debug("Finding files in ${jetty.base} that match: %s",regex);
recurseDir(baseFiles,baseDir,new FS.RelativeRegexFilter(baseDir,pattern));
StartLog.debug("Found %,d files",baseFiles.size());
for (File base : baseFiles)
{
String relpath = toRelativePath(baseDir,base);
File home = new File(homeDir,FS.separators(relpath));
if (home.exists())
{
homeFiles.remove(home);
}
ret.add(base);
}
}
// add any remaining home files.
ret.addAll(homeFiles);
StartLog.debug("Merged Files: %,d files%n",ret.size());
Collections.sort(ret,new NaturalSort.Files());
return ret;
}
else
{
// simple return
Collections.sort(homeFiles,new NaturalSort.Files());
return homeFiles;
}
}
private void recurseDir(List<File> files, File dir, RelativeRegexFilter filter)
{
// find matches first
files.addAll(Arrays.asList(dir.listFiles(filter)));
// now dive down into sub-directories
for (File subdir : dir.listFiles(FS.DirFilter.INSTANCE))
{
recurseDir(files,subdir,filter);
}
}
/**
* Collect the list of files in both <code>${jetty.base}</code> and <code>${jetty.home}</code>, even if the same file shows up in both places.
*/
public List<File> rawListFiles(String relPathToDirectory, FileFilter filter)
{
Objects.requireNonNull(filter,"FileFilter cannot be null");
List<File> ret = new ArrayList<>();
// Home Dir
File homePath = new File(homeDir,FS.separators(relPathToDirectory));
ret.addAll(Arrays.asList(homePath.listFiles(filter)));
if (isBaseDifferent())
{
// Base Dir
File basePath = new File(baseDir,FS.separators(relPathToDirectory));
ret.addAll(Arrays.asList(basePath.listFiles(filter)));
}
// Sort
Collections.sort(ret,new NaturalSort.Files());
return ret;
}
public void setBaseDir(File dir)
{
try
@ -416,12 +376,6 @@ public class BaseHome
}
}
// TODO - inline
private String toRelativePath(File dir, File path)
{
return FS.toRelativePath(dir,path);
}
/**
* Convenience method for <code>toShortForm(file.getCanonicalPath())</code>
*/

View File

@ -22,11 +22,15 @@ import java.io.Closeable;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.Locale;
import java.util.regex.Pattern;
public class FS
{
@Deprecated
public static class AllFilter implements FileFilter
{
public static final AllFilter INSTANCE = new AllFilter();
@ -37,7 +41,8 @@ public class FS
return true;
}
}
@Deprecated
public static class DirFilter implements FileFilter
{
public static final DirFilter INSTANCE = new DirFilter();
@ -48,7 +53,8 @@ public class FS
return path.isDirectory();
}
}
@Deprecated
public static class RelativeRegexFilter implements FileFilter
{
private final File baseDir;
@ -65,12 +71,13 @@ public class FS
{
// get relative path
String relativePath = FS.toRelativePath(baseDir,path);
// see if it matches
return (pattern.matcher(relativePath).matches());
}
}
@Deprecated
public static class FilenameRegexFilter implements FileFilter
{
private final Pattern pattern;
@ -87,6 +94,7 @@ public class FS
}
}
@Deprecated
public static class FileNamesFilter implements FileFilter
{
private final String filenames[];
@ -114,6 +122,7 @@ public class FS
}
}
@Deprecated
public static class IniFilter extends FilenameRegexFilter
{
public IniFilter()
@ -122,6 +131,7 @@ public class FS
}
}
@Deprecated
public static class XmlFilter extends FilenameRegexFilter
{
public XmlFilter()
@ -130,11 +140,36 @@ public class FS
}
}
public static boolean isValidDirectory(Path path)
{
LinkOption lopts[] = new LinkOption[0];
if (!Files.exists(path,lopts))
{
// doesn't exist, not a valid directory
return false;
}
if (!Files.isDirectory(path,lopts))
{
// not a directory (as expected)
StartLog.warn("Not a directory: " + path);
return false;
}
return true;
}
public static boolean canReadDirectory(File path)
{
return (path.exists() && path.isDirectory() && path.canRead());
}
public static boolean canReadDirectory(Path path)
{
LinkOption lopts[] = new LinkOption[0];
return Files.exists(path,lopts) && Files.isDirectory(path,lopts) && Files.isReadable(path);
}
public static boolean canReadFile(File path)
{
return (path.exists() && path.isFile() && path.canRead());
@ -168,7 +203,7 @@ public class FS
throw new IOException("Unable to create directory: " + dir.getAbsolutePath());
}
}
public static void ensureDirectoryWritable(File dir) throws IOException
{
if (!dir.exists())
@ -194,7 +229,7 @@ public class FS
{
return filename.toLowerCase(Locale.ENGLISH).endsWith(".xml");
}
public static String toRelativePath(File baseDir, File path)
{
return baseDir.toURI().relativize(path.toURI()).toASCIIString();
@ -216,4 +251,9 @@ public class FS
}
return ret.toString();
}
public static boolean exists(Path path)
{
return Files.exists(path,new LinkOption[0]);
}
}

View File

@ -18,9 +18,7 @@
package org.eclipse.jetty.start;
import static org.eclipse.jetty.start.UsageException.ERR_INVOKE_MAIN;
import static org.eclipse.jetty.start.UsageException.ERR_NOT_STOPPED;
import static org.eclipse.jetty.start.UsageException.ERR_UNKNOWN;
import static org.eclipse.jetty.start.UsageException.*;
import java.io.BufferedReader;
import java.io.File;
@ -39,6 +37,7 @@ import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -534,17 +533,12 @@ public class Main
File start_d = baseHome.getBaseFile("start.d");
if (FS.canReadDirectory(start_d))
{
List<File> files = new ArrayList<>();
for (File file : start_d.listFiles(new FS.IniFilter()))
List<Path> paths = baseHome.getPaths(start_d.toPath(),1,"*.ini");
Collections.sort(paths,new NaturalSort.Paths());
for (Path path: paths)
{
files.add(file);
}
Collections.sort(files,new NaturalSort.Files());
for (File file : files)
{
StartLog.debug("Reading ${jetty.base}/start.d/%s - %s",file.getName(),file);
args.parse(baseHome,new StartIni(file));
StartLog.debug("Reading ${jetty.base}/start.d/%s - %s",path.getFileName(),path);
args.parse(baseHome,new StartIni(path));
}
}

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.start;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -45,7 +46,7 @@ public class Modules implements Iterable<Module>
* ex: modules/npn/npn-1.7.0_01.mod (property expansion resolves to non-existent file)
*/
private Set<String> missingModules = new HashSet<String>();
private int maxDepth = -1;
private Set<String> asNameSet(Set<Module> moduleSet)
@ -294,10 +295,10 @@ public class Modules implements Iterable<Module>
private void findParents(Module module, Map<String, Module> ret)
{
ret.put(module.getName(), module);
ret.put(module.getName(),module);
for (Module parent : module.getParentEdges())
{
ret.put(parent.getName(), parent);
ret.put(parent.getName(),parent);
findParents(parent,ret);
}
}
@ -371,13 +372,13 @@ public class Modules implements Iterable<Module>
public void registerAll(BaseHome basehome, StartArgs args) throws IOException
{
for (File file : basehome.listFiles("modules",new FS.FilenameRegexFilter("^.*\\.mod$")))
for (Path path : basehome.getPaths("modules/*.mod"))
{
registerModule(basehome,args,file);
registerModule(basehome,args,path.toFile());
}
// load missing post-expanded dependent modules
boolean done = false;
boolean done = false;
while (!done)
{
done = true;
@ -399,14 +400,14 @@ public class Modules implements Iterable<Module>
for (String missingParent : missingParents)
{
File file = basehome.getFile("modules/" + missingParent + ".mod");
if ( FS.canReadFile(file) )
if (FS.canReadFile(file))
{
Module module = registerModule(basehome,args,file);
updateParentReferencesTo(module);
}
else
{
StartLog.debug("Missing module definition: [ Mod: %s | File: %s]", missingParent, file);
StartLog.debug("Missing module definition: [ Mod: %s | File: %s]",missingParent,file);
missingModules.add(missingParent);
}
}
@ -440,7 +441,7 @@ public class Modules implements Iterable<Module>
*/
public List<Module> resolveEnabled()
{
Map<String, Module> active = new HashMap<String,Module>();
Map<String, Module> active = new HashMap<String, Module>();
for (Module module : modules.values())
{
@ -455,20 +456,20 @@ public class Modules implements Iterable<Module>
*
* Ex: npn should match anything under npn/
*/
for ( String missing : missingModules )
for (String missing : missingModules)
{
for (String activeModule: active.keySet())
{
if ( missing.startsWith(activeModule) )
for (String activeModule : active.keySet())
{
if (missing.startsWith(activeModule))
{
StartLog.warn("** Unable to continue, required dependency missing. [%s]", missing);
StartLog.warn("** Unable to continue, required dependency missing. [%s]",missing);
StartLog.warn("** As configured, Jetty is unable to start due to a missing enabled module dependency.");
StartLog.warn("** This may be due to a transitive dependency akin to spdy on npn, which resolves based on the JDK in use.");
return Collections.emptyList();
}
}
}
List<Module> ordered = new ArrayList<>();
ordered.addAll(active.values());
Collections.sort(ordered,new Module.DepthComparator());
@ -477,7 +478,7 @@ public class Modules implements Iterable<Module>
public Set<String> resolveParentModulesOf(String moduleName)
{
Map<String,Module> ret = new HashMap<>();
Map<String, Module> ret = new HashMap<>();
Module module = get(moduleName);
findParents(module,ret);
return ret.keySet();
@ -524,4 +525,26 @@ public class Modules implements Iterable<Module>
m.setParentNames(resolvedParents);
}
}
@Override
public String toString()
{
StringBuilder str = new StringBuilder();
str.append("Modules[");
str.append("count=").append(modules.size());
str.append(",<");
boolean delim = false;
for (String name : modules.keySet())
{
if (delim)
{
str.append(',');
}
str.append(name);
delim = true;
}
str.append(">");
str.append("]");
return str.toString();
}
}

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.start;
import java.io.File;
import java.nio.file.Path;
import java.text.CollationKey;
import java.text.Collator;
import java.util.Comparator;
@ -28,6 +29,19 @@ import java.util.Comparator;
*/
public class NaturalSort
{
public static class Paths implements Comparator<Path>
{
private final Collator collator = Collator.getInstance();
@Override
public int compare(Path o1, Path o2)
{
CollationKey key1 = collator.getCollationKey(o1.toString());
CollationKey key2 = collator.getCollationKey(o2.toString());
return key1.compareTo(key2);
}
}
public static class Files implements Comparator<File>
{
private final Collator collator = Collator.getInstance();

View File

@ -0,0 +1,161 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystemLoopException;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PathFinder extends SimpleFileVisitor<Path>
{
private boolean includeDirsInResults = false;
private Map<String, Path> hits = new HashMap<>();
private Path basePath = null;
private PathMatcher dirMatcher = PathMatchers.getNonHidden();
private PathMatcher fileMatcher = PathMatchers.getNonHidden();
private void addHit(Path path)
{
String relPath = basePath.relativize(path).toString();
StartLog.debug("addHit(" + path + ") = [" + relPath + "," + path + "]");
hits.put(relPath,path);
}
public PathMatcher getDirMatcher()
{
return dirMatcher;
}
public PathMatcher getFileMatcher()
{
return fileMatcher;
}
public List<File> getHitList()
{
List<File> ret = new ArrayList<>();
for (Path path : hits.values())
{
ret.add(path.toFile());
}
return ret;
}
public Collection<Path> getHits()
{
return hits.values();
}
public boolean isIncludeDirsInResults()
{
return includeDirsInResults;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
{
if (dirMatcher.matches(dir))
{
StartLog.debug("Following dir: " + dir);
if (includeDirsInResults)
{
addHit(dir);
}
return FileVisitResult.CONTINUE;
}
else
{
StartLog.debug("Skipping dir: " + dir);
return FileVisitResult.SKIP_SUBTREE;
}
}
/**
* Set the active basePath, used for resolving relative paths.
* <p>
* When a hit arrives for a subsequent find that has the same relative path as a prior hit, the new hit overrides the prior path as the active hit.
*
* @param basePath
* the basePath to tag all hits with
*/
public void setBase(Path basePath)
{
this.basePath = basePath;
}
public void setDirMatcher(PathMatcher dirMatcher)
{
this.dirMatcher = dirMatcher;
}
public void setFileMatcher(PathMatcher fileMatcher)
{
this.fileMatcher = fileMatcher;
}
public void setFileMatcher(String pattern)
{
this.fileMatcher = PathMatchers.getMatcher(pattern);
}
public void setIncludeDirsInResults(boolean includeDirsInResults)
{
this.includeDirsInResults = includeDirsInResults;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
{
if (fileMatcher.matches(file))
{
StartLog.debug("Found file: " + file);
addHit(file);
}
else
{
StartLog.debug("Ignoring file: " + file);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException
{
if (exc instanceof FileSystemLoopException)
{
StartLog.warn("skipping detected filesystem loop: " + file);
return FileVisitResult.SKIP_SUBTREE;
}
else
{
StartLog.warn(exc);
return super.visitFileFailed(file,exc);
}
}
}

View File

@ -0,0 +1,208 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
/**
* Common PathMatcher implementations.
*/
public class PathMatchers
{
private static class NonHiddenMatcher implements PathMatcher
{
@Override
public boolean matches(Path path)
{
try
{
return !Files.isHidden(path);
}
catch (IOException e)
{
StartLog.debug(e);
return false;
}
}
}
private static final char GLOB_CHARS[] = "*?".toCharArray();
private static final char SYNTAXED_GLOB_CHARS[] = "{}[]|:".toCharArray();
private static final Path EMPTY_PATH = new File(".").toPath();
/**
* Convert a pattern to a Path object.
*
* @param pattern
* the raw pattern (can contain "glob:" or "regex:" syntax indicator)
* @return the Path version of the pattern provided.
*/
private static Path asPath(String pattern)
{
String test = pattern;
if (test.startsWith("glob:"))
{
test = test.substring("glob:".length());
}
else if (test.startsWith("regex:"))
{
test = test.substring("regex:".length());
}
return new File(test).toPath();
}
public static PathMatcher getMatcher(String pattern)
{
FileSystem fs = FileSystems.getDefault();
// If using FileSystem.getPathMatcher() with "glob:" or "regex:"
// use FileSystem default pattern behavior
if (pattern.startsWith("glob:") || pattern.startsWith("regex:"))
{
StartLog.debug("Using Standard " + fs.getClass().getName() + " pattern: " + pattern);
return fs.getPathMatcher(pattern);
}
// If the pattern starts with a root path then its assumed to
// be a full system path
for (Path root : fs.getRootDirectories())
{
StartLog.debug("root: " + root);
if (pattern.startsWith(root.toString()))
{
String pat = "glob:" + pattern;
StartLog.debug("Using absolute path pattern: " + pat);
return fs.getPathMatcher(pat);
}
}
// Doesn't start with filesystem root, then assume the pattern
// is a relative file path pattern.
String pat = "glob:**/" + pattern;
StartLog.debug("Using relative path pattern: " + pat);
return fs.getPathMatcher(pat);
}
public static PathMatcher getNonHidden()
{
return new NonHiddenMatcher();
}
/**
* Provide the non-glob / non-regex prefix on the pattern as a Path reference.
*
* @param pattern
* the pattern to test
* @return the Path representing the search root for the pattern provided.
*/
public static Path getSearchRoot(final String pattern)
{
Path path = asPath(pattern);
Path test = path.getRoot();
boolean isSyntaxed = pattern.startsWith("glob:") || pattern.startsWith("regex:");
int len = path.getNameCount();
for (int i = 0; i < len; i++)
{
Path part = path.getName(i);
if (isGlob(part.toString(),isSyntaxed))
{
// found a glob part, return prior parts now
break;
}
// is this the last entry?
if (i == (len - 1))
{
// always return prior entries
break;
}
if (test == null)
{
test = part;
}
else
{
test = test.resolve(part);
}
}
if (test == null)
{
return EMPTY_PATH;
}
return test;
}
/**
* Tests if provided pattern is an absolute reference (or not)
*
* @param pattern
* the pattern to test
* @return true if pattern is an absolute reference.
*/
public static boolean isAbsolute(final String pattern)
{
return asPath(pattern).isAbsolute();
}
/**
* Determine if part is a glob pattern.
*
* @param part
* the string to check
* @param syntaxed
* true if overall pattern is syntaxed with <code>"glob:"</code> or <code>"regex:"</code>
* @return true if part has glob characters
*/
private static boolean isGlob(String part, boolean syntaxed)
{
int len = part.length();
for (int i = 0; i < len; i++)
{
char c = part.charAt(i);
for (char g : GLOB_CHARS)
{
if (c == g)
{
return true;
}
}
if (syntaxed)
{
for (char g : SYNTAXED_GLOB_CHARS)
{
if (c == g)
{
return true;
}
}
}
}
return false;
}
}

View File

@ -21,9 +21,9 @@ package org.eclipse.jetty.start;
import static org.eclipse.jetty.start.UsageException.*;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -325,66 +325,10 @@ public class StartArgs
StartLog.debug("rawlibref = " + rawlibref);
String libref = properties.expand(rawlibref);
StartLog.debug("expanded = " + libref);
if (libref.startsWith("regex:"))
for (Path libpath : baseHome.getPaths(libref))
{
String regex = libref.substring("regex:".length());
for (File libfile : baseHome.listFilesRegex(regex))
{
classpath.addComponent(libfile);
}
continue;
}
libref = FS.separators(libref);
// Any globs here?
if (libref.contains("*"))
{
// Glob Reference
int idx = libref.lastIndexOf(File.separatorChar);
String relativePath = "/";
String filenameRef = libref;
if (idx >= 0)
{
relativePath = libref.substring(0,idx);
filenameRef = libref.substring(idx + 1);
}
StringBuilder regex = new StringBuilder();
regex.append('^');
for (char c : filenameRef.toCharArray())
{
switch (c)
{
case '*':
regex.append(".*");
break;
case '.':
regex.append("\\.");
break;
default:
regex.append(c);
}
}
regex.append('$');
StartLog.debug("regex = " + regex);
FileFilter filter = new FS.FilenameRegexFilter(regex.toString());
List<File> libs = baseHome.listFiles(relativePath,filter);
StartLog.debug("found " + libs.size() + " libs");
for (File libfile : libs)
{
classpath.addComponent(libfile);
}
}
else
{
// Straight Reference
File libfile = baseHome.getFile(libref);
classpath.addComponent(libfile);
classpath.addComponent(libpath.toFile());
}
}

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.start;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Path;
/**
* Simple Start .INI handler
@ -32,6 +33,11 @@ public class StartIni extends TextFile
super(file);
}
public StartIni(Path path) throws FileNotFoundException, IOException
{
this(path.toFile());
}
@Override
public void addUniqueLine(String line)
{

View File

@ -22,6 +22,7 @@ import static org.hamcrest.Matchers.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@ -32,7 +33,55 @@ import org.junit.Test;
public class BaseHomeTest
{
private void assertFileList(BaseHome hb, String message, List<String> expected, List<File> files)
public static void assertPathList(BaseHome hb, String message, List<String> expected, PathFinder finder)
{
List<String> actual = new ArrayList<>();
for (Path path : finder.getHits())
{
actual.add(hb.toShortForm(path.toFile()));
}
if (actual.size() != expected.size())
{
System.out.printf("Actual Path(s): %,d hits%n",actual.size());
for (String path : actual)
{
System.out.printf(" %s%n",path);
}
System.out.printf("Expected Path(s): %,d entries%n",expected.size());
for (String path : expected)
{
System.out.printf(" %s%n",path);
}
}
Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));
}
public static void assertPathList(BaseHome hb, String message, List<String> expected, List<Path> paths)
{
List<String> actual = new ArrayList<>();
for (Path path : paths)
{
actual.add(hb.toShortForm(path.toFile()));
}
if (actual.size() != expected.size())
{
System.out.printf("Actual Path(s): %,d hits%n",actual.size());
for (String path : actual)
{
System.out.printf(" %s%n",path);
}
System.out.printf("Expected Path(s): %,d entries%n",expected.size());
for (String path : expected)
{
System.out.printf(" %s%n",path);
}
}
Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));
}
public static void assertFileList(BaseHome hb, String message, List<String> expected, List<File> files)
{
List<String> actual = new ArrayList<>();
for (File file : files)
@ -42,15 +91,6 @@ public class BaseHomeTest
Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));
}
private void toOsSeparators(List<String> expected)
{
for (int i = 0; i < expected.size(); i++)
{
String fixed = FS.separators(expected.get(i));
expected.set(i,fixed);
}
}
@Test
public void testGetFile_OnlyHome() throws IOException
{
@ -68,13 +108,13 @@ public class BaseHomeTest
}
@Test
public void testListFiles_OnlyHome() throws IOException
public void testGetPaths_OnlyHome() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
File baseDir = null;
BaseHome hb = new BaseHome(homeDir,baseDir);
List<File> files = hb.listFiles("/start.d");
List<Path> paths = hb.getPaths("start.d/*");
List<String> expected = new ArrayList<>();
expected.add("${jetty.home}/start.d/jmx.ini");
@ -82,19 +122,19 @@ public class BaseHomeTest
expected.add("${jetty.home}/start.d/jsp.ini");
expected.add("${jetty.home}/start.d/logging.ini");
expected.add("${jetty.home}/start.d/ssl.ini");
toOsSeparators(expected);
FSTest.toOsSeparators(expected);
assertFileList(hb,"Files found",expected,files);
assertPathList(hb,"Paths found",expected,paths);
}
@Test
public void testListFiles_Filtered_OnlyHome() throws IOException
public void testGetPaths_OnlyHome_InisOnly() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
File baseDir = null;
BaseHome hb = new BaseHome(homeDir,baseDir);
List<File> files = hb.listFiles("/start.d",new FS.IniFilter());
List<Path> paths = hb.getPaths("start.d/*.ini");
List<String> expected = new ArrayList<>();
expected.add("${jetty.home}/start.d/jmx.ini");
@ -102,19 +142,19 @@ public class BaseHomeTest
expected.add("${jetty.home}/start.d/jsp.ini");
expected.add("${jetty.home}/start.d/logging.ini");
expected.add("${jetty.home}/start.d/ssl.ini");
toOsSeparators(expected);
FSTest.toOsSeparators(expected);
assertFileList(hb,"Files found",expected,files);
assertPathList(hb,"Paths found",expected,paths);
}
@Test
public void testListFiles_Both() throws IOException
public void testGetPaths_Both() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
File baseDir = MavenTestingUtils.getTestResourceDir("hb.1/base");
BaseHome hb = new BaseHome(homeDir,baseDir);
List<File> files = hb.listFiles("/start.d");
List<Path> paths = hb.getPaths("start.d/*.ini");
List<String> expected = new ArrayList<>();
expected.add("${jetty.base}/start.d/jmx.ini");
@ -123,9 +163,9 @@ public class BaseHomeTest
expected.add("${jetty.base}/start.d/logging.ini");
expected.add("${jetty.home}/start.d/ssl.ini");
expected.add("${jetty.base}/start.d/myapp.ini");
toOsSeparators(expected);
FSTest.toOsSeparators(expected);
assertFileList(hb,"Files found",expected,files);
assertPathList(hb,"Paths found",expected,paths);
}
@Test

View File

@ -0,0 +1,62 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
import java.io.File;
import java.util.List;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.Assert;
import org.junit.Test;
public class FSTest
{
@Test
public void testCanReadDirectory()
{
File targetDir = MavenTestingUtils.getTargetDir();
Assert.assertTrue("Can read dir: " + targetDir,FS.canReadDirectory(targetDir));
}
@Test
public void testCanReadDirectory_NotDir()
{
File bogusFile = MavenTestingUtils.getTestResourceFile("bogus.xml");
Assert.assertFalse("Can read dir: " + bogusFile,FS.canReadDirectory(bogusFile));
}
@Test
public void testCanReadFile()
{
File pom = MavenTestingUtils.getProjectFile("pom.xml");
Assert.assertTrue("Can read file: " + pom,FS.canReadFile(pom));
}
/**
* Utility method used by other test cases
*/
public static void toOsSeparators(List<String> expected)
{
for (int i = 0; i < expected.size(); i++)
{
String fixed = FS.separators(expected.get(i));
expected.set(i,fixed);
}
}
}

View File

@ -98,7 +98,7 @@ public class MainTest
List<String> cmdLineArgs = new ArrayList<>();
addUseCasesHome(cmdLineArgs);
// JVM args
cmdLineArgs.add("--exec");
cmdLineArgs.add("-Xms1024m");

View File

@ -35,7 +35,7 @@ public class ModulesTest
{
private final static List<String> TEST_SOURCE = Collections.singletonList("<test>");
private StartArgs DEFAULT_ARGS = new StartArgs(new String[] { "jetty.version=TEST" }).parseCommandLine();
@Test
public void testLoadAllModules() throws IOException
{
@ -43,10 +43,26 @@ public class ModulesTest
BaseHome basehome = new BaseHome(homeDir,homeDir);
Modules modules = new Modules();
modules.registerAll(basehome, DEFAULT_ARGS);
Assert.assertThat("Module count",modules.count(),is(30));
modules.registerAll(basehome,DEFAULT_ARGS);
List<String> moduleNames = new ArrayList<>();
for (Module mod : modules)
{
// skip npn-boot in this test (as its behavior is jdk specific)
if (mod.getName().equals("npn-boot"))
{
continue;
}
moduleNames.add(mod.getName());
}
String expected[] = { "jmx", "client", "stats", "spdy", "deploy", "debug", "security", "npn", "ext", "websocket", "rewrite", "ipaccess", "xinetd",
"proxy", "webapp", "jndi", "lowresources", "https", "plus", "requestlog", "jsp", "monitor", "xml", "servlet", "jaas", "http", "base", "server",
"annotations" };
Assert.assertThat("Module count: " + moduleNames,moduleNames.size(),is(expected.length));
}
@Test
public void testEnableRegexSimple() throws IOException
{
@ -54,11 +70,11 @@ public class ModulesTest
BaseHome basehome = new BaseHome(homeDir,homeDir);
Modules modules = new Modules();
modules.registerAll(basehome, DEFAULT_ARGS);
modules.registerAll(basehome,DEFAULT_ARGS);
modules.enable("[sj]{1}.*",TEST_SOURCE);
String expected[] = { "jmx", "stats", "spdy", "security", "jndi", "jsp", "servlet", "jaas", "server" };
Assert.assertThat("Enabled Module count",modules.resolveEnabled().size(),is(expected.length));
}
@ -70,7 +86,7 @@ public class ModulesTest
// Register modules
Modules modules = new Modules();
modules.registerAll(basehome, DEFAULT_ARGS);
modules.registerAll(basehome,DEFAULT_ARGS);
modules.buildGraph();
// Enable 2 modules
@ -108,12 +124,12 @@ public class ModulesTest
List<String> actualLibs = modules.normalizeLibs(active);
Assert.assertThat("Resolved Libs: " + actualLibs,actualLibs,contains(expectedLibs.toArray()));
// Assert XML List
List<String> expectedXmls = new ArrayList<>();
expectedXmls.add("etc/jetty.xml");
expectedXmls.add("etc/jetty-http.xml");
List<String> actualXmls = modules.normalizeXmls(active);
Assert.assertThat("Resolved XMLs: " + actualXmls,actualXmls,contains(expectedXmls.toArray()));
}
@ -126,7 +142,7 @@ public class ModulesTest
// Register modules
Modules modules = new Modules();
modules.registerAll(basehome, DEFAULT_ARGS);
modules.registerAll(basehome,DEFAULT_ARGS);
modules.buildGraph();
// modules.dump();
@ -136,7 +152,7 @@ public class ModulesTest
// Collect active module list
List<Module> active = modules.resolveEnabled();
// Assert names are correct, and in the right order
List<String> expectedNames = new ArrayList<>();
expectedNames.add("base");
@ -174,10 +190,10 @@ public class ModulesTest
expectedLibs.add("lib/jetty-annotations-${jetty.version}.jar");
expectedLibs.add("lib/annotations/*.jar");
expectedLibs.add("lib/websocket/*.jar");
List<String> actualLibs = modules.normalizeLibs(active);
Assert.assertThat("Resolved Libs: " + actualLibs,actualLibs,contains(expectedLibs.toArray()));
// Assert XML List
List<String> expectedXmls = new ArrayList<>();
expectedXmls.add("etc/jetty.xml");
@ -185,7 +201,7 @@ public class ModulesTest
expectedXmls.add("etc/jetty-plus.xml");
expectedXmls.add("etc/jetty-annotations.xml");
expectedXmls.add("etc/jetty-websockets.xml");
List<String> actualXmls = modules.normalizeXmls(active);
Assert.assertThat("Resolved XMLs: " + actualXmls,actualXmls,contains(expectedXmls.toArray()));
}

View File

@ -0,0 +1,87 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.Test;
public class PathFinderTest
{
@Test
public void testFindInis() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
Path homePath = homeDir.toPath();
PathFinder finder = new PathFinder();
finder.setFileMatcher("glob:**/*.ini");
finder.setBase(homePath);
Files.walkFileTree(homePath,EnumSet.of(FileVisitOption.FOLLOW_LINKS),30,finder);
List<String> expected = new ArrayList<>();
expected.add("${jetty.home}/start.d/jmx.ini");
expected.add("${jetty.home}/start.d/jndi.ini");
expected.add("${jetty.home}/start.d/jsp.ini");
expected.add("${jetty.home}/start.d/logging.ini");
expected.add("${jetty.home}/start.d/ssl.ini");
expected.add("${jetty.home}/start.ini");
FSTest.toOsSeparators(expected);
BaseHome hb = new BaseHome(homeDir,null);
BaseHomeTest.assertPathList(hb,"Files found",expected,finder);
}
@Test
public void testFindMods() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
List<String> expected = new ArrayList<>();
File modulesDir = new File(homeDir,"modules");
for (File file : modulesDir.listFiles())
{
if (file.getName().endsWith(".mod"))
{
expected.add("${jetty.home}/modules/" + file.getName());
}
}
FSTest.toOsSeparators(expected);
Path modulesPath = modulesDir.toPath();
PathFinder finder = new PathFinder();
finder.setFileMatcher(PathMatchers.getMatcher("modules/*.mod"));
finder.setBase(modulesPath);
Files.walkFileTree(modulesPath,EnumSet.of(FileVisitOption.FOLLOW_LINKS),1,finder);
BaseHome hb = new BaseHome(homeDir,null);
BaseHomeTest.assertPathList(hb,"Files found",expected,finder);
}
}

View File

@ -0,0 +1,105 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
import static org.hamcrest.Matchers.*;
import java.nio.file.Path;
import org.eclipse.jetty.toolchain.test.OS;
import org.junit.Assert;
import org.junit.Test;
public class PathMatchersTest
{
private void assertIsAbsolute(String pattern, boolean expected)
{
Assert.assertThat("isAbsolute(\"" + pattern + "\")",PathMatchers.isAbsolute(pattern),is(expected));
}
@Test
public void testIsAbsolute()
{
if (OS.IS_UNIX)
{
assertIsAbsolute("/opt/app",true);
assertIsAbsolute("/opt/florb",true);
assertIsAbsolute("/home/user/benfranklin",true);
assertIsAbsolute("glob:/home/user/benfranklin/*.jar",true);
assertIsAbsolute("glob:/**/*.jar",true);
assertIsAbsolute("regex:/*-[^dev].ini",true);
}
if (OS.IS_WINDOWS)
{
assertIsAbsolute("C:\\\\System32",true);
assertIsAbsolute("C:\\\\Program Files",true);
}
}
@Test
public void testIsNotAbsolute()
{
assertIsAbsolute("etc",false);
assertIsAbsolute("lib",false);
assertIsAbsolute("${user.dir}",false);
assertIsAbsolute("**/*.jar",false);
assertIsAbsolute("glob:*.ini",false);
assertIsAbsolute("regex:*-[^dev].ini",false);
}
private void assertSearchRoot(String pattern, String expectedSearchRoot)
{
Path actual = PathMatchers.getSearchRoot(pattern);
String expectedNormal = FS.separators(expectedSearchRoot);
Assert.assertThat(".getSearchRoot(\"" + pattern + "\")",actual.toString(),is(expectedNormal));
}
@Test
public void testGetSearchRoot()
{
if (OS.IS_UNIX)
{
// absolute first
assertSearchRoot("/opt/app/*.jar","/opt/app");
assertSearchRoot("/lib/jvm/**/jre/lib/*.jar","/lib/jvm");
assertSearchRoot("glob:/var/lib/*.xml","/var/lib");
assertSearchRoot("glob:/var/lib/*.{xml,java}","/var/lib");
assertSearchRoot("glob:/opt/corporate/lib-{dev,prod}/*.ini","/opt/corporate");
assertSearchRoot("regex:/opt/jetty/.*/lib-(dev|prod)/*.ini","/opt/jetty");
assertSearchRoot("/*.ini","/");
assertSearchRoot("/etc/jetty.conf","/etc");
assertSearchRoot("/common.conf","/");
}
if (OS.IS_WINDOWS)
{
// absolute patterns (complete with required windows slash escaping)
assertSearchRoot("C:\\\\corp\\\\lib\\\\*.jar","C:\\corp\\lib");
assertSearchRoot("D:\\\\lib\\\\**\\\\jre\\\\lib\\\\*.jar","C:\\lib");
}
// some relative paths
assertSearchRoot("lib/*.jar","lib");
assertSearchRoot("etc/jetty.xml","etc");
assertSearchRoot("start.ini",".");
assertSearchRoot("start.d/",".");
}
}

View File

@ -76,7 +76,6 @@ public class TestUseCases
@Test
public void testWithSpdyBadNpnVersion() throws Exception
{
//StartLog.enableDebug();
assertUseCase("home","base.enable.spdy.bad.npn.version","assert-enable-spdy-bad-npn-version.txt","java.version=1.7.0_01");
}

View File

@ -3,7 +3,7 @@
#
[lib]
regex:lib/ext/.*\.jar$
lib/ext/**.jar
[files]
lib/