KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > java > gen > JavaClassGenerator


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.java.gen;
31
32 import com.caucho.java.JavaCompiler;
33 import com.caucho.java.JavaWriter;
34 import com.caucho.loader.DynamicClassLoader;
35 import com.caucho.loader.SimpleLoader;
36 import com.caucho.loader.enhancer.EnhancingClassLoader;
37 import com.caucho.server.util.CauchoSystem;
38 import com.caucho.util.CharBuffer;
39 import com.caucho.util.L10N;
40 import com.caucho.vfs.MergePath;
41 import com.caucho.vfs.Path;
42 import com.caucho.vfs.Vfs;
43 import com.caucho.vfs.WriteStream;
44
45 import java.io.IOException JavaDoc;
46 import java.lang.reflect.Method JavaDoc;
47 import java.util.ArrayList JavaDoc;
48 import java.util.logging.Level JavaDoc;
49 import java.util.logging.Logger JavaDoc;
50
51 /**
52  * Factory for generating Java classes.
53  */

54 public class JavaClassGenerator {
55   private static final L10N L = new L10N(JavaClassGenerator.class);
56   private static final Logger JavaDoc log
57     = Logger.getLogger(JavaClassGenerator.class.getName());
58   
59   // Parent class loader
60
private ClassLoader JavaDoc _parentLoader;
61   // class loader
62
private ClassLoader JavaDoc _loader;
63
64   private String JavaDoc _encoding;
65   
66   // The search path
67
private Path _searchPath;
68
69   // The work directory
70
private Path _workPath;
71
72   private ArrayList JavaDoc<String JavaDoc> _pendingFiles = new ArrayList JavaDoc<String JavaDoc>();
73
74   private String JavaDoc _initMethod = "_caucho_init";
75   private String JavaDoc _isModifiedMethod = "_caucho_is_modified";
76
77   /**
78    * Sets the full generated class.
79    */

80   public static String JavaDoc cleanClassName(String JavaDoc className)
81   {
82     CharBuffer cb = new CharBuffer();
83     
84     for (int i = 0; i < className.length(); i++) {
85       char ch = className.charAt(i);
86
87       if (ch == '.' || ch == '/')
88     cb.append('.');
89       else if (Character.isJavaIdentifierPart(ch))
90     cb.append(ch);
91       else
92     cb.append('_');
93     }
94
95     return cb.toString();
96   }
97
98   /**
99    * Returns the default merge path
100    */

101   public static Path getDefaultSearchPath()
102   {
103     MergePath mergePath = new MergePath();
104     
105     mergePath.addMergePath(Vfs.lookup());
106     mergePath.addClassPath();
107
108     return mergePath;
109   }
110   
111   /**
112    * Sets the search path.
113    */

114   public void setSearchPath(Path path)
115   {
116     _searchPath = path;
117   }
118
119   /**
120    * Returns the assigned search path.
121    */

122   public Path getSearchPath()
123   {
124     return _searchPath;
125   }
126   
127   public void setEncoding(String JavaDoc encoding)
128   {
129     _encoding = encoding;
130   }
131   
132   /**
133    * Sets the parent class loader.
134    *
135    * @param loader parent class loader
136    */

137   public void setParentLoader(ClassLoader JavaDoc loader)
138   {
139     if (loader instanceof EnhancingClassLoader) {
140       EnhancingClassLoader enhancingLoader = (EnhancingClassLoader) loader;
141     }
142     
143     _parentLoader = loader;
144   }
145   
146   /**
147    * Sets the class loader.
148    *
149    * @param loader parent class loader
150    */

151   public void setLoader(ClassLoader JavaDoc loader)
152   {
153     _loader = loader;
154   }
155   
156   /**
157    * Gets the class loader.
158    */

159   public ClassLoader JavaDoc getClassLoader()
160   {
161     return _loader;
162     /*
163     if (_loader == null) {
164       _loader = SimpleLoader.create(getParentLoader(),
165                     getWorkDir());
166     }
167     
168     return _loader;
169     */

170   }
171
172   /**
173    * Sets the parent class loader.
174    *
175    * @return the parent class loader
176    */

177   public ClassLoader JavaDoc getParentLoader()
178   {
179     if (_parentLoader == null)
180       _parentLoader = Thread.currentThread().getContextClassLoader();
181     
182     return _parentLoader;
183   }
184
185   /**
186    * Sets the parent class loader.
187    *
188    * @return the parent class loader
189    */

190   public ClassLoader JavaDoc getPreloadLoader()
191   {
192     return Thread.currentThread().getContextClassLoader();
193
194       /*
195       if (_preloadLoader instanceof EnhancingClassLoader) {
196     EnhancingClassLoader enhancingLoader;
197     enhancingLoader = (EnhancingClassLoader) _preloadLoader;
198     _preloadLoader = enhancingLoader.getRawLoader();
199       }
200       */

201   }
202
203   /**
204    * Sets the work path for the generated class.
205    */

206   public void setWorkDir(Path workPath)
207   {
208     _workPath = workPath;
209   }
210   
211   /**
212    * Returns the class dir for the generated class.
213    */

214   public Path getWorkDir()
215   {
216     if (_workPath == null)
217       return CauchoSystem.getWorkPath();
218     else
219       return _workPath;
220   }
221
222   /**
223    * Try to preload the class.
224    *
225    * @return true if the preloaded class is still valid.
226    */

227   public Class JavaDoc preload(String JavaDoc fullClassName)
228   {
229     try {
230       return loadClass(fullClassName, true);
231     } catch (ClassNotFoundException JavaDoc e) {
232       log.log(Level.FINEST, e.toString(), e);
233       
234       return null;
235     }
236   }
237
238   /**
239    * Call to generate the java source.
240    */

241   public void generate(GenClass javaClass)
242     throws Exception JavaDoc
243   {
244     String JavaDoc className = javaClass.getFullClassName();
245     String JavaDoc javaPathName = className.replace('.', '/') + ".java";
246     String JavaDoc classPathName = className.replace('.', '/') + ".class";
247
248     Path javaPath = getWorkDir().lookup(javaPathName);
249     Path classPath = getWorkDir().lookup(classPathName);
250
251     try {
252       classPath.remove();
253     } catch (IOException JavaDoc e) {
254     }
255
256     javaPath.getParent().mkdirs();
257
258     WriteStream os = javaPath.openWrite();
259     try {
260       if (_encoding != null)
261     os.setEncoding(_encoding);
262       
263       JavaWriter out = new JavaWriter(os);
264
265       javaClass.generate(out);
266     } finally {
267       os.close();
268     }
269
270     _pendingFiles.add(javaPathName);
271   }
272
273   public void addPendingFile(String JavaDoc javaPath)
274   {
275     _pendingFiles.add(javaPath);
276   }
277
278   /**
279    * Compiles the Java code
280    */

281   public Class JavaDoc compile(String JavaDoc fullClassName)
282     throws Exception JavaDoc
283   {
284     compileJava(fullClassName);
285     
286     return loadClass(fullClassName, false);
287   }
288   
289   /**
290    * Compiles the class.
291    */

292   public void compileJava(String JavaDoc fullClassName)
293     throws IOException JavaDoc, ClassNotFoundException JavaDoc
294   {
295     JavaCompiler compiler = JavaCompiler.create(getPreloadLoader());
296
297     compiler.setClassLoader(getPreloadLoader());
298     compiler.setClassDir(getWorkDir());
299
300     if (_encoding != null)
301       compiler.setEncoding(_encoding);
302
303     compiler.compile(fullClassName.replace('.', '/') + ".java", null);
304   }
305   
306   /**
307    * Compiles the pending files
308    */

309   public void compilePendingJava()
310     throws IOException JavaDoc, ClassNotFoundException JavaDoc
311   {
312     JavaCompiler compiler = JavaCompiler.create(getPreloadLoader());
313
314     compiler.setClassLoader(getPreloadLoader());
315     compiler.setClassDir(getWorkDir());
316
317     if (_encoding != null)
318       compiler.setEncoding(_encoding);
319
320     String JavaDoc []files = new String JavaDoc[_pendingFiles.size()];
321     _pendingFiles.toArray(files);
322     _pendingFiles.clear();
323
324     compiler.compileBatch(files);
325   }
326
327   /**
328    * Loads the generated class. If any class dependencies have
329    * changed, return null.
330    */

331   public Class JavaDoc loadClass(String JavaDoc fullClassName)
332     throws ClassNotFoundException JavaDoc
333   {
334     return loadClass(fullClassName, false);
335   }
336
337   /**
338    * Loads the generated class. If any class dependencies have
339    * changed, return null.
340    */

341   public Class JavaDoc loadClass(String JavaDoc fullClassName, boolean preload)
342     throws ClassNotFoundException JavaDoc
343   {
344     DynamicClassLoader preloadLoader = null;
345     
346     try {
347       ClassLoader JavaDoc loader;
348
349       if (preload) {
350     preloadLoader = SimpleLoader.create(getPreloadLoader(),
351                         getWorkDir(),
352                         fullClassName);
353
354     // needed for cases like Amber enhancing
355
preloadLoader.setServletHack(true);
356     loader = preloadLoader;
357       }
358       else {
359     // XXX: because of automatic instantiation, might cause trouble
360
loader = getClassLoader();
361
362     if (loader == null) {
363       loader = SimpleLoader.create(getParentLoader(),
364                        getWorkDir(),
365                        fullClassName);
366     }
367       }
368
369       Class JavaDoc cl = Class.forName(fullClassName, false, loader);
370
371       if (cl == null)
372     return null;
373       
374       if (! preload)
375     return cl;
376
377       if (isModified(cl))
378     return null;
379
380       if (_loader != null)
381     loader = _loader;
382       else {
383     loader = SimpleLoader.create(getParentLoader(),
384                      getWorkDir(),
385                      fullClassName);
386       }
387
388       return Class.forName(fullClassName, false, loader);
389     } catch (RuntimeException JavaDoc e) {
390       if (! preload)
391     throw e;
392       else
393     return null;
394     } catch (Error JavaDoc e) {
395       if (! preload)
396     throw e;
397       else
398     return null;
399     } catch (ClassNotFoundException JavaDoc e) {
400       if (! preload)
401     throw e;
402       else
403     return null;
404     } finally {
405       if (preloadLoader != null)
406     preloadLoader.destroy();
407     }
408   }
409
410   /**
411    * Returns true if the class is modified.
412    */

413   public boolean isModified(Class JavaDoc cl)
414   {
415     Path searchPath = getSearchPath();
416       
417     if (searchPath == null)
418       searchPath = getDefaultSearchPath();
419
420     try {
421       Method JavaDoc method = cl.getMethod(_initMethod, new Class JavaDoc[] { Path.class });
422       method.invoke(null, new Object JavaDoc[] { searchPath });
423
424       method = cl.getMethod(_isModifiedMethod, new Class JavaDoc[0]);
425       Boolean JavaDoc value = (Boolean JavaDoc) method.invoke(null, new Object JavaDoc[] {});
426
427       return value.booleanValue();
428     } catch (NoSuchMethodException JavaDoc e) {
429       return false;
430     } catch (Throwable JavaDoc e) {
431       log.warning(e.toString());
432       
433       return true;
434     }
435   }
436 }
437
Popular Tags