KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > tool > EclipseCompilerImpl


1 /*******************************************************************************
2  * Copyright (c) 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.tool;
12
13 import java.io.BufferedOutputStream JavaDoc;
14 import java.io.File JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.OutputStream JavaDoc;
17 import java.io.PrintWriter JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Locale JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import javax.annotation.processing.Processor;
24 import javax.tools.Diagnostic;
25 import javax.tools.DiagnosticListener;
26 import javax.tools.JavaFileManager;
27 import javax.tools.JavaFileObject;
28 import javax.tools.StandardJavaFileManager;
29 import javax.tools.StandardLocation;
30
31 import org.eclipse.jdt.core.compiler.CategorizedProblem;
32 import org.eclipse.jdt.core.compiler.CharOperation;
33 import org.eclipse.jdt.core.compiler.InvalidInputException;
34 import org.eclipse.jdt.internal.compiler.ClassFile;
35 import org.eclipse.jdt.internal.compiler.CompilationResult;
36 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
37 import org.eclipse.jdt.internal.compiler.IProblemFactory;
38 import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
39 import org.eclipse.jdt.internal.compiler.batch.FileSystem;
40 import org.eclipse.jdt.internal.compiler.batch.Main;
41 import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
42 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
43 import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
44 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
45 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
46 import org.eclipse.jdt.internal.compiler.util.Messages;
47 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
48
49 public class EclipseCompilerImpl extends Main {
50     private static final CompilationUnit[] NO_UNITS = new CompilationUnit[0];
51     private HashMap JavaDoc<CompilationUnit, JavaFileObject> javaFileObjectMap;
52     Iterable JavaDoc<? extends JavaFileObject> compilationUnits;
53     public JavaFileManager fileManager;
54     protected Processor[] processors;
55     public DiagnosticListener<? super JavaFileObject> diagnosticListener;
56
57     public EclipseCompilerImpl(PrintWriter JavaDoc out, PrintWriter JavaDoc err, boolean systemExitWhenFinished) {
58         super(out, err, systemExitWhenFinished);
59     }
60
61     public boolean call() {
62         try {
63             if (this.proceed) {
64                 this.globalProblemsCount = 0;
65                 this.globalErrorsCount = 0;
66                 this.globalWarningsCount = 0;
67                 this.globalTasksCount = 0;
68                 this.lineCount = 0;
69                 this.exportedClassFilesCounter = 0;
70                 // request compilation
71
performCompilation();
72             }
73         } catch (InvalidInputException e) {
74             this.logger.logException(e);
75             if (this.systemExitWhenFinished) {
76                 cleanup();
77                 System.exit(-1);
78             }
79             return false;
80         } catch(IllegalArgumentException JavaDoc e) {
81             throw e;
82         } catch (RuntimeException JavaDoc e) { // internal compiler failure
83
this.logger.logException(e);
84             return false;
85         } finally {
86             cleanup();
87         }
88         if (this.globalErrorsCount == 0)
89             return true;
90         return false;
91     }
92
93     private void cleanup() {
94         this.logger.flush();
95         this.logger.close();
96         this.processors = null;
97         try {
98             if (this.fileManager != null) {
99                 this.fileManager.flush();
100             }
101         } catch (IOException JavaDoc e) {
102             // ignore
103
}
104     }
105
106     public CompilationUnit[] getCompilationUnits() {
107         if (this.compilationUnits == null) return NO_UNITS;
108         ArrayList JavaDoc<CompilationUnit> units = new ArrayList JavaDoc<CompilationUnit>();
109         for (final JavaFileObject javaFileObject : this.compilationUnits) {
110             if (javaFileObject.getKind() != JavaFileObject.Kind.SOURCE) {
111                 throw new IllegalArgumentException JavaDoc();
112             }
113             String JavaDoc name = javaFileObject.getName();
114             name = name.replace('\\', '/');
115             CompilationUnit compilationUnit = new CompilationUnit(null,
116                 name,
117                 null) {
118
119                 public char[] getContents() {
120                     try {
121                         return javaFileObject.getCharContent(true).toString().toCharArray();
122                     } catch(IOException JavaDoc e) {
123                         e.printStackTrace();
124                         throw new AbortCompilationUnit(null, e, null);
125                     }
126                 }
127             };
128             units.add(compilationUnit);
129             this.javaFileObjectMap.put(compilationUnit, javaFileObject);
130         }
131         CompilationUnit[] result = new CompilationUnit[units.size()];
132         units.toArray(result);
133         return result;
134     }
135     /*
136      * Low-level API performing the actual compilation
137      */

