KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > builder > Engine


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.java.source.builder;
21
22 import org.netbeans.modules.java.source.engine.EngineEnvironment;
23 import org.netbeans.modules.java.source.engine.JavaFormatOptions;
24 import org.netbeans.modules.java.source.engine.PropertySheetInfo;
25 import org.netbeans.modules.java.source.engine.JackpotEngine;
26 import org.netbeans.modules.java.source.engine.ApplicationContext;
27 import org.netbeans.modules.java.source.engine.BuildProgress;
28 import org.netbeans.modules.java.source.engine.EmptyScriptException;
29 import org.netbeans.modules.java.source.engine.EngineException;
30 import org.netbeans.modules.java.source.engine.QueryProgress;
31 import org.netbeans.modules.java.source.engine.RecursiveRuleException;
32 import org.netbeans.modules.java.source.engine.RulesParseException;
33 import org.netbeans.api.java.source.transform.UndoList;
34 import org.netbeans.modules.java.source.pretty.VeryPretty;
35 import org.netbeans.api.java.source.query.Query;
36 import org.netbeans.api.java.source.query.ResultTableModel;
37 import org.netbeans.modules.java.source.save.Commit;
38 import org.netbeans.modules.java.source.script.TransformParser;
39 import org.netbeans.api.java.source.transform.ChangeSet;
40 import org.netbeans.api.java.source.transform.Transformer;
41 import org.netbeans.modules.classfile.ClassFile;
42 import org.openide.filesystems.FileObject;
43 import org.openide.filesystems.Repository;
44 import com.sun.tools.javac.api.JavacTaskImpl;
45 import com.sun.tools.javac.main.JavaCompiler;
46 import com.sun.tools.javac.tree.JCTree;
47 import com.sun.tools.javac.util.Context;
48 import com.sun.tools.javac.util.Log;
49 import com.sun.tools.javac.util.Options;
50 import java.io.*;
51 import java.util.StringTokenizer JavaDoc;
52 import java.util.logging.*;
53 import javax.tools.JavaFileObject;
54
55 /**
56  * Jackpot execution engine.
57  */

