KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > components > compiler > Javac


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.axis.components.compiler;
18
19 import org.apache.axis.components.logger.LogFactory;
20 import org.apache.axis.utils.ClassUtils;
21 import org.apache.axis.utils.Messages;
22 import org.apache.commons.logging.Log;
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.ByteArrayInputStream JavaDoc;
26 import java.io.ByteArrayOutputStream JavaDoc;
27 import java.io.File JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.OutputStream JavaDoc;
30 import java.io.OutputStreamWriter JavaDoc;
31 import java.io.PrintWriter JavaDoc;
32 import java.lang.reflect.Constructor JavaDoc;
33 import java.lang.reflect.Method JavaDoc;
34 import java.util.ArrayList JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.NoSuchElementException JavaDoc;
37 import java.util.StringTokenizer JavaDoc;
38 import java.net.URL JavaDoc;
39 import java.net.MalformedURLException JavaDoc;
40 import java.net.URLClassLoader JavaDoc;
41
42 /**
43  * This class wraps the Sun's Javac Compiler.
44  *
45  * @author <a HREF="mailto:dims@yahoo.com">Davanum Srinivas</a>
46  * @author <a HREF="mailto:stefano@apache.org">Stefano Mazzocchi</a>
47  * @since 2.0
48  */

49
50 public class Javac extends AbstractCompiler
51 {
52     protected static Log log =
53         LogFactory.getLog(Javac.class.getName());
54
55     public static final String JavaDoc CLASSIC_CLASS = "sun.tools.javac.Main";
56     public static final String JavaDoc MODERN_CLASS = "com.sun.tools.javac.main.Main";
57
58     private boolean modern = false;
59
60     public Javac() {
61         ClassLoader JavaDoc cl = getClassLoader();
62         try {
63             ClassUtils.forName(MODERN_CLASS, true, cl);
64             modern = true;
65         } catch (ClassNotFoundException JavaDoc e) {
66             log.debug(Messages.getMessage("noModernCompiler"));
67             try {
68                 ClassUtils.forName(CLASSIC_CLASS, true, cl);
69                 modern = false;
70             } catch (Exception JavaDoc ex) {
71                 log.error(Messages.getMessage("noCompiler00"), ex);
72                 throw new RuntimeException JavaDoc(Messages.getMessage("noCompiler00"));
73             }
74         }
75         log.debug(Messages.getMessage("compilerClass",
76                 (modern ? MODERN_CLASS : CLASSIC_CLASS)));
77     }
78
79     private ClassLoader JavaDoc getClassLoader() {
80         // Use reflection to be able to build on all JDKs
81
ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
82
83         URL JavaDoc toolsURL = null;
84         String JavaDoc tools = System.getProperty("java.home");
85         if (tools != null) {
86             File JavaDoc f = new File JavaDoc(tools + "/../lib/tools.jar");
87             if (f.exists()) {
88                 try {
89                     toolsURL = f.toURL();
90                     cl = new URLClassLoader JavaDoc(new URL JavaDoc[]{toolsURL}, cl);
91                 } catch (MalformedURLException JavaDoc e) {
92                 }
93             }
94         }
95         
96         return cl;
97     }
98
99     /**
100      * Compile a source file yielding a loadable class file.
101      *
102      * @exception IOException If an error occurs during compilation
103      */

104     public boolean compile() throws IOException JavaDoc {
105         ByteArrayOutputStream JavaDoc err = new ByteArrayOutputStream JavaDoc();
106         boolean result = false;
107
108         try {
109             // Create an instance of the compiler, redirecting output to err
110
Class JavaDoc c = ClassUtils.forName(modern ? MODERN_CLASS : CLASSIC_CLASS,
111                                          true,
112                                          getClassLoader());
113
114             Constructor JavaDoc cons;
115             Object JavaDoc compiler;
116             if (modern) {
117                 PrintWriter JavaDoc pw = new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(err));
118                 cons =
119                     c.getConstructor(new Class JavaDoc[] { String JavaDoc.class,
120                                                    PrintWriter JavaDoc.class});
121        
122                 compiler = cons.newInstance(new Object JavaDoc[] { "javac", pw });
123             }
124             else {
125                 cons =
126                     c.getConstructor(new Class JavaDoc[] { OutputStream JavaDoc.class,
127                                                    String JavaDoc.class });
128                 compiler = cons.newInstance(new Object JavaDoc[] { err, "javac" });
129         
130             }
131               
132             // Call the compile() method
133
Method JavaDoc compile = c.getMethod("compile",
134                                          new Class JavaDoc [] { String JavaDoc[].class });
135
136             if (modern) {
137                 int compilationResult =
138                     ((Integer JavaDoc)compile.invoke(compiler, new Object JavaDoc[]
139                         {
140                             toStringArray(fillArguments
141                                           (new ArrayList JavaDoc()))})).intValue();
142
143                 result = (compilationResult == 0);
144                 log.debug("Compilation Returned: "
145                           + Integer.toString(compilationResult));
146             }
147             else {
148                 Boolean JavaDoc ok =
149                     (Boolean JavaDoc)compile.invoke(compiler, new Object JavaDoc[]
150                         {toStringArray(fillArguments(new ArrayList JavaDoc()))});
151         
152                 result = ok.booleanValue();
153             }
154         } catch (Exception JavaDoc cnfe){
155             log.error(Messages.getMessage("noCompiler00"), cnfe);
156             throw new RuntimeException JavaDoc(Messages.getMessage("noCompiler00"));
157         }
158
159         this.errors = new ByteArrayInputStream JavaDoc(err.toByteArray());
160         return result;
161     }
162
163     /**
164      * Parse the compiler error stream to produce a list of
165      * <code>CompilerError</code>s
166      *
167      * @param input The error stream
168      * @return The list of compiler error messages
169      * @exception IOException If an error occurs during message collection
170      */

