source: branches/0.22.x/abcl/src/org/armedbear/lisp/JavaClassLoader.java

Last change on this file was 12802, checked in by Mark Evenson, 14 years ago

Re-apply grovel tags patch.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.4 KB
Line 
1/*
2 * JavaClassLoader.java
3 *
4 * Copyright (C) 2003-2005 Peter Graves
5 * $Id: JavaClassLoader.java 12802 2010-07-12 09:51:19Z mevenson $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38import java.util.Collections;
39import java.util.HashSet;
40import java.util.Set;
41import java.net.URL;
42import java.net.URLClassLoader;
43
44public class JavaClassLoader extends URLClassLoader {
45
46    private static JavaClassLoader persistentInstance;
47
48    private static Set<String> packages = Collections.synchronizedSet(new HashSet<String>());
49
50    public JavaClassLoader()
51    {
52        this(JavaClassLoader.class.getClassLoader());
53    }
54
55    public JavaClassLoader(ClassLoader parent) {
56  super(new URL[] {}, parent);
57    }
58
59    public JavaClassLoader(URL[] classpath, ClassLoader parent) {
60  super(classpath, parent);
61    }
62
63    public static JavaClassLoader getPersistentInstance()
64    {
65        return getPersistentInstance(null);
66    }
67
68    public static JavaClassLoader getPersistentInstance(String packageName)
69    {
70        if (persistentInstance == null)
71            persistentInstance = new JavaClassLoader();
72  definePackage(packageName);
73        return persistentInstance;
74    }
75
76    private static void definePackage(String packageName)
77    {
78        if (packageName != null && !packages.contains(packageName)) {
79            persistentInstance.definePackage(packageName,"","1.0","","","1.0","",null);
80            packages.add(packageName);
81        }
82    }
83
84    public Class<?> loadClassFromByteArray(byte[] classbytes) {
85        return loadClassFromByteArray(null, classbytes);
86    }
87
88    public Class<?> loadClassFromByteArray(String className,
89                                                byte[] classbytes)
90    {
91        try {
92            long length = classbytes.length;
93            if (length < Integer.MAX_VALUE) {
94                Class<?> c =
95                    defineClass(className, classbytes, 0, (int) length);
96                if (c != null) {
97                    resolveClass(c);
98                    return c;
99                }
100            }
101        }
102      catch (LinkageError e) {
103                throw e;
104      }
105        catch (Throwable t) {
106            Debug.trace(t);
107        }
108        return null;
109    }
110
111    public Class<?> loadClassFromByteArray(String className, byte[] bytes,
112                                                int offset, int length)
113    {
114        try {
115            Class<?> c = defineClass(className, bytes, offset, length);
116            if (c != null) {
117                resolveClass(c);
118                return c;
119            }
120        }
121        catch (VerifyError e)
122          {
123            error(new LispError("Class verification failed: " + e.getMessage()));
124          }
125        catch (Throwable t) {
126            Debug.trace(t);
127        }
128        return null;
129    }
130
131    @Override
132    public void addURL(URL url) {
133  super.addURL(url);
134    }
135
136    public static final Symbol CLASSLOADER = PACKAGE_JAVA.intern("*CLASSLOADER*");
137
138    private static final Primitive GET_DEFAULT_CLASSLOADER = new pf_get_default_classloader();
139    private static final class pf_get_default_classloader extends Primitive {
140 
141  private final LispObject defaultClassLoader = new JavaObject(new JavaClassLoader());
142
143        pf_get_default_classloader() {
144            super("get-default-classloader", PACKAGE_JAVA, true, "");
145        }
146
147        @Override
148        public LispObject execute() {
149      return defaultClassLoader;
150        }
151    };
152
153    // ### make-classloader &optional parent => java-class-loader
154    private static final Primitive MAKE_CLASSLOADER = new pf_make_classloader();
155    private static final class pf_make_classloader extends Primitive
156    {
157        pf_make_classloader() 
158        {
159            super("make-classloader", PACKAGE_JAVA, true, "&optional parent");
160        }
161
162        @Override
163        public LispObject execute() {
164      return new JavaObject(new JavaClassLoader(getCurrentClassLoader()));
165        }
166
167        @Override
168        public LispObject execute(LispObject parent) {
169      return new JavaObject(new JavaClassLoader((ClassLoader) parent.javaInstance(ClassLoader.class)));
170        }
171    };
172
173    // ### dump-classpath &optional classloader => list-of-pathname-lists
174    private static final Primitive DUMP_CLASSPATH = new pf_dump_classpath();
175    private static final class pf_dump_classpath extends Primitive
176    {
177        pf_dump_classpath() 
178        {
179            super("dump-classpath", PACKAGE_JAVA, true, "&optional classloader");
180        }
181
182        @Override
183        public LispObject execute() {
184      return execute(new JavaObject(getCurrentClassLoader()));
185        }
186
187        @Override
188        public LispObject execute(LispObject classloader) {
189      LispObject list = NIL;
190      Object o = classloader.javaInstance();
191      while(o instanceof ClassLoader) {
192    ClassLoader cl = (ClassLoader) o;
193    list = list.push(dumpClassPath(cl));
194    o = cl.getParent();
195      }
196      return list.nreverse();
197        }
198    };
199
200    // ### add-to-classpath jar-or-jars &optional (classloader (get-current-classloader))
201    private static final Primitive ADD_TO_CLASSPATH = new pf_add_to_classpath();
202    private static final class pf_add_to_classpath extends Primitive
203    {
204        pf_add_to_classpath() 
205        {
206            super("add-to-classpath", PACKAGE_JAVA, true, "jar-or-jars &optional (classloader (get-current-classloader))");
207        }
208
209        @Override
210        public LispObject execute(LispObject jarOrJars) {
211      return execute(jarOrJars, new JavaObject(getCurrentClassLoader()));
212        }
213
214        @Override
215        public LispObject execute(LispObject jarOrJars, LispObject classloader) {
216      Object o = classloader.javaInstance();
217      if(o instanceof JavaClassLoader) {
218    JavaClassLoader jcl = (JavaClassLoader) o;
219    if(jarOrJars instanceof Cons) {
220        while(jarOrJars != NIL) {
221      addURL(jcl, jarOrJars.car());
222      jarOrJars = jarOrJars.cdr();
223        }
224    } else {
225        addURL(jcl, jarOrJars);
226    }
227    return T;
228      } else {
229    return error(new TypeError(o + " must be an instance of " + JavaClassLoader.class.getName()));
230      }
231        }
232    };
233
234    protected static void addURL(JavaClassLoader jcl, LispObject jar) {
235  try {
236      if(jar instanceof Pathname) {
237    jcl.addURL(((Pathname) jar).toURL());
238      } else if(jar instanceof AbstractString) {
239    jcl.addURL(new Pathname(jar.toString()).toURL());
240      } else {
241    error(new TypeError(jar + " must be a pathname designator"));
242      }
243  } catch(java.net.MalformedURLException e) {
244      error(new LispError(jar + " is not a valid URL"));
245  }
246    }
247
248
249    public static LispObject dumpClassPath(ClassLoader o) {
250  if(o instanceof URLClassLoader) {
251      LispObject list = NIL;
252      for(URL u : ((URLClassLoader) o).getURLs()) {
253    list = list.push(new Pathname(u));
254      }
255      return new Cons(new JavaObject(o), list.nreverse());
256  } else {
257      return new JavaObject(o);
258  }
259    }
260
261    public static ClassLoader getCurrentClassLoader() {
262  LispObject classLoader = CLASSLOADER.symbolValueNoThrow();
263  if(classLoader != null) {
264      return (ClassLoader) classLoader.javaInstance(ClassLoader.class);
265  } else {
266      return Lisp.class.getClassLoader();
267  }
268    }
269
270
271
272}
Note: See TracBrowser for help on using the repository browser.