View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.start;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.nio.file.FileSystemLoopException;
24  import java.nio.file.FileVisitResult;
25  import java.nio.file.Path;
26  import java.nio.file.PathMatcher;
27  import java.nio.file.SimpleFileVisitor;
28  import java.nio.file.attribute.BasicFileAttributes;
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.HashMap;
32  import java.util.HashSet;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Set;
36  
37  public class PathFinder extends SimpleFileVisitor<Path>
38  {
39      // internal tracking of prior notified paths (to avoid repeated notification of same ignored path)
40      private static Set<Path> NOTIFIED_PATHS = new HashSet<>();
41  
42      private boolean includeDirsInResults = false;
43      private Map<String, Path> hits = new HashMap<>();
44      private Path basePath = null;
45      private PathMatcher dirMatcher = PathMatchers.getNonHidden();
46      private PathMatcher fileMatcher = PathMatchers.getNonHidden();
47  
48      private void addHit(Path path)
49      {
50          String relPath = basePath.relativize(path).toString();
51          StartLog.debug("Found [" + relPath + "]  " + path);
52          hits.put(relPath,path);
53      }
54  
55      public PathMatcher getDirMatcher()
56      {
57          return dirMatcher;
58      }
59  
60      public PathMatcher getFileMatcher()
61      {
62          return fileMatcher;
63      }
64  
65      public List<File> getHitList()
66      {
67          List<File> ret = new ArrayList<>();
68          for (Path path : hits.values())
69          {
70              ret.add(path.toFile());
71          }
72          return ret;
73      }
74  
75      public Collection<Path> getHits()
76      {
77          return hits.values();
78      }
79  
80      public boolean isIncludeDirsInResults()
81      {
82          return includeDirsInResults;
83      }
84  
85      @Override
86      public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
87      {
88          if (dirMatcher.matches(dir))
89          {
90              StartLog.trace("Following dir: " + dir);
91              if (includeDirsInResults && fileMatcher.matches(dir))
92              {
93                  addHit(dir);
94              }
95              return FileVisitResult.CONTINUE;
96          }
97          else
98          {
99              StartLog.trace("Skipping dir: " + dir);
100             return FileVisitResult.SKIP_SUBTREE;
101         }
102     }
103 
104     /**
105      * Set the active basePath, used for resolving relative paths.
106      * <p>
107      * 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.
108      * 
109      * @param basePath
110      *            the basePath to tag all hits with
111      */
112     public void setBase(Path basePath)
113     {
114         this.basePath = basePath;
115     }
116 
117     public void setDirMatcher(PathMatcher dirMatcher)
118     {
119         this.dirMatcher = dirMatcher;
120     }
121 
122     public void setFileMatcher(PathMatcher fileMatcher)
123     {
124         this.fileMatcher = fileMatcher;
125     }
126 
127     public void setFileMatcher(String pattern)
128     {
129         this.fileMatcher = PathMatchers.getMatcher(pattern);
130     }
131 
132     public void setIncludeDirsInResults(boolean includeDirsInResults)
133     {
134         this.includeDirsInResults = includeDirsInResults;
135     }
136 
137     @Override
138     public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
139     {
140         if (fileMatcher.matches(file))
141         {
142             addHit(file);
143         }
144         else
145         {
146             StartLog.trace("Ignoring file: " + file);
147         }
148         return FileVisitResult.CONTINUE;
149     }
150 
151     @Override
152     public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException
153     {
154         if (exc instanceof FileSystemLoopException)
155         {
156             if (!NOTIFIED_PATHS.contains(file))
157             {
158                 StartLog.warn("skipping detected filesystem loop: " + file);
159                 NOTIFIED_PATHS.add(file);
160             }
161             return FileVisitResult.SKIP_SUBTREE;
162         }
163         else
164         {
165             StartLog.warn(exc);
166             return super.visitFileFailed(file,exc);
167         }
168     }
169 }