1 /* 2 * Copyright (C) 2007-2010 Júlio Vilmar Gesser. 3 * Copyright (C) 2011, 2013-2018 The JavaParser Team. 4 * 5 * This file is part of JavaParser. 6 * 7 * JavaParser can be used either under the terms of 8 * a) the GNU Lesser General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * b) the terms of the Apache License 12 * 13 * You should have received a copy of both licenses in LICENCE.LGPL and 14 * LICENCE.APACHE. Please refer to those files for details. 15 * 16 * JavaParser is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU Lesser General Public License for more details. 20 */ 21 22 package com.github.javaparser.symbolsolver.utils; 23 24 import com.github.javaparser.JavaParser; 25 import com.github.javaparser.ParseProblemException; 26 import com.github.javaparser.ast.CompilationUnit; 27 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 28 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; 29 import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver; 30 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; 31 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; 32 import com.github.javaparser.utils.Log; 33 34 import java.io.FileNotFoundException; 35 import java.io.IOException; 36 import java.nio.file.*; 37 import java.nio.file.attribute.BasicFileAttributes; 38 import java.util.HashSet; 39 import java.util.Optional; 40 import java.util.Set; 41 42 import static com.github.javaparser.utils.Utils.assertNotNull; 43 import static java.nio.file.FileVisitResult.*; 44 45 /** 46 * Utility class to add all jars and roots of java files of the provided path to a TypeSolver instance. 47 * It traverses the file directory tree and adds all files ending in either .java or .jar. 48 */ 49 public class SymbolSolverQuickSetup { 50 51 public interface DirFilter { filter(Path path)52 boolean filter(Path path); 53 } 54 55 private final Path root; 56 private CombinedTypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(false)); 57 private DirFilter dirFilter = path -> false; 58 SymbolSolverQuickSetup(Path root)59 public SymbolSolverQuickSetup(Path root) { 60 assertNotNull(root); 61 if (!Files.isDirectory(root)) { 62 throw new IllegalArgumentException("Only directories are allowed as root path!"); 63 } 64 this.root = root.normalize(); 65 Log.info("New symbol source root at \"%s\"", this.root); 66 } 67 SymbolSolverQuickSetup(Path root, DirFilter dirFilter)68 public SymbolSolverQuickSetup(Path root, DirFilter dirFilter) { 69 this(root); 70 this.dirFilter = dirFilter; 71 } 72 walk()73 public TypeSolver walk() throws IOException { 74 Files.walkFileTree(root, new JavaSymbolSolverWalker()); 75 Files.walkFileTree(root, new JarVisitor()); 76 return typeSolver; 77 } 78 tryToWalk()79 public Optional<TypeSolver> tryToWalk() { 80 try { 81 return Optional.of(walk()); 82 } catch (IOException e) { 83 Log.error(e, "Unable to walk root " + root); 84 return Optional.empty(); 85 } 86 } 87 getTypeSolver()88 public TypeSolver getTypeSolver() { 89 return typeSolver; 90 } 91 92 /** 93 * The path that was passed in the constructor. 94 */ getRoot()95 public Path getRoot() { 96 return root; 97 } 98 99 /** 100 * Walks the directory and adds the roots of the java files to the TypeSolver 101 */ 102 private class JavaSymbolSolverWalker extends SimpleFileVisitor<Path> { 103 104 private final Set<Path> roots = new HashSet<>(); 105 106 @Override visitFile(Path file, BasicFileAttributes attr)107 public FileVisitResult visitFile(Path file, BasicFileAttributes attr) throws FileNotFoundException { 108 if (attr.isRegularFile()) { 109 PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**.java"); 110 if (matcher.matches(file)) { 111 try { 112 Optional<Path> root = JavaParser.parse(file.toFile()).getStorage() 113 .map(CompilationUnit.Storage::getSourceRoot); 114 if (root.isPresent()) { 115 typeSolver.add(new JavaParserTypeSolver(root.get().toFile())); 116 if (roots.add(root.get())) { 117 Log.trace("Added dir " + root.get() + " to the TypeSolver"); 118 return SKIP_SIBLINGS; 119 } 120 } 121 } catch (ParseProblemException e) { 122 Log.error(e, "Unable to parse file " + file); 123 } 124 } 125 } 126 return CONTINUE; 127 } 128 129 @Override preVisitDirectory(Path dir, BasicFileAttributes attrs)130 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { 131 if (Files.isHidden(dir) || dirFilter.filter(dir) || roots.stream().anyMatch(dir::startsWith)) { 132 return SKIP_SUBTREE; 133 } 134 return CONTINUE; 135 } 136 } 137 138 private class JarVisitor extends SimpleFileVisitor<Path> { 139 140 @Override visitFile(Path file, BasicFileAttributes attr)141 public FileVisitResult visitFile(Path file, BasicFileAttributes attr) throws IOException { 142 if (attr.isRegularFile()) { 143 PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**.jar"); 144 if (matcher.matches(file)) { 145 typeSolver.add(new JarTypeSolver(file.toString())); 146 } 147 } 148 return CONTINUE; 149 } 150 } 151 } 152 153