KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > script > PluginCompiler


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.script;
21
22 import com.sun.tools.javac.util.DefaultFileManager;
23 import com.sun.tools.javac.main.*;
24 import com.sun.tools.javac.util.*;
25
26 import java.io.*;
27 import javax.tools.JavaFileManager;
28 import javax.tools.JavaFileObject;
29
30 /** Helper class for algorithmically generating java source code, then
31     compiling it and plugging it back into the current system. This is most
32     often used when you want to use Java like a scripting language and allow
33     users to imbed Java source code fragments in (for example) menu actions,
34     and then have them transform into runnable classes.
35     When compiling and running this class, you must pass in the jar file
36     containing the javac classes to use, such as tools.jar from a JDK directory.
37     The canonical usage pattern is:
38     <pre>
39     PluginCompiler pc = new PluginCompiler(); // don't have to "new" each time:
40                           // instances can be reused
41     String scriptSourceName = ...; // some unique name to identify
42                           // this script -- often it's
43                           // source file
44     if (pc.needsGeneration(scriptSourceName)) {
45     // come here if the cached compiled class file is out of date w.r.t
46     // the script. Generate the .java file for the script:
47     pc.startGeneration();
48     pc.write("public class ");
49     pc.writeClassName();
50     pc.write("extends SomeUsefulInterface");
51     pc.write(" { public ");
52     pc.writeClassName();
53     pc.write("() { System.err.println(\"Hello from the constructor of \"+this.getClass().getName());}\n");
54     Reader in = new BufferedReader(new FileReader(scriptSourceName));
55     Parse the script from "in", outputting the results via:
56     pc.write(methods to implement SomeUsefulInterface);
57     pc.write("}\n");
58     }
59     Class c = pc.loadClass(); // Compile the .java file if
60                           // necessary; load the .class
61                           // regardless
62     SomeUsefulInterface o = (SomeUsefulInterface) c.newInstance();
63     // do whatever you want with it
64 </pre>
65     */