171     protected List JavaDoc parseStream(BufferedReader JavaDoc input) throws IOException JavaDoc {
172         if (modern) {
173             return parseModernStream(input);
174         } else {
175             return parseClassicStream(input);
176         }
177     }
178
179     /**
180      * Parse the compiler error stream to produce a list of
181      * <code>CompilerError</code>s
182      *
183      * @param input The error stream
184      * @return The list of compiler error messages
185      * @exception IOException If an error occurs during message collection
186      */

187     protected List JavaDoc parseModernStream(BufferedReader JavaDoc input) throws IOException JavaDoc {
188         List JavaDoc errors = new ArrayList JavaDoc();
189         String JavaDoc line = null;
190         StringBuffer JavaDoc buffer = null;
191
192         while (true) {
193             // cleanup the buffer
194
buffer = new StringBuffer JavaDoc(); // this is quicker than clearing it
195

196             // most errors terminate with the '^' char
197
do {
198                 if ((line = input.readLine()) == null)
199                 {
200                     if (buffer.length() > 0) {
201                         // There's an error which doesn't end with a '^'
202
errors.add(new CompilerError("\n" + buffer.toString()));
203                     }
204                     return errors;
205                 }
206                 log.debug(line);
207                 buffer.append(line);
208                 buffer.append('\n');
209             } while (!line.endsWith("^"));
210
211             // add the error bean
212
errors.add(parseModernError(buffer.toString()));
213         }
214     }
215
216     /**
217      * Parse an individual compiler error message with modern style.
218      *
219      * @param error The error text
220      * @return A messaged <code>CompilerError</code>
221      */

222     private CompilerError parseModernError(String JavaDoc error) {
223         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(error, ":");
224         try {
225             String JavaDoc file = tokens.nextToken();
226             if (file.length() == 1) file = new StringBuffer JavaDoc(file).append(":").append(tokens.nextToken()).toString();
227             int line = Integer.parseInt(tokens.nextToken());
228
229             String JavaDoc message = tokens.nextToken("\n").substring(1);
230             String JavaDoc context = tokens.nextToken("\n");
231             String JavaDoc pointer = tokens.nextToken("\n");
232             int startcolumn = pointer.indexOf("^");
233             int endcolumn = context.indexOf(" ", startcolumn);
234             if (endcolumn == -1) endcolumn = context.length();
235             return new CompilerError(file, false, line, startcolumn, line, endcolumn, message);
236         } catch(NoSuchElementException JavaDoc nse) {
237             return new CompilerError(Messages.getMessage("noMoreTokens", error));
238         } catch(Exception JavaDoc nse) {
239             return new CompilerError(Messages.getMessage("cantParse", error));
240         }
241     }
242
243     /**
244      * Parse the compiler error stream to produce a list of
245      * <code>CompilerError</code>s
246      *
247      * @param input The error stream
248      * @return The list of compiler error messages
249      * @exception IOException If an error occurs during message collection
250      */

251     protected List JavaDoc parseClassicStream(BufferedReader JavaDoc input) throws IOException JavaDoc {
252         List JavaDoc errors = null;
253         String JavaDoc line = null;
254         StringBuffer JavaDoc buffer = null;
255
256         while (true) {
257             // cleanup the buffer
258
buffer = new StringBuffer JavaDoc(); // this is faster than clearing it
259

260             // each error has 3 lines
261
for (int i = 0; i < 3 ; i++) {
262                 if ((line = input.readLine()) == null) return errors;
263                 log.debug(line);
264                 buffer.append(line);
265                 buffer.append('\n');
266             }
267
268             // if error is found create the vector
269
if (errors == null) errors = new ArrayList JavaDoc();
270
271             // add the error bean
272
errors.add(parseClassicError(buffer.toString()));
273         }
274     }
275
276     /**
277      * Parse an individual compiler error message with classic style.
278      *
279      * @param error The error text
280      * @return A messaged <code>CompilerError</code>
281      */

282     private CompilerError parseClassicError(String JavaDoc error) {
283         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(error, ":");
284         try {
285             String JavaDoc file = tokens.nextToken();
286             if (file.length() == 1) {
287                 file = new StringBuffer JavaDoc(file).append(":").
288                         append(tokens.nextToken()).toString();
289             }
290             int line = Integer.parseInt(tokens.nextToken());
291
292             String JavaDoc last = tokens.nextToken();
293             // In case the message contains ':', it should be reassembled
294
while (tokens.hasMoreElements()) {
295                 last += tokens.nextToken();
296             }
297             tokens = new StringTokenizer JavaDoc(last.trim(), "\n");
298             String JavaDoc message = tokens.nextToken();
299             String JavaDoc context = tokens.nextToken();
300             String JavaDoc pointer = tokens.nextToken();
301             int startcolumn = pointer.indexOf("^");
302             int endcolumn = context.indexOf(" ", startcolumn);
303             if (endcolumn == -1) endcolumn = context.length();
304
305             return new CompilerError(srcDir + File.separator + file, true,
306                     line, startcolumn, line, endcolumn, message);
307         } catch(NoSuchElementException JavaDoc nse) {
308             return new CompilerError(Messages.getMessage("noMoreTokens",
309                     error));
310         } catch(Exception JavaDoc nse) {
311             return new CompilerError(Messages.getMessage("cantParse", error));
312         }
313     }
314
315     public String JavaDoc toString() {
316         return Messages.getMessage("sunJavac");
317     }
318 }
319
Popular Tags