58 public class Engine implements JackpotEngine {
59     private EngineEnvironment env;
60     ApplicationContext appContext;
61     private boolean buildFinished;
62     private String JavaDoc jackpotPath;
63     
64     static final Logger logger = Logger.getLogger("org.netbeans.modules.java.source");
65     
66     /** Creates a new instance of Engine */
67     public Engine(ApplicationContext appContext, String JavaDoc jackpotPath) {
68         this.appContext = appContext;
69         appContext.setStatusMessage("");
70         this.jackpotPath = jackpotPath;
71     }
72     
73     /**
74      * Creates a Jackpot environment and builds its sources.
75      *
76      * @return the number of compilation errors from the build.
77      */

78     public int initialize(String JavaDoc sourcepath, String JavaDoc classpath, String JavaDoc source) throws Exception JavaDoc {
79         return initialize(sourcepath, classpath, null, source);
80     }
81     
82     /**
83      * Creates a Jackpot environment and builds its sources.
84      *
85      * @return the number of compilation errors from the build.
86      */

87     public int initialize(String JavaDoc sourcepath, String JavaDoc classpath, String JavaDoc bootclasspath, String JavaDoc source) throws Exception JavaDoc {
88         return initialize(sourcepath, classpath, bootclasspath, source, null);
89     }
90     
91     /**
92      * Creates a Jackpot environment and builds its sources.
93      *
94      * @return the number of compilation errors from the build.
95      */

96     public int initialize(String JavaDoc sourcepath, String JavaDoc classpath, String JavaDoc bootclasspath, String JavaDoc sourceLevel, String JavaDoc encoding) throws Exception JavaDoc {
97         if (buildFinished)
98             throw new AssertionError JavaDoc("engine already initialized");
99         JavacTaskImpl task = Builder.createJavacTask(sourcepath, classpath, bootclasspath, sourceLevel, encoding);
100         env = new DefaultEnvironment(task, appContext, sourceLevel);
101     BuildProgress progressBar = appContext.getBuildProgress();
102         Builder builder = new Builder(task, getPaths(sourcepath), progressBar);
103         int errors = 0;
104         try {
105             errors = builder.build();
106         } catch (OutOfMemoryError JavaDoc e) {
107             env = null;
108             System.gc();
109             throw e;
110         } finally {
111         progressBar.dispose();
112     }
113         buildFinished = true;
114         return errors;
115     }
116     
117     /**
118      * Utility method to break apart a path string into an array of its path elements.
119      */

120     private String JavaDoc[] getPaths(String JavaDoc path) {
121         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(path, File.pathSeparator);
122         String JavaDoc[] paths = new String JavaDoc[tok.countTokens()];
123         int i = 0;
124         while (tok.hasMoreTokens())
125             paths[i++] = tok.nextToken();
126         return paths;
127     }
128     
129     public boolean isInitialized() {
130         return buildFinished;
131     }
132
133     public ResultTableModel runCommand(String JavaDoc queryName, String JavaDoc className) throws Exception JavaDoc {
134         return runCommand(queryName, null, className);
135     }
136
137     public ResultTableModel runCommand(String JavaDoc queryName, String JavaDoc transformerName, String JavaDoc className) throws Exception JavaDoc {
138         Query query = null;
139         QueryProgress progressBar = appContext.getQueryProgress();
140         progressBar.setTotalQueries(1);
141         try {
142             query = createCommand(queryName, transformerName, className);
143             if (appContext.setProperties(query, queryName)) {
144                 progressBar.queryStarted(queryName);
145                 query.init();
146                 query.attach(env);
147                 query.apply();
148                 query.release();
149                 query.destroy();
150                 progressBar.queryFinished();
151             }
152             return query.getResult();
153         } catch (EmptyScriptException e) {
154             throw e;
155     } catch (RulesParseException rpe) {
156         throw rpe;
157         } catch (ThreadDeath JavaDoc td) {
158             return query != null ? query.getResult() : null; // user canceled command execution
159
} catch (Throwable JavaDoc t) {
160             throw new EngineException("Error executing operator", t);
161         } finally {
162             progressBar.dispose();
163         }
164     }
165
166     public ResultTableModel runCommands(String JavaDoc querySetName, Query[] queries) throws Exception JavaDoc {
167         MultiTransformer multi = null;
168         QueryProgress progressBar = appContext.getQueryProgress();
169         try {
170             multi = new MultiTransformer(querySetName, queries, progressBar);
171             multi.init();
172             multi.attach(env);
173             multi.apply();
174             ResultTableModel rtm = multi.getResult();
175             multi.release();
176             return rtm;
177         } catch (EmptyScriptException e) {
178             throw e;
179     } catch (RulesParseException rpe) {
180         throw rpe;
181         } catch (ThreadDeath JavaDoc td) {
182             return multi != null ? multi.getResult() : null; // user canceled command execution
183
} catch (Throwable JavaDoc t) {
184             throw new EngineException("Error executing operator", t);
185         } finally {
186             multi.destroy();
187             progressBar.dispose();
188         }
189     }
190     
191     public Query createCommand(String JavaDoc queryName, String JavaDoc transformerName, String JavaDoc className) throws Exception JavaDoc {
192         Class JavaDoc c = createQueryClass(className);
193         Object JavaDoc obj = c.newInstance();
194         if (!(obj instanceof Query))
195             throw new EngineException("I don't know how to handle " + c);
196         Query query = (Query)obj;
197         query.setQueryDescription(queryName);
198         if (query instanceof Transformer && transformerName != null)
199             ((Transformer)query).setRefactoringDescription(transformerName);
200         return query;
201     }
202     
203     public Transformer createScript(String JavaDoc queryName, String JavaDoc transformerName, String JavaDoc path) throws Exception JavaDoc {
204         if (path.startsWith("file:"))
205             path = path.substring(5);
206         final InputStream is;
207         final long lastmod;
208         FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource(path);
209         if (fo != null) {
210             is = fo.getInputStream();
211             lastmod = fo.lastModified().getTime();
212         } else {
213             File f = new File(path);
214             is = new FileInputStream(f); // may throw FileNotFoundException
215
lastmod = f.lastModified();
216         }
217         Reader in = new InputStreamReader(is);
218         Class JavaDoc c = createScriptClass(path, queryName, transformerName, in, lastmod);
219         Object JavaDoc obj = c.newInstance();
220         if (!(obj instanceof Transformer))
221             throw new EngineException("I don't know how to handle " + c);
222         return (Transformer)obj;
223     }
224
225     /**
226      * Executes a rules file script.
227      */

228     public ResultTableModel runScript(String JavaDoc queryName, String JavaDoc transformName, String JavaDoc path) throws Exception JavaDoc {
229         QueryProgress progressBar = appContext.getQueryProgress();
230         progressBar.setTotalQueries(1);
231         try {
232             Transformer query = createScript(queryName, transformName, path);
233             if (appContext.setProperties(query, queryName)) {
234                 progressBar.queryStarted(queryName);
235                 query.init();
236                 query.attach(env);
237                 query.apply();
238                 query.release();
239                 query.destroy();
240                 progressBar.queryFinished();
241             }
242             return query.getResult();
243         } catch (RecursiveRuleException e) {
244             throw e;
245         } catch (EmptyScriptException e) {
246             throw e;
247     } catch (RulesParseException rpe) {
248         throw rpe;
249         } catch (Throwable JavaDoc t) {
250             throw new EngineException("Error executing operator", t);
251         } finally {
252             progressBar.dispose();
253         }
254     }
255
256     private Class JavaDoc createScriptClass(String JavaDoc path, String JavaDoc queryName, String JavaDoc transformDesc, Reader in, long lastmod) throws Exception JavaDoc {
257         TransformParser tp = new TransformParser(path, queryName, transformDesc, in, lastmod, jackpotPath);
258         tp.parseRules();
259         if (!tp.hasRules())
260             throw new EmptyScriptException(queryName);
261         if (tp.hasErrors())
262             throw new RulesParseException(tp.getErrors());
263         Class JavaDoc ret;
264         Throwable JavaDoc t0 = null;
265         try {
266             ret = tp.codeRules();
267         } catch(Throwable JavaDoc t) {
268             t0 = t;
269             ret = null;
270         }
271         if (tp.hasErrors())
272             throw new RulesParseException("script errors:\n" + tp.getErrors());
273         else if(t0 != null)
274             throw new EngineException("script compilation failed", t0);
275         return ret;
276     }
277
278     private Class JavaDoc createQueryClass(final String JavaDoc className) throws Exception JavaDoc {
279         ClassLoader JavaDoc loader = new ClassLoader JavaDoc(getClass().getClassLoader()) {
280             public Class JavaDoc findClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
281                 if (name.endsWith(".class")) {
282                     try {
283                         if (name.startsWith("file://"))
284                             name = name.substring(7);
285                         else if (name.startsWith("file:"))
286                             name = name.substring(5);
287                         FileInputStream in = new FileInputStream(name);
288                         int len0 = in.available();
289                         byte[] b = new byte[len0];
290                         int len1 = in.read(b);
291                         in.close();
292                         if (len1 != len0)
293                             throw new ClassNotFoundException JavaDoc(name + ": read failure");
294                         ClassFile cf = new ClassFile(name);
295                         return defineClass(cf.getName().getExternalName(), b, 0, b.length);
296                     } catch (IOException e) {
297                         throw new ClassNotFoundException JavaDoc("failed loading " + name, e);
298                     }
299                 }
300                 Class JavaDoc c = appContext.getCommandClass(name);
301                 return (c == null) ? super.findClass(name) : c;
302             }
303         };
304         return loader.loadClass(className);
305     }
306         
307     public void undo(boolean erase) {
308         if (!buildFinished)
309             throw new AssertionError JavaDoc("engine not initialized");
310         UndoList undoList = env.getUndoList();
311         undoList.undo();
312         if (erase)
313             undoList.clearRedo();
314     }
315     
316     public void redo() {
317         if (!buildFinished)
318             throw new AssertionError JavaDoc("engine not initialized");
319         env.getUndoList().redo();
320     }
321     
322     public boolean canUndo() {
323         return buildFinished ? env.getUndoList().canUndo() : false;
324     }
325     
326     public boolean canRedo() {
327         return buildFinished ? env.getUndoList().canRedo() : false;
328     }
329     
330     public void applyChanges(final ChangeSet changeSet) {
331         Transformer<Object JavaDoc,Object JavaDoc> t = new Transformer<Object JavaDoc,Object JavaDoc>() {
332             @Override JavaDoc
333             public void init() {
334                 super.init();
335                 this.changes = changeSet;
336             }
337         };
338         t.init();
339         t.attach(env);
340         t.apply();
341         t.release();
342         t.destroy();
343     }
344     
345     public boolean needsCommit() {
346         if (!buildFinished)
347             return false;
348         Commit save = new Commit();
349         return save.isEnabled(env);
350     }
351     
352     /**
353      * Commits changes to source files. Returns true if engine can be released
354      * afterwards, depending upon whether there are changes and what the user
355      * indicated should be done with them.
356      */

