View Javadoc
1   /*
2    * Copyright (c) 2006 JMockit developers
3    * This file is subject to the terms of the MIT license (see LICENSE.txt).
4    */
5   package mockit.coverage.reporting.sourceFiles;
6   
7   import edu.umd.cs.findbugs.annotations.NonNull;
8   import edu.umd.cs.findbugs.annotations.Nullable;
9   
10  import java.io.BufferedReader;
11  import java.io.File;
12  import java.io.FileFilter;
13  import java.io.IOException;
14  import java.nio.charset.StandardCharsets;
15  import java.nio.file.Files;
16  import java.nio.file.Path;
17  import java.util.List;
18  
19  import org.checkerframework.checker.index.qual.NonNegative;
20  
21  public final class InputFile {
22      @NonNull
23      final String filePath;
24      @NonNull
25      private final File sourceFile;
26      @NonNull
27      private final BufferedReader input;
28  
29      @Nullable
30      public static InputFile createIfFileExists(@NonNull List<File> sourceDirs, @NonNull String filePath)
31              throws IOException {
32          File sourceFile = findSourceFile(sourceDirs, filePath);
33          return sourceFile == null ? null : new InputFile(filePath, sourceFile);
34      }
35  
36      @Nullable
37      private static File findSourceFile(@NonNull List<File> sourceDirs, @NonNull String filePath) {
38          int p = filePath.indexOf('/');
39          String topLevelPackage = p < 0 ? "" : filePath.substring(0, p);
40          int n = sourceDirs.size();
41  
42          for (int i = 0; i < n; i++) {
43              File sourceDir = sourceDirs.get(i);
44              File sourceFile = getSourceFile(sourceDir, topLevelPackage, filePath);
45  
46              if (sourceFile != null) {
47                  giveCurrentSourceDirHighestPriority(sourceDirs, i);
48                  addRootSourceDirIfNew(sourceDirs, filePath, sourceFile);
49                  return sourceFile;
50              }
51          }
52  
53          return null;
54      }
55  
56      @Nullable
57      private static File getSourceFile(@NonNull File sourceDir, @NonNull final String topLevelPackage,
58              @NonNull String filePath) {
59          File file = sourceDir.toPath().resolve(filePath).toFile();
60  
61          if (file.exists()) {
62              return file;
63          }
64  
65          File[] subDirs = sourceDir.listFiles((FileFilter) subDir -> subDir.isDirectory() && !subDir.isHidden()
66                  && !subDir.getName().equals(topLevelPackage));
67  
68          if (subDirs != null && subDirs.length > 0) {
69              for (File subDir : subDirs) {
70                  File sourceFile = getSourceFile(subDir, topLevelPackage, filePath);
71  
72                  if (sourceFile != null) {
73                      return sourceFile;
74                  }
75              }
76          }
77  
78          return null;
79      }
80  
81      private static void giveCurrentSourceDirHighestPriority(@NonNull List<File> sourceDirs,
82              @NonNegative int currentSourceDirIndex) {
83          if (currentSourceDirIndex > 0) {
84              File firstSourceDir = sourceDirs.get(0);
85              File currentSourceDir = sourceDirs.get(currentSourceDirIndex);
86  
87              if (!firstSourceDir.getPath().startsWith(currentSourceDir.getPath())) {
88                  sourceDirs.set(currentSourceDirIndex, firstSourceDir);
89                  sourceDirs.set(0, currentSourceDir);
90              }
91          }
92      }
93  
94      private static void addRootSourceDirIfNew(@NonNull List<File> sourceDirs, @NonNull String filePath,
95              @NonNull File sourceFile) {
96          String sourceFilePath = sourceFile.getPath();
97          String sourceRootDir = sourceFilePath.substring(0, sourceFilePath.length() - filePath.length());
98          File newSourceDir = Path.of(sourceRootDir).toFile();
99  
100         if (!sourceDirs.contains(newSourceDir)) {
101             sourceDirs.add(0, newSourceDir);
102         }
103     }
104 
105     private InputFile(@NonNull String filePath, @NonNull File sourceFile) throws IOException {
106         this.filePath = filePath;
107         this.sourceFile = sourceFile;
108         input = Files.newBufferedReader(sourceFile.toPath(), StandardCharsets.UTF_8);
109     }
110 
111     @NonNull
112     String getSourceFileName() {
113         return sourceFile.getName();
114     }
115 
116     @NonNull
117     String getSourceFilePath() {
118         String path = sourceFile.getPath();
119         return path.startsWith("..") ? path.substring(3) : path;
120     }
121 
122     @Nullable
123     String nextLine() throws IOException {
124         return input.readLine();
125     }
126 
127     void close() throws IOException {
128         input.close();
129     }
130 }