source: branches/0.15.x/abcl/src/org/armedbear/lisp/JavaClass.java

Last change on this file was 11590, checked in by astalla, 17 years ago

Merged the scripting branch, providing JSR-223 support and other new
features. JSR-233 is only built if the necessary javax.script.* classes
are found in the CLASSPATH.

File size: 4.4 KB
Line 
1/*
2 * BuiltInClass.java
3 *
4 * Copyright (C) 2003-2007 Peter Graves
5 * $Id: BuiltInClass.java 11297 2008-08-31 13:26:45Z ehuelsmann $
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
22package org.armedbear.lisp;
23
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.LinkedList;
27import java.util.Map;
28import java.util.Queue;
29import java.util.Set;
30import java.util.Stack;
31
32public class JavaClass extends LispClass {
33
34  private Class<?> javaClass;
35  //There is no point for this Map to be weak since values keep a reference to the corresponding
36  //key (the Java class). This should not be a problem since Java classes are limited in number -
37  //if they grew indefinitely, the JVM itself would crash.
38  private static final Map<Class<?>, JavaClass> cache = new HashMap<Class<?>, JavaClass>();
39
40  private JavaClass(Class<?> javaClass) {
41    this.javaClass = javaClass;
42    setDirectSuperclass(BuiltInClass.JAVA_OBJECT);
43  }
44
45  private void initCPL() {
46    LispObject cpl = Lisp.NIL;
47    try {
48      cpl = cpl.push(BuiltInClass.CLASS_T);
49      cpl = cpl.push(BuiltInClass.JAVA_OBJECT);
50      Set<Class<?>> alreadySeen = new HashSet<Class<?>>();
51      Stack<JavaClass> stack = new Stack<JavaClass>();
52      Class<?> theClass = javaClass;
53      boolean stop = false;
54      while(!stop && theClass != null) {
55        stop = addClass(alreadySeen, stack, theClass);
56        for(Class<?> c : theClass.getInterfaces()) {
57          stop = addClass(alreadySeen, stack, c) && stop; //watch out for short-circuiting!
58        }
59        theClass = theClass.getSuperclass();
60      }
61      while(!stack.isEmpty()) {
62        cpl = cpl.push(stack.pop());
63      }
64    } catch (ConditionThrowable e) {
65      throw new Error("Cannot push class in class precedence list", e);
66    }
67    setCPL(cpl);
68  }
69
70  private static boolean addClass(Set<Class<?>> alreadySeen, Stack<JavaClass> stack, Class<?> theClass) {
71    if(!alreadySeen.contains(theClass)) {
72      alreadySeen.add(theClass);
73      stack.push(findJavaClass(theClass));
74      return false;
75    }
76    return true;
77  }
78
79  public LispObject typeOf() {
80    return Symbol.JAVA_CLASS;
81  }
82
83  public LispObject classOf() {
84    return StandardClass.JAVA_CLASS;
85  }
86
87  public LispObject typep(LispObject type) throws ConditionThrowable {
88    if (type == Symbol.JAVA_CLASS)
89      return T;
90    if (type == StandardClass.JAVA_CLASS)
91      return T;
92    return super.typep(type);
93  }
94
95  public LispObject getDescription() throws ConditionThrowable {
96    return new SimpleString(writeToString());
97  }
98
99  public String writeToString() throws ConditionThrowable {
100    FastStringBuffer sb = new FastStringBuffer("#<JAVA-CLASS ");
101    sb.append(javaClass.getCanonicalName());
102    sb.append('>');
103    return sb.toString();
104  }
105
106  public static JavaClass findJavaClass(Class<?> javaClass) {
107    synchronized (cache) {
108      JavaClass c = cache.get(javaClass);
109      if (c == null) {
110        c = new JavaClass(javaClass);
111        cache.put(javaClass, c);
112        c.initCPL();
113      }
114      return c;
115    }
116  }
117
118  public Class<?> getJavaClass() {
119    return javaClass;
120  }
121
122  public boolean subclassp(LispObject obj) throws ConditionThrowable {
123    if(obj == BuiltInClass.CLASS_T) {
124      return true;
125    }
126    if(obj == BuiltInClass.JAVA_OBJECT) {
127      return true;
128    }
129    if(obj instanceof JavaClass) {
130      return ((JavaClass) obj).getJavaClass().isAssignableFrom(javaClass);
131    }
132    return false;
133  }
134
135  private static final Primitive _FIND_JAVA_CLASS = new Primitive(
136      "%find-java-class", PACKAGE_JAVA, false, "string") {
137    public LispObject execute(LispObject arg) throws ConditionThrowable {
138      try {
139        return findJavaClass(Class.forName((String) arg.getStringValue()));
140      } catch (ClassNotFoundException e) {
141        throw new ConditionThrowable("Cannot find Java class " + arg.getStringValue());
142      }
143    }
144
145  };
146
147}
Note: See TracBrowser for help on using the repository browser.