View Javadoc
1   package org.codehaus.plexus.compiler;
2   
3   /**
4    * The MIT License
5    *
6    * Copyright (c) 2005, The Codehaus
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   */
26  import java.io.File;
27  import java.io.IOException;
28  import java.util.Collections;
29  import java.util.List;
30  import java.util.Set;
31  import java.util.TreeSet;
32  
33  import org.codehaus.plexus.util.DirectoryScanner;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  /**
38   * @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
39   * @author <a href="mailto:michal.maczka@dimatics.com">Michal Maczka </a>
40   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
41   */
42  public abstract class AbstractCompiler implements Compiler {
43      private final Logger log = LoggerFactory.getLogger(getClass());
44  
45      private final org.codehaus.plexus.logging.Logger plexusLogger;
46  
47      protected static final String EOL = System.lineSeparator();
48  
49      protected static final String PS = System.getProperty("path.separator");
50  
51      private final CompilerOutputStyle compilerOutputStyle;
52  
53      private final String inputFileEnding;
54  
55      private final String outputFileEnding;
56  
57      private final String outputFile;
58  
59      // ----------------------------------------------------------------------
60      //
61      // ----------------------------------------------------------------------
62  
63      protected AbstractCompiler(
64              CompilerOutputStyle compilerOutputStyle,
65              String inputFileEnding,
66              String outputFileEnding,
67              String outputFile) {
68          this.compilerOutputStyle = compilerOutputStyle;
69  
70          this.inputFileEnding = inputFileEnding;
71  
72          this.outputFileEnding = outputFileEnding;
73  
74          this.outputFile = outputFile;
75  
76          this.plexusLogger = new PlexusLoggerWrapper(log);
77      }
78  
79      /**
80       *
81       * @return a Logger
82       */
83      protected Logger getLog() {
84          return log;
85      }
86  
87      /**
88       * @return a plexus Logger
89       * @deprecated please use {@link #getLog()}
90       */
91      @Deprecated
92      protected org.codehaus.plexus.logging.Logger getLogger() {
93          return plexusLogger;
94      }
95  
96      // ----------------------------------------------------------------------
97      //
98      // ----------------------------------------------------------------------
99  
100     public abstract String getCompilerId();
101 
102     @Override
103     public CompilerResult performCompile(CompilerConfiguration configuration) throws CompilerException {
104         throw new CompilerNotImplementedException("The performCompile method has not been implemented.");
105     }
106 
107     @Override
108     public CompilerOutputStyle getCompilerOutputStyle() {
109         return compilerOutputStyle;
110     }
111 
112     @Override
113     public String getInputFileEnding(CompilerConfiguration configuration) throws CompilerException {
114         return inputFileEnding;
115     }
116 
117     @Override
118     public String getOutputFileEnding(CompilerConfiguration configuration) throws CompilerException {
119         if (compilerOutputStyle != CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE) {
120             throw new RuntimeException("This compiler implementation doesn't have one output file per input file.");
121         }
122 
123         return outputFileEnding;
124     }
125 
126     @Override
127     public String getOutputFile(CompilerConfiguration configuration) throws CompilerException {
128         if (compilerOutputStyle != CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES) {
129             throw new RuntimeException("This compiler implementation doesn't have one output file for all files.");
130         }
131 
132         return outputFile;
133     }
134 
135     @Override
136     public boolean canUpdateTarget(CompilerConfiguration configuration) throws CompilerException {
137         return true;
138     }
139 
140     // ----------------------------------------------------------------------
141     // Utility Methods
142     // ----------------------------------------------------------------------
143 
144     public static String getPathString(List<String> pathElements) {
145         StringBuilder sb = new StringBuilder();
146 
147         for (String pathElement : pathElements) {
148             sb.append(pathElement).append(File.pathSeparator);
149         }
150 
151         return sb.toString();
152     }
153 
154     protected static Set<String> getSourceFilesForSourceRoot(CompilerConfiguration config, String sourceLocation) {
155 
156         DirectoryScanner scanner = new DirectoryScanner();
157         scanner.setBasedir(sourceLocation);
158 
159         if (!scanner.getBasedir().exists()) {
160             return Collections.emptySet();
161         }
162 
163         Set<String> includes = config.getIncludes();
164 
165         if (includes != null && !includes.isEmpty()) {
166             String[] inclStrs = includes.toArray(new String[0]);
167             scanner.setIncludes(inclStrs);
168         } else {
169             scanner.setIncludes(new String[] {"**/*.java"});
170         }
171 
172         Set<String> excludes = config.getExcludes();
173 
174         if (excludes != null && !excludes.isEmpty()) {
175             String[] exclStrs = excludes.toArray(new String[0]);
176             scanner.setExcludes(exclStrs);
177         }
178 
179         scanner.scan();
180 
181         String[] sourceDirectorySources = scanner.getIncludedFiles();
182 
183         Set<String> sources = new TreeSet<>();
184 
185         for (String sourceDirectorySource : sourceDirectorySources) {
186             File f = new File(sourceLocation, sourceDirectorySource);
187 
188             sources.add(f.getPath());
189         }
190 
191         return sources;
192     }
193 
194     protected static String[] getSourceFiles(CompilerConfiguration config) {
195         Set<String> sources = new TreeSet<>();
196 
197         Set<File> sourceFiles = config.getSourceFiles();
198 
199         if (sourceFiles != null && !sourceFiles.isEmpty()) {
200             for (File sourceFile : sourceFiles) {
201                 sources.add(sourceFile.getAbsolutePath());
202             }
203         } else {
204             for (String sourceLocation : config.getSourceLocations()) {
205                 sources.addAll(getSourceFilesForSourceRoot(config, sourceLocation));
206             }
207         }
208 
209         String[] result;
210 
211         if (sources.isEmpty()) {
212             result = new String[0];
213         } else {
214             result = sources.toArray(new String[0]);
215         }
216 
217         return result;
218     }
219 
220     protected static String makeClassName(String fileName, String sourceDir) throws CompilerException {
221         File origFile = new File(fileName);
222 
223         String canonical = null;
224 
225         if (origFile.exists()) {
226             canonical = getCanonicalPath(origFile).replace('\\', '/');
227         }
228 
229         if (sourceDir != null) {
230             String prefix = getCanonicalPath(new File(sourceDir)).replace('\\', '/');
231 
232             if (canonical != null) {
233                 if (canonical.startsWith(prefix)) {
234                     String result = canonical.substring(prefix.length() + 1, canonical.length() - 5);
235 
236                     result = result.replace('/', '.');
237 
238                     return result;
239                 }
240             } else {
241                 File t = new File(sourceDir, fileName);
242 
243                 if (t.exists()) {
244                     String str = getCanonicalPath(t).replace('\\', '/');
245 
246                     return str.substring(prefix.length() + 1, str.length() - 5).replace('/', '.');
247                 }
248             }
249         }
250 
251         if (fileName.endsWith(".java")) {
252             fileName = fileName.substring(0, fileName.length() - 5);
253         }
254 
255         fileName = fileName.replace('\\', '.');
256 
257         return fileName.replace('/', '.');
258     }
259 
260     private static String getCanonicalPath(File origFile) throws CompilerException {
261         try {
262             return origFile.getCanonicalPath();
263         } catch (IOException e) {
264             throw new CompilerException(
265                     "Error while getting the canonical path of '" + origFile.getAbsolutePath() + "'.", e);
266         }
267     }
268 
269     protected void logCompiling(String[] sourceFiles, CompilerConfiguration config) {
270         if (log.isInfoEnabled()) {
271             log.info("Compiling "
272                     + (sourceFiles == null
273                             ? ""
274                             : (sourceFiles.length + " source file" + (sourceFiles.length == 1 ? " " : "s ")))
275                     + "with "
276                     + getCompilerId() + " [" + config.describe() + "]" + " to "
277                     + getRelativeWorkingDirectory(config));
278         }
279     }
280 
281     private static String getRelativeWorkingDirectory(CompilerConfiguration config) {
282         String to;
283         if (config.getWorkingDirectory() == null) {
284             to = config.getOutputLocation();
285         } else {
286             try {
287                 to = config.getWorkingDirectory()
288                         .toPath()
289                         .relativize(new File(config.getOutputLocation()).toPath())
290                         .toString();
291             } catch (IllegalArgumentException e) {
292                 // may happen on Windows if the working directory is on a different drive
293                 to = config.getOutputLocation();
294             }
295         }
296         return to;
297     }
298 }