138     public IErrorHandlingPolicy getHandlingPolicy() {
139         // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
140
return new IErrorHandlingPolicy() {
141             public boolean proceedOnErrors() {
142                 return false; // stop if there are some errors
143
}
144             public boolean stopOnFirstError() {
145                 return false;
146             }
147         };
148     }
149
150     public IProblemFactory getProblemFactory() {
151         return new DefaultProblemFactory() {
152             @Override JavaDoc
153             public CategorizedProblem createProblem(
154                     final char[] originatingFileName,
155                     final int problemId,
156                     final String JavaDoc[] problemArguments,
157                     final String JavaDoc[] messageArguments,
158                     final int severity,
159                     final int startPosition,
160                     final int endPosition,
161                     final int lineNumber,
162                     final int columnNumber) {
163
164                 DiagnosticListener<? super JavaFileObject> diagnosticListener = EclipseCompilerImpl.this.diagnosticListener;
165                 if (diagnosticListener != null) {
166                     diagnosticListener.report(new Diagnostic<JavaFileObject>() {
167                         public String JavaDoc getCode() {
168                             return Integer.toString(problemId);
169                         }
170                         public long getColumnNumber() {
171                             return columnNumber;
172                         }
173                         public long getEndPosition() {
174                             return endPosition;
175                         }
176                         public Kind getKind() {
177                             if ((severity & ProblemSeverities.Error) != 0) {
178                                 return Diagnostic.Kind.ERROR;
179                             }
180                             if ((severity & ProblemSeverities.Optional) != 0) {
181                                 return Diagnostic.Kind.WARNING;
182                             }
183                             if ((severity & ProblemSeverities.Warning) != 0) {
184                                 return Diagnostic.Kind.MANDATORY_WARNING;
185                             }
186                             return Diagnostic.Kind.OTHER;
187                         }
188                         public long getLineNumber() {
189                             return lineNumber;
190                         }
191                         public String JavaDoc getMessage(Locale JavaDoc locale) {
192                             setLocale(locale);
193                             return getLocalizedMessage(problemId, problemArguments);
194                         }
195                         public long getPosition() {
196                             return startPosition;
197                         }
198                         public JavaFileObject getSource() {
199                             try {
200                                 if (EclipseCompilerImpl.this.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) {
201                                     return EclipseCompilerImpl.this.fileManager.getJavaFileForInput(
202                                             StandardLocation.SOURCE_PATH,
203                                             new String JavaDoc(originatingFileName),
204                                             JavaFileObject.Kind.SOURCE);
205                                 }
206                             } catch (IOException JavaDoc e) {
207                                 // ignore
208
}
209                             return null;
210                         }
211                         public long getStartPosition() {
212                             return startPosition;
213                         }
214                     });
215                 }
216                 return super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber, columnNumber);
217             }
218         };
219     }
220
221     @Override JavaDoc
222     @SuppressWarnings JavaDoc("unchecked")
223     protected void initialize(PrintWriter JavaDoc outWriter, PrintWriter JavaDoc errWriter, boolean systemExit, Map JavaDoc customDefaultOptions) {
224         super.initialize(outWriter, errWriter, systemExit, customDefaultOptions);
225         this.javaFileObjectMap = new HashMap JavaDoc<CompilationUnit, JavaFileObject>();
226     }
227
228     @Override JavaDoc
229     protected void initializeAnnotationProcessorManager() {
230         super.initializeAnnotationProcessorManager();
231         if (this.batchCompiler.annotationProcessorManager != null && this.processors != null) {
232             this.batchCompiler.annotationProcessorManager.setProcessors(this.processors);
233         } else if (this.processors != null) {
234             throw new UnsupportedOperationException JavaDoc("Cannot handle annotation processing"); //$NON-NLS-1$
235
}
236     }
237
238     // Dump classfiles onto disk for all compilation units that where successful
239
// and do not carry a -d none spec, either directly or inherited from Main.
240
public void outputClassFiles(CompilationResult unitResult) {
241         if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) {
242             ClassFile[] classFiles = unitResult.getClassFiles();
243             boolean generateClasspathStructure = this.fileManager.hasLocation(StandardLocation.CLASS_OUTPUT);
244             String JavaDoc currentDestinationPath = this.destinationPath;
245             File JavaDoc outputLocation = null;
246             if (currentDestinationPath != null) {
247                 outputLocation = new File JavaDoc(currentDestinationPath);
248                 outputLocation.mkdirs();
249             }
250             for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) {
251                 // retrieve the key and the corresponding classfile
252
ClassFile classFile = classFiles[i];
253                 char[] filename = classFile.fileName();
254                 int length = filename.length;
255                 char[] relativeName = new char[length + 6];
256                 System.arraycopy(filename, 0, relativeName, 0, length);
257                 System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6);
258                 CharOperation.replace(relativeName, '/', File.separatorChar);
259                 String JavaDoc relativeStringName = new String JavaDoc(relativeName);
260                 if (this.compilerOptions.verbose) {
261                     EclipseCompilerImpl.this.out.println(
262                         Messages.bind(
263                             Messages.compilation_write,
264                             new String JavaDoc[] {
265                                 String.valueOf(this.exportedClassFilesCounter+1),
266                                 relativeStringName
267                             }));
268                 }
269                 try {
270                     JavaFileObject javaFileForOutput =
271                     this.fileManager.getJavaFileForOutput(
272                             StandardLocation.CLASS_OUTPUT,
273                             new String JavaDoc(filename),
274                             JavaFileObject.Kind.CLASS,
275                             this.javaFileObjectMap.get(unitResult.compilationUnit));
276
277                     if (generateClasspathStructure) {
278                         if (currentDestinationPath != null) {
279                             int index = CharOperation.lastIndexOf(File.separatorChar, relativeName);
280                             if (index != -1) {
281                                 File JavaDoc currentFolder = new File JavaDoc(currentDestinationPath, relativeStringName.substring(0, index));
282                                 currentFolder.mkdirs();
283                             }
284                         } else {
285                             // create the subfolfers is necessary
286
// need a way to retrieve the folders to create
287
String JavaDoc path = javaFileForOutput.toUri().getPath();
288                             int index = path.lastIndexOf('/');
289                             if (index != -1) {
290                                 File JavaDoc file = new File JavaDoc(path.substring(0, index));
291                                 file.mkdirs();
292                             }
293                         }
294                     }
295
296                     OutputStream JavaDoc openOutputStream = javaFileForOutput.openOutputStream();
297                     BufferedOutputStream JavaDoc bufferedOutputStream = new BufferedOutputStream JavaDoc(openOutputStream);
298                     bufferedOutputStream.write(classFile.header, 0, classFile.headerOffset);
299                     bufferedOutputStream.write(classFile.contents, 0, classFile.contentsOffset);
300                     bufferedOutputStream.flush();
301                     bufferedOutputStream.close();
302                 } catch (IOException JavaDoc e) {
303                     this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e);
304                 }
305                 LookupEnvironment env = EclipseCompilerImpl.this.batchCompiler.lookupEnvironment;
306                 if (classFile.isShared) {
307                     synchronized (env.classFilePool) {
308                         env.classFilePool.release(classFile);
309                     }
310                 }
311                 this.logger.logClassFile(
312                     generateClasspathStructure,
313                     currentDestinationPath,
314                     relativeStringName);
315                 this.exportedClassFilesCounter++;
316             }
317         }
318     }
319
320     @Override JavaDoc
321     @SuppressWarnings JavaDoc("unchecked")
322     protected void setPaths(ArrayList JavaDoc bootclasspaths,
323             String JavaDoc sourcepathClasspathArg,
324             ArrayList JavaDoc sourcepathClasspaths,
325             ArrayList JavaDoc classpaths,
326             ArrayList JavaDoc extdirsClasspaths,
327             ArrayList JavaDoc endorsedDirClasspaths,
328             String JavaDoc customEncoding) throws InvalidInputException {
329
330         ArrayList JavaDoc<FileSystem.Classpath> fileSystemClasspaths = new ArrayList JavaDoc<FileSystem.Classpath>();
331         EclipseFileManager javaFileManager = null;
332         StandardJavaFileManager standardJavaFileManager = null;
333         if (this.fileManager instanceof EclipseFileManager) {
334             javaFileManager = (EclipseFileManager) this.fileManager;
335         }
336         if (this.fileManager instanceof StandardJavaFileManager) {
337             standardJavaFileManager = (StandardJavaFileManager) this.fileManager;
338         }
339
340         if (javaFileManager != null) {
341             if ((javaFileManager.flags & EclipseFileManager.HAS_ENDORSED_DIRS) == 0
342                     && (javaFileManager.flags & EclipseFileManager.HAS_BOOTCLASSPATH) != 0) {
343                 fileSystemClasspaths.addAll((ArrayList JavaDoc<? extends FileSystem.Classpath>) this.handleEndorseddirs(null));
344             }
345         }
346         Iterable JavaDoc<? extends File JavaDoc> location = null;
347         if (standardJavaFileManager != null) {
348             location = standardJavaFileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH);
349         }
350         if (location != null) {
351             for (File JavaDoc file : location) {
352                 Classpath classpath = FileSystem.getClasspath(
353                     file.getAbsolutePath(),
354                     null,
355                     null);
356                 if (classpath != null) {
357                     fileSystemClasspaths.add(classpath);
358                 }
359             }
360         }
361         if (javaFileManager != null) {
362             if ((javaFileManager.flags & EclipseFileManager.HAS_EXT_DIRS) == 0
363                     && (javaFileManager.flags & EclipseFileManager.HAS_BOOTCLASSPATH) != 0) {
364                 fileSystemClasspaths.addAll((ArrayList JavaDoc<? extends FileSystem.Classpath>) this.handleExtdirs(null));
365             }
366         }
367         if (standardJavaFileManager != null) {
368             location = standardJavaFileManager.getLocation(StandardLocation.SOURCE_PATH);
369         } else {
370             location = null;
371         }
372         if (location != null) {
373             for (File JavaDoc file : location) {
374                 fileSystemClasspaths.add(FileSystem.getClasspath(
375                     file.getAbsolutePath(),
376                     null,
377                     null));
378             }
379         }
380         if (standardJavaFileManager != null) {
381             location = standardJavaFileManager.getLocation(StandardLocation.CLASS_PATH);
382         } else {
383             location = null;
384         }
385         if (location != null) {
386             for (File JavaDoc file : location) {
387                 Classpath classpath = FileSystem.getClasspath(
388                     file.getAbsolutePath(),
389                     null,
390                     null);
391                 if (classpath != null) {
392                     fileSystemClasspaths.add(classpath);
393                 }
394             }
395         }
396         if (this.checkedClasspaths == null) {
397             fileSystemClasspaths.addAll((ArrayList JavaDoc<? extends FileSystem.Classpath>) this.handleBootclasspath(null, null));
398             fileSystemClasspaths.addAll((ArrayList JavaDoc<? extends FileSystem.Classpath>) this.handleClasspath(null, null));
399         }
400         fileSystemClasspaths = FileSystem.ClasspathNormalizer.normalize(fileSystemClasspaths);
401         final int size = fileSystemClasspaths.size();
402         if (size != 0) {
403             this.checkedClasspaths = new FileSystem.Classpath[size];
404             int i = 0;
405             for (FileSystem.Classpath classpath : fileSystemClasspaths) {
406                 this.checkedClasspaths[i++] = classpath;
407             }
408         }
409     }
410 }
411
Popular Tags