/*
* $Id: CompiledClassType.java,v 1.15 2002/09/16 08:05:04 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.script.compiler;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import anvil.core.Any;
import anvil.core.AnyClass;
import anvil.core.Register;
import anvil.core.ObjectPool;
import anvil.core.runtime.AnyType;
import anvil.core.runtime.AnyFunction;
import anvil.codec.ConstantPool;
import anvil.Log;
import anvil.doc.Doc;
import anvil.script.ClassDispatcher;
import anvil.script.ClassType;
import anvil.script.ClassRef;
import anvil.script.CompilableFunction;
import anvil.script.Context;
import anvil.script.ConstantVariableType;
import anvil.script.Grammar;
import anvil.script.InterfaceType;
import anvil.script.Type;
import anvil.script.InterfaceRef;
import anvil.script.MemberVariableType;
import anvil.script.MethodType;
import anvil.script.Module;
import anvil.script.Scope;
import anvil.server.ZoneClassLoader;
import anvil.java.util.Hashlist;
import anvil.java.util.BindingEnumeration;
/**
* class CompiledClassType
*
* @author: Jani Lehtim�ki
*/
public class CompiledClassType extends CompiledScope implements ClassType
{
protected ClassType[] _parents;
protected String _pathinfo;
protected ClassRef _base;
protected InterfaceRef[] _interfaces;
protected ConstructorBase _constructor;
protected String _constructor_signature;
protected HashSet _instanceof;
protected Hashlist _fields = new Hashlist();
protected ClassDispatcher _dispatcher = null;
public CompiledClassType(ClassLoader classloader, Scope parent, Class cls, String name, Doc document)
{
super(parent, cls, name, document);
_pathinfo = getModule().getPathinfo();
try {
Class basecls = cls.getSuperclass();
if (basecls.isAssignableFrom(AnyClass.class)) {
_base = new ResolvedClassRef(Any.__class__);
} else {
_base = new DelayedClassRef(basecls);
}
String[] bases = (String[])getstatic(cls, "_bases");
int n = bases.length;
_interfaces = new InterfaceRef[n];
for(int i=0; i<n; i++) {
Class icls = classloader.loadClass(bases[i]);
_interfaces[i] = new DelayedInterfaceRef(icls);
}
putstatic(cls, "_class", this);
putstatic(cls, "_type", new AnyType(this));
} catch (Throwable t) {
anvil.Log.log().error("Class initialization failed: "+cls.getName(), t);
}
int c = 0;
Type type = parent;
while(type != null) {
if (type.getType() != CLASS) {
break;
}
c++;
type = type.getParent();
}
_parents = new ClassType[c];
type = parent;
for(int i=0; i<c; i++) {
_parents[c-i-1] = (ClassType)type;
type = type.getParent();
}
initializeMembers(classloader);
}
protected MemberVariableType onMemberVariable(Field field, String name, Doc doc)
{
_fields.put(name, field);
return super.onMemberVariable(field, name, doc);
}
protected MethodType onConstructor(Method method, Constructor constructor, String name, Object[] parameters, Doc doc)
{
_constructor = (ConstructorBase)super.onConstructor(method, constructor, name, parameters, doc);
Class[] types = constructor.getParameterTypes();
StringBuffer signature = new StringBuffer();
signature.append("(");
for(int i=0, n=types.length; i<n; i++) {
signature.append('L');
signature.append(types[i].getName().replace('.', '/'));
signature.append(';');
}
signature.append(")V");
_constructor_signature = signature.toString();
return _constructor;
}
private void gatherInstances(ClassType classtype)
{
if (classtype == null) {
return;
}
_instanceof.add(classtype);
InterfaceRef[] bases = classtype.getInterfaces();
int n = bases.length;
for(int i=0; i<n; i++) {
gatherInstances(bases[i].getInterfaceType());
}
gatherInstances(classtype.getBaseClass());
}
private void gatherInstances(InterfaceType interfacetype)
{
if (interfacetype == null) {
return;
}
_instanceof.add(interfacetype);
InterfaceRef[] bases = interfacetype.getBases();
int n = bases.length;
for(int i=0; i<n; i++) {
gatherInstances(bases[i].getInterfaceType());
}
}
public String getPathinfo()
{
return _pathinfo;
}
public int getType()
{
return CLASS;
}
public ClassType[] getEnclosingClasses()
{
return _parents;
}
public boolean isInstanceOf(Type ofType)
{
HashSet set = _instanceof;
if (set == null) {
synchronized(this) {
_instanceof = set = new HashSet();
gatherInstances(this);
}
}
return set.contains(ofType);
}
public CompilableFunction getConstructor()
{
return _constructor;
}
public ClassRef getBase()
{
return _base;
}
public ClassType getBaseClass()
{
return _base.getClassType();
}
public CompiledClassType getCompiledBaseClass()
{
ClassType classtype = _base.getClassType();
if (classtype instanceof CompiledClassType) {
return (CompiledClassType)classtype;
}
return null;
}
public AnyClass newInstance()
{
try {
return (AnyClass)_class.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public InterfaceRef[] getInterfaces()
{
return _interfaces;
}
public Type lookupDeclaration(String name)
{
Type type = (Type)_types.get(name);
if (type == null) {
type = lookupInheritedDeclaration(name);
}
return type;
}
public Type lookupInheritedDeclaration(String name)
{
return _base.getClassType().lookupDeclaration(name);
}
public BindingEnumeration getMembers(AnyClass instance)
{
return new FieldEnumeration(instance, _fields.keysAndElements());
}
public int getConstructorReference(ConstantPool pool)
{
return pool.addMethodRef(getTypeRef(pool), "<init>", _constructor_signature);
}
public Type getMember(Context context, String member)
{
Type type = (Type)_types.get(member);
if (type != null && type.getType() == MEMBER_VARIABLE) {
return type;
}
throw context.NoSuchEntity(_qname + '.' + member);
}
public Any getMemberType(Context context, String member)
{
Type type = (Type)_types.get(member);
if (type != null && type.getType() == MEMBER_VARIABLE) {
return new AnyType(type);
}
throw context.NoSuchEntity(_qname + '.' + member);
}
public ClassDispatcher getDispatcher(Context context)
{
ClassDispatcher dispatcher = _dispatcher;
if (dispatcher == null) {
synchronized(this) {
if (_dispatcher != null) {
return _dispatcher;
}
try {
ZoneClassLoader loader = context.zone().getClassLoader();
return (_dispatcher = DispatcherFactory.create(this, loader));
} catch (Throwable t) {
context.log().error("CompiledClass.createDispatcher(" + this + ")", t);
throw context.InternalError("Creation of dispatcher failed: "+t);
}
}
}
return dispatcher;
}
}