66 public class PluginCompiler {
67
68     private static final File generatedCodeDir;
69     private final ClassLoader JavaDoc classloader = new ClassLoader JavaDoc(getClass().getClassLoader()) {
70     public Class JavaDoc findClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
71         try {
72         FileInputStream in = new FileInputStream(new File(generatedCodeDir, name + ".class"));
73         int len0 = in.available();
74         byte[] b = new byte[len0];
75         int len1 = in.read(b);
76         in.close();
77         if (len1 != len0)
78             throw new ClassNotFoundException JavaDoc("read failure");
79         return defineClass(name, b, 0, b.length);
80         } catch(Throwable JavaDoc t) {
81         ClassNotFoundException JavaDoc cnf;
82         if (t instanceof ClassNotFoundException JavaDoc)
83             cnf = (ClassNotFoundException JavaDoc) t;
84         else
85             cnf = new ClassNotFoundException JavaDoc("load failure", t);
86         throw cnf;
87         }
88     }
89     };
90
91     static {
92         File cb = new File(System.getProperty("user.home"), ".jackpot");
93         if (!cb.exists() && !cb.mkdirs()) {
94             File tmp = null;
95             try {
96                 tmp = File.createTempFile("HOHO", null);
97                 cb = new File(tmp.getParentFile(),
98                               "PluginCache-"+System.getProperty("user.name","user"));
99             }
100             catch(IOException ioe) {
101                 cb = new File("/tmp/AuxPluginCache");
102             }
103             finally {
104                 if (tmp != null)
105                     tmp.delete();
106             }
107             cb.mkdirs();
108         }
109     generatedCodeDir = cb;
110     }
111
112     private String JavaDoc className;
113     private File source;
114     private File genJava;
115     private LineWriter out;
116     private static int seq = 0;
117     public boolean needsGeneration(String JavaDoc s, long lastModified, boolean force) {
118     int src = 0;
119     int dst = 0;
120     char [] nbuf;
121     if (s != null) {
122         source = new File(s);
123         int limit = s.length();
124         nbuf = new char[(limit < 2 ? 10 : limit) + 6];
125         while (src < limit) {
126         char c = s.charAt(src++);
127         if (dst > 0) {
128             if (Character.isJavaIdentifierPart(c))
129             nbuf[dst++] = c;
130             else if (nbuf[dst - 1] != '_')
131             nbuf[dst++] = '_';
132         } else if (Character.isJavaIdentifierStart(c))
133             nbuf[dst++] = c;
134         }
135         while (dst > 0 && nbuf[dst - 1] == '_')
136         dst--;
137     } else {
138         source = null;
139         nbuf = new char[12];
140     }
141     if (dst == 0) {
142         nbuf[dst++] = 'C';
143         int ls = seq++;
144         do {
145         nbuf[dst++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef".charAt(ls & 31);
146         ls >>>= 5;
147         } while (ls != 0);
148     }
149     className = new String JavaDoc(nbuf, 0, dst);
150         String JavaDoc javaName = new String JavaDoc(nbuf, 0, addExt(nbuf, dst, ".java"));
151     genJava = new File(generatedCodeDir, javaName);
152         File genClass = new File(generatedCodeDir, javaName.replace(".java", ".class"));
153     out = null;
154     if(force) return true;
155     long sm = lastModified > 0 ? lastModified : source != null ? source.lastModified() : 0;
156     return sm <= 0 || sm >= genClass.lastModified();
157     }
158     private static int addExt(char[] buf, int st, String JavaDoc ext) {
159     int limit = ext.length();
160     for (int i = 0; i < limit; i++)
161         buf[st + i] = ext.charAt(i);
162     return st + limit;
163     }
164     public void startGeneration()
165     throws IOException
166     {
167     out = new LineWriter(new FileWriter(genJava));
168     }
169     public void write(String JavaDoc s)
170     throws IOException
171     {
172     out.write(s);
173     }
174     public void write(int i) throws IOException {
175     if(i<0) {
176         out.write('-');
177         i = -i;
178     }
179     if(i>=10) write(i/10);
180     out.write((char)('0'+i%10));
181     }
182     public void write(long i) throws IOException {
183     if(i<0) {
184         out.write('-');
185         i = -i;
186     }
187     if(i>=10) write(i/10);
188     out.write((char)('0'+i%10));
189     }
190         
191     public void writeClassName()
192     throws IOException
193     {
194     out.write(className);
195     }
196     public void write(char c)
197     throws IOException
198     {
199     out.write(c);
200     }
201     private static final char[] hexChars = "0123456789ABCDEF".toCharArray();
202     private static final char backslash = '\\';
203     private static void oneChar(Writer out, char c)
204     throws IOException
205     {
206     if (c < 040 || c == '\'' || c >= 127 && c <= 0377) {
207         out.write(backslash);
208         out.write(hexChars[(c >>> 6) & 7]);
209         out.write(hexChars[(c >>> 3) & 7]);
210         out.write(hexChars[(c >>> 0) & 7]);
211         } else if (c == '"') {
212             out.write('\\');
213             out.write('"');
214     } else if (c < 127)
215         out.write(c);
216     else {
217         out.write(backslash);
218         out.write('u');
219         out.write(hexChars[(c >>> 12) & 0xF]);
220         out.write(hexChars[(c >>> 8) & 0xF]);
221         out.write(hexChars[(c >>> 4) & 0xF]);
222         out.write(hexChars[(c >>> 0) & 0xF]);
223     }
224     }
225     public void writeQuoted(String JavaDoc s)
226     throws IOException
227    {
228     Writer out = this.out;
229     if (s == null)
230         out.write("null");
231     else {
232         int limit = s.length();
233         out.write('"');
234         for (int i = 0; i < limit; i++)
235         oneChar(out, s.charAt(i));
236         out.write('"');
237     }
238     }
239     public void writeCapitalizedIdent(String JavaDoc s)
240     throws IOException
241    {
242     Writer out = this.out;
243     if (s == null)
244         out.write("NULL");
245     else {
246         int limit = s.length();
247         boolean start = true;
248         for (int i = 0; i < limit; i++) {
249         char c = s.charAt(i);
250         if(Character.isJavaIdentifierPart(c)) {
251             if(start && Character.isLowerCase(c))
252             c = Character.toLowerCase(c);
253             out.write(c);
254             start = false;
255         } else start=true;
256         }
257     }
258     }
259     public void writeQuoted(char c)
260     throws IOException
261     {
262     out.write('\'');
263     oneChar(out, c);
264     out.write('\'');
265     }
266     public Writer getWriter() { return out; }
267     
268     public int getCurrentLineNumber() {
269         return out.getLineNumber();
270     }
271     
272 /* public static void main(String[] args) {
273     try {
274         PluginCompiler pc = new PluginCompiler ();
275         if (pc.needsGeneration("Yo Ho!")) {
276         pc.startGeneration();
277         pc.write("public class ");
278         pc.writeClassName();
279         pc.write(" { public ");
280         pc.writeClassName();
281         pc.write("() { System.err.println(\"Hello from \"+this.getClass().getName());}}\n");
282         }
283         pc.loadClass().newInstance();
284     } catch(Throwable t) {
285         System.err.flush();
286         t.printStackTrace();
287     }
288     } */

289
290     ScriptParser.ScriptLog log;
291
292     public Class JavaDoc loadClass(String JavaDoc javacpath) throws IOException {
293     if (out != null) {
294         out.close();
295         Context context = new Context();
296             DefaultFileManager.preRegister(context);
297         log = new ScriptParser.ScriptLog(context);
298         Options options = Options.instance(context);
299         String JavaDoc gcd = generatedCodeDir.toString();
300         options.put("-source", "1.5");
301             options.put("-target", "1.5");
302         options.put("-d", gcd);
303         options.put("-sourcepath", gcd);
304             options.put("-g", "-g");
305             if (javacpath != null)
306                 options.put("-Xbootclasspath/p:", javacpath);
307             DefaultFileManager fileManager = new DefaultFileManager(context, true, null);
308             JavaFileObject fileobject = fileManager.getFileForInput(genJava.toString());
309         List<JavaFileObject> filenames = List.of(fileobject);
310         JavaCompiler comp = new JavaCompiler(context);
311         log.useSource(fileobject);
312         try {
313         comp.compile(filenames);
314         if(hasErrors())
315             throw new IOException("Compilation errors");
316         } catch(Throwable JavaDoc t) {
317         IOException ioe = new IOException("Class " + className + " compilation exception");
318         ioe.initCause(t);
319         throw ioe;
320         }
321     }
322     try {
323         return classloader.loadClass(className);
324     } catch(ClassNotFoundException JavaDoc cnf) {
325         IOException ioe = new IOException("Class " + className + " not found");
326         ioe.initCause(cnf);
327         throw ioe;
328     }
329     }
330     public boolean hasErrors() { return log!=null && log.hasErrors(); }
331     public String JavaDoc getErrors() { return log==null ? null : log.getErrors(); }
332     
333     /**
334      * BufferedWriter which tracks the current line number of written text.
335      */

336     private static class LineWriter extends BufferedWriter {
337         int line = 0;
338         LineWriter(Writer out) {
339             super(out);
340         }
341         public void write(String JavaDoc s, int off, int len) throws IOException {
342             write(s.toCharArray(), off, len);
343         }
344         public void write(char[] cbuf, int off, int len) throws IOException {
345             super.write(cbuf, off, len);
346             for (int i = off; i < len; i++)
347                 if (cbuf[i] == '\n')
348                     line++;
349         }
350         public void write(int c) throws IOException {
351             super.write(c);
352             if (c == '\n')
353                 line++;
354         }
355         public void newLine() throws IOException {
356             super.newLine();
357             line++;
358         }
359         int getLineNumber() {
360             return line;
361         }
362     }
363 }
364
Popular Tags