357     public boolean commit() throws IOException {
358         if (!buildFinished)
359             throw new AssertionError JavaDoc("engine not initialized");
360         Commit save = new Commit();
361         if (!save.isEnabled(env))
362             return true;
363         save.init();
364         save.attach(env);
365         save.commit();
366         save.release();
367         save.destroy();
368         return true;
369     }
370     
371     public void close() {
372         if (env != null) {
373             UndoList undoList = env.getUndoList();
374             undoList.reset();
375         }
376         env = null;
377         appContext = null;
378         jackpotPath = null;
379         buildFinished = false;
380     }
381
382     public PropertySheetInfo getPropertySheetInfo(String JavaDoc className) {
383         try {
384             Class JavaDoc cls = Class.forName(className);
385             return PropertySheetInfo.find(cls);
386         } catch (Exception JavaDoc e) {
387             return null;
388         }
389     }
390
391     public JavaFormatOptions getFormatOptions() {
392         return JavaFormatOptions.getDefault();
393     }
394     
395     public String JavaDoc format(JavaFileObject source, JavaFormatOptions formatOptions) throws IOException {
396         // compile source
397
Context context = new Context();
398         Options options = Options.instance(context);
399         options.put("-source", "1.5");
400         JavaCompiler comp = new JavaCompiler(context);
401         Log.instance(context).useSource(source);
402         JCTree.JCCompilationUnit unit = comp.parse(source);
403
404         // format it
405
VeryPretty formatter = new VeryPretty(context, formatOptions);
406         unit.accept(formatter);
407         return formatter.toString();
408     }
409 }
410
Popular Tags