KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > fractal > julia > loader > DynamicLoader


1 /***
2  * Julia: France Telecom's implementation of the Fractal API
3  * Copyright (C) 2001-2002 France Telecom R&D
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Contact: Eric.Bruneton@rd.francetelecom.com
20  *
21  * Author: Eric Bruneton
22  */

23
24 package org.objectweb.fractal.julia.loader;
25
26 import org.objectweb.fractal.julia.asm.ClassGenerationException;
27 import org.objectweb.fractal.julia.asm.ClassGenerator;
28
29 import java.io.BufferedOutputStream JavaDoc;
30 import java.io.ByteArrayInputStream JavaDoc;
31 import java.io.File JavaDoc;
32 import java.io.FileOutputStream JavaDoc;
33 import java.io.FileWriter JavaDoc;
34 import java.io.InputStream JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.Map JavaDoc;
37
38 /**
39  * Provides an implementation of the {@link Loader} interface that can
40  * generate classes on the fly.
41  * <br>
42  * <br>
43  * <b>Requirements</b>
44  * <ul>
45  * <li>the Java platform must provide the Java reflection API and the
46  * ClassLoader class.</li>
47  * </ul>
48  */

49
50 public class DynamicLoader extends BasicLoader {
51
52   // -------------------------------------------------------------------------
53
// PUBLIC constructor (needed for bootstrap)
54
// -------------------------------------------------------------------------
55

56   public DynamicLoader () {
57   }
58
59   // -------------------------------------------------------------------------
60
// Fields and methods added and overriden by the mixin class
61
// -------------------------------------------------------------------------
62

63   private String JavaDoc genLog;
64   
65   private String JavaDoc genDir;
66   
67   public void init (final Map JavaDoc context) throws Exception JavaDoc {
68     super.init(context);
69     
70     if (context.get("julia.loader.gen.dir") != null) {
71       genDir = (String JavaDoc)context.get("julia.loader.gen.dir");
72     } else if (System.getProperty("julia.loader.gen.dir") != null) {
73       genDir = System.getProperty("julia.loader.gen.dir");
74     }
75
76     if (context.get("julia.loader.gen.log") != null) {
77       genLog = (String JavaDoc)context.get("julia.loader.gen.log");
78     } else if (System.getProperty("julia.loader.gen.log") != null) {
79       genLog = System.getProperty("julia.loader.gen.log");
80     }
81   }
82   
83   public Class JavaDoc loadClass (final String JavaDoc name, final Object JavaDoc loader)
84     throws ClassNotFoundException JavaDoc
85   {
86     return PublicClassLoader.getInstance(getClassLoader(loader)).loadClass(name);
87   }
88
89   protected Class JavaDoc generateClass (
90     final String JavaDoc name,
91     final Tree classDescriptor,
92     final Object JavaDoc loader) throws ClassNotFoundException JavaDoc
93   {
94     ClassLoader JavaDoc cl = getClassLoader(loader);
95     ClassGenerator classGen = null;
96     try {
97       classGen = (ClassGenerator)newObject(classDescriptor.getSubTree(0), loader);
98     } catch (ClassCastException JavaDoc e) {
99       throw new ClassGenerationException(
100         null,
101         classDescriptor.toString(),
102         "The class generator is not an instance of ClassGenerator");
103     } catch (Exception JavaDoc e) {
104       throw new ClassGenerationException(
105         e, classDescriptor.toString(), "Cannot create the class generator");
106     }
107     byte[] b = classGen.generateClass(name, classDescriptor, this, cl);
108     if (genLog != null) {
109       String JavaDoc line = classDescriptor.toString();
110       if (genLog.equals("out")) {
111         System.out.println(line);
112       } else if (genLog.equals("err")) {
113         System.err.println(line);
114       } else {
115         try {
116           FileWriter JavaDoc fw = new FileWriter JavaDoc(genLog, true);
117           fw.write(line);
118           fw.write('\n');
119           fw.close();
120         } catch (Exception JavaDoc e) {
121           e.printStackTrace();
122         }
123       }
124     }
125     if (genDir != null) {
126       try {
127         String JavaDoc pkg;
128         String JavaDoc cls;
129         int dot = name.lastIndexOf('.');
130         if (dot > 0) {
131           pkg = name.substring(0, dot).replace('.', File.separatorChar);
132           cls = name.substring(dot + 1);
133         } else {
134           pkg = "";
135           cls = name;
136         }
137         File JavaDoc dirFile = new File JavaDoc(new File JavaDoc(genDir), pkg);
138         if (!dirFile.exists()) {
139           dirFile.mkdirs();
140         }
141         File JavaDoc classFile = new File JavaDoc(dirFile, cls + ".class");
142         BufferedOutputStream JavaDoc bos =
143           new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(classFile));
144         bos.write(b);
145         bos.close();
146       } catch (Exception JavaDoc e) {
147         e.printStackTrace();
148       }
149     }
150     return PublicClassLoader.getInstance(cl).defineClass(name, b);
151   }
152
153   private ClassLoader JavaDoc getClassLoader (final Object JavaDoc loader) {
154     if (loader instanceof ClassLoader JavaDoc) {
155       return (ClassLoader JavaDoc)loader;
156     } else if (loader != null) {
157       return loader.getClass().getClassLoader();
158     } else {
159       return getClass().getClassLoader();
160     }
161   }
162   
163   /**
164    * Provides a {@link ClassLoader} with a public {@link ClassLoader#defineClass
165    * defineClass} method.
166    */

167
168   static class PublicClassLoader extends ClassLoader JavaDoc {
169
170     /**
171      * A map associating loaders to their parent class loader.
172      */

173
174     private final static Map JavaDoc INSTANCES = new HashMap JavaDoc();
175
176     /**
177      * Byte code of the dynamically generated classes.
178      */

179
180     private Map JavaDoc bytecodes = new HashMap JavaDoc();
181
182     /**
183      * Constructs a {@link PublicClassLoader} with the given parent class
184      * loader.
185      *
186      * @param parent the parent class loader.
187      */

188
189     private PublicClassLoader (final ClassLoader JavaDoc parent) {
190       super(parent);
191     }
192
193     /**
194      * Returns the PublicClassLoader whose parent class loader is equal to the
195      * given loader.
196      *
197      * @param parent the parent class loader.
198      * @return the PublicClassLoader whose parent class loader is equal to the
199      * given loader.
200      */

201
202     public static PublicClassLoader getInstance (final ClassLoader JavaDoc parent) {
203       synchronized (INSTANCES) {
204         PublicClassLoader instance = (PublicClassLoader)INSTANCES.get(parent);
205         if (instance == null) {
206           instance = new PublicClassLoader(parent);
207           INSTANCES.put(parent, instance);
208         }
209         return instance;
210       }
211     }
212
213     /**
214      * Converts an array of bytes into an instance of class {@link Class}.
215      *
216      * @param name the name of the class.
217      * @param b the class bytes.
218      * @return the {@link Class} object created from the data.
219      */

220
221     public Class JavaDoc defineClass (final String JavaDoc name, final byte[] b) {
222       bytecodes.put(name.replace('.', '/') + ".class", b);
223       return defineClass(name, b, 0, b.length);
224     }
225
226     public InputStream JavaDoc getResourceAsStream (final String JavaDoc name) {
227       InputStream JavaDoc is = super.getResourceAsStream(name);
228       if (is == null) {
229         byte[] b = (byte[])bytecodes.get(name);
230         if (b != null) {
231           is = new ByteArrayInputStream JavaDoc(b);
232         }
233       }
234       return is;
235     }
236   }
237 }
238
Popular Tags