KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > language > programming > java > Jikes


1 /*
2  * Copyright 1999-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 package org.apache.cocoon.components.language.programming.java;
17
18 import java.io.BufferedInputStream JavaDoc;
19 import java.io.BufferedReader JavaDoc;
20 import java.io.ByteArrayInputStream JavaDoc;
21 import java.io.ByteArrayOutputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.StringTokenizer JavaDoc;
27
28 import org.apache.avalon.framework.service.ServiceException;
29 import org.apache.avalon.framework.service.ServiceManager;
30 import org.apache.avalon.framework.service.Serviceable;
31 import org.apache.cocoon.components.language.programming.CompilerError;
32 import org.apache.cocoon.components.thread.RunnableManager;
33 import EDU.oswego.cs.dl.util.concurrent.CountDown;
34
35 /**
36  * This class wraps IBM's <i>Jikes</i> Java compiler
37  * NOTE: inspired by the Apache Jasper implementation.
38  * @author <a HREF="mailto:stefano@apache.org">Stefano Mazzocchi</a>
39  * @version CVS $Id: Jikes.java 124680 2005-01-08 20:23:32Z antonio $
40  * @since 2.0
41  */

42
43 public class Jikes extends AbstractJavaCompiler implements Serviceable {
44
45     static final int OUTPUT_BUFFER_SIZE = 1024;
46     static final int BUFFER_SIZE = 512;
47
48     private ServiceManager m_serviceManager;
49     
50     private static class StreamPumper implements Runnable JavaDoc {
51
52         private BufferedInputStream JavaDoc stream;
53         private boolean endOfStream = false;
54         private int SLEEP_TIME = 5;
55         private OutputStream JavaDoc out;
56         private CountDown m_done;
57
58         public StreamPumper(BufferedInputStream JavaDoc is, OutputStream JavaDoc out, CountDown done) {
59             this.stream = is;
60             this.out = out;
61             m_done = done;
62         }
63
64         public void pumpStream() throws IOException JavaDoc {
65             byte[] buf = new byte[BUFFER_SIZE];
66             if (!endOfStream) {
67                 int bytesRead = stream.read(buf, 0, BUFFER_SIZE);
68
69                 if (bytesRead > 0) {
70                     out.write(buf, 0, bytesRead);
71                 } else if (bytesRead == -1) {
72                     endOfStream = true;
73                 }
74             }
75         }
76
77         public void run() {
78             try {
79                 while (!endOfStream) {
80                     pumpStream();
81                     Thread.sleep(SLEEP_TIME);
82                 }
83             } catch (Exception JavaDoc e) {
84                // getLogger().warn("Jikes.run()", e);
85
}
86             m_done.release(); // signal 'we are finished'
87
}
88         }
89
90     /**
91      * Set the {@link ServiceManager}
92      */

93     public void service( ServiceManager serviceManager )
94     throws ServiceException
95     {
96         m_serviceManager = serviceManager;
97     }
98
99     /**
100      * Copy arguments to a string array
101      *
102      * @param arguments The compiler arguments
103      * @return A string array containing compilation arguments
104      */

105     protected String JavaDoc[] toStringArray(List JavaDoc arguments) {
106       int i;
107
108       for (i = 0; i < arguments.size(); i++) {
109         String JavaDoc arg = (String JavaDoc) arguments.get(i);
110         if (arg.equals("-sourcepath")) {
111           // Remove -sourcepath option. Jikes does not understand that.
112
arguments.remove(i);
113           arguments.remove(i);
114           break;
115         }
116       }
117
118       String JavaDoc[] args = new String JavaDoc[arguments.size() + 1];
119       for (i = 0; i < arguments.size(); i++) {
120         args[i] = (String JavaDoc) arguments.get(i);
121       }
122
123       args[i] = file;
124
125       return args;
126     }
127
128     /**
129      * Execute the compiler
130      */

131     public boolean compile() throws IOException JavaDoc {
132
133         List JavaDoc args = new ArrayList JavaDoc();
134         // command line name
135
args.add("jikes");
136         // indicate Emacs output mode must be used
137
args.add("+E");
138         // avoid warnings
139
// Option nowarn with one hyphen only
140
args.add("-nowarn");
141
142         int exitValue;
143         ByteArrayOutputStream JavaDoc tmpErr = new ByteArrayOutputStream JavaDoc(OUTPUT_BUFFER_SIZE);
144
145         try {
146             Process JavaDoc p = Runtime.getRuntime().exec(toStringArray(fillArguments(args)));
147
148             BufferedInputStream JavaDoc compilerErr = new BufferedInputStream JavaDoc(p.getErrorStream());
149
150             RunnableManager runnableManager = null;
151             try
152             {
153                 runnableManager = (RunnableManager)m_serviceManager.lookup( RunnableManager.ROLE );
154             }
155             catch( final ServiceException se )
156             {
157                 getLogger().error( "Cannot get RunnableManager", se );
158                 throw new IOException JavaDoc( "Cannot get RunnableManager" );
159             }
160
161             final CountDown done = new CountDown( 1 );
162             StreamPumper errPumper = new StreamPumper(compilerErr, tmpErr, done);
163             runnableManager.execute( errPumper );
164             m_serviceManager.release( runnableManager );
165
166             p.waitFor();
167             exitValue = p.exitValue();
168
169             done.acquire(); // Wait for StreadmPumper to finish
170
compilerErr.close();
171
172             p.destroy();
173
174             tmpErr.close();
175             this.errors = new ByteArrayInputStream JavaDoc(tmpErr.toByteArray());
176
177         } catch (InterruptedException JavaDoc somethingHappened) {
178             getLogger().debug("Jikes.compile():SomethingHappened", somethingHappened);
179             return false;
180         }
181
182         // Jikes returns 0 even when there are some types of errors.
183
// Check if any error output as well
184
// Return should be OK when both exitValue and
185
// tmpErr.size() are 0 ?!
186
return ((exitValue == 0) && (tmpErr.size() == 0));
187     }
188
189     /**
190      * Parse the compiler error stream to produce a list of
191      * <code>CompilerError</code>s
192      *
193      * @param input The error stream
194      * @return The list of compiler error messages
195      * @exception IOException If an error occurs during message collection
196      */

197     protected List JavaDoc parseStream(BufferedReader JavaDoc input) throws IOException JavaDoc {
198         List JavaDoc errors = null;
199         String JavaDoc line = null;
200         StringBuffer JavaDoc buffer = null;
201
202         while (true) {
203             // cleanup the buffer
204
buffer = new StringBuffer JavaDoc(); // this is faster than clearing it
205

206             // first line is not space-starting
207
if (line == null) line = input.readLine();
208             if (line == null) return errors;
209             buffer.append(line);
210
211             // all other space-starting lines are one error
212
while (true) {
213                 line = input.readLine();
214                 // EOF
215
if (line == null)
216                     break;
217                 // Continuation of previous error starts with ' '
218
if (line.length() > 0 && line.charAt(0) != ' ')
219                     break;
220                 buffer.append('\n');
221                 buffer.append(line);
222             }
223
224             // if error is found create the vector
225
if (errors == null) errors = new ArrayList JavaDoc();
226
227             // add the error bean
228
errors.add(parseError(buffer.toString()));
229         }
230     }
231
232     /**
233      * Parse an individual compiler error message
234      *
235      * @param error The error text
236      * @return A mssaged <code>CompilerError</code>
237      */

238     private CompilerError parseError(String JavaDoc error) {
239         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(error, ":");
240         String JavaDoc file = tokens.nextToken();
241         if (file.length() == 1) file = new StringBuffer JavaDoc(file).append(":").append(tokens.nextToken()).toString();
242         StringBuffer JavaDoc message = new StringBuffer JavaDoc();
243         String JavaDoc type = "";
244         int startline = 0;
245         int startcolumn = 0;
246         int endline = 0;
247         int endcolumn = 0;
248
249         try {
250             startline = Integer.parseInt(tokens.nextToken());
251             startcolumn = Integer.parseInt(tokens.nextToken());
252             endline = Integer.parseInt(tokens.nextToken());
253             endcolumn = Integer.parseInt(tokens.nextToken());
254         } catch (Exception JavaDoc e) {
255             // FIXME: VG: This is not needed anymore?
256
message.append("Please ensure that you have your JDK's rt.jar listed in your classpath. Jikes needs it to operate.");
257             type="error";
258             getLogger().error(message.toString(), e);
259         }
260
261         if ("".equals(message.toString())) {
262             type = tokens.nextToken().trim().toLowerCase();
263             message.append(tokens.nextToken("\n").substring(1).trim());
264
265             while (tokens.hasMoreTokens())
266                 message.append("\n").append(tokens.nextToken());
267         }
268
269         return new CompilerError(file, type.equals("error"), startline, startcolumn, endline, endcolumn, message.toString());
270     }
271
272     public String JavaDoc toString() {
273         return "IBM Jikes Compiler";
274     }
275 }
276
Popular Tags