/*
* $Id: NativeClass.java,v 1.4 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.util.Enumeration;
import java.util.Hashtable;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import anvil.java.util.Hashlist;
import anvil.java.util.BindingEnumeration;
import anvil.core.Any;
import anvil.core.AnyClass;
import anvil.core.runtime.AnyType;
import anvil.doc.Doc;
import anvil.script.Context;
import anvil.script.ClassDispatcher;
import anvil.script.ConstantVariableType;
import anvil.script.Grammar;
import anvil.script.NativeJava;
import anvil.script.Type;
import anvil.script.CompilableFunction;
import anvil.script.Module;
import anvil.script.ScriptException;
import anvil.script.ClassType;
import anvil.script.ClassRef;
import anvil.script.InterfaceRef;
import anvil.script.Scope;
import anvil.server.ZoneClassLoader;
/**
* class NativeClass
*
* @author: Jani Lehtim�ki
*/
public class NativeClass implements ClassType, NativeJava
{
protected Class _class;
protected String _descriptor;
protected NativeNamespace _parent;
protected String _name;
protected String _qname;
protected CompilableFunction _constructor;
protected ClassRef _base;
protected Doc _document;
protected Hashlist _types = new Hashlist();
protected ClassDispatcher _dispatcher;
protected Any _wrapper;
public NativeClass(String classname, Class cls)
{
this(classname, cls, null, "");
}
public NativeClass(String classname, Class cls, String document)
{
this(classname, cls, null, document);
}
public NativeClass(String classname, Class cls, ClassType base, String document)
{
_class = cls;
_descriptor = cls.getName().replace('.', '/');
_name = classname;
_document = anvil.doc.DocParser.parse(document);
if (base != null) {
_base = new ResolvedClassRef(base);
}
FunctionBase function;
Object[] parameters;
Doc doc;
int n;
boolean declare = true;
try {
Method[] methods = cls.getDeclaredMethods();
n = methods.length;
for(int i=0; i<n; i++) {
Method method = methods[i];
String name = method.getName();
if (name.startsWith("m_")) {
name = name.substring(2);
parameters = (Object[]) Compiled.getstatic(cls, "p_"+name);
if (_document != null) {
doc = _document.findFirst(Doc.T_METHOD, name);
} else {
doc = null;
}
function = new NativeMethod(this, method, name, parameters, doc);
_types.put(name, function);
} else if (name.equals("newInstance")) {
if (Modifier.isStatic(method.getModifiers())) {
doc = _document.findFirst(Doc.T_CONSTRUCTOR, classname);
parameters = (Object[])Compiled.getstatic(cls, "newInstance");
_constructor = new NativeConstructor(this, method, _name, parameters, doc);
_types.put(classname, _constructor);
}
}
}
if (cls != Any.class) {
Field[] fields = cls.getDeclaredFields();
Object obj;
n = fields.length;
for(int i=0; i<n; i++) {
Field field = fields[i];
String name = field.getName();
int mod = field.getModifiers();
if (name.startsWith("p_")) {
continue;
}
if (name.startsWith("_")) {
continue;
}
if (name.equals("newInstance")) {
continue;
}
if (Modifier.isPublic(mod) && Modifier.isStatic(mod) && Modifier.isFinal(mod)) {
try {
obj = field.get(null);
if (obj instanceof Any) {
if (_document != null) {
doc = _document.findFirst(Doc.T_CONST, name);
} else {
doc = null;
}
_types.put(name, new NativeConstantVariable(this, name, field, doc));
}
} catch (Exception e) {
anvil.Log.log().error("Couldn't get field '"+field+"' from "+classname+"."+classname);
}
}
}
}
} catch (Throwable t) {
t.printStackTrace();
}
anvil.core.ObjectPool.register(cls);
}
/*package*/ void setParent(NativeNamespace parent)
{
_parent = parent;
if (_base == null && this != anvil.core.Any.__class__) {
_base = new ResolvedClassRef(anvil.core.Any.__class__);
}
}
public String toString()
{
return "class "+getQualifiedName();
}
public String getName()
{
return _name;
}
public final String getQualifiedName()
{
if (_qname == null) {
_qname = Grammar.buildQualifiedName(this);
}
return _qname;
}
public String getPathinfo()
{
return "";
}
public int getType()
{
return CLASS;
}
public Scope getParent()
{
return _parent;
}
private ClassType[] EMPTY_PARENTS = new ClassType[0];
public ClassType[] getEnclosingClasses()
{
return EMPTY_PARENTS;
}
public Doc getDocument()
{
return _document;
}
public Enumeration getDeclarations()
{
return _types.elements();
}
public BindingEnumeration getMembers(AnyClass instnace)
{
return BindingEnumeration.EMPTY;
}
public Type lookupDeclaration(String name)
{
Type type = (Type)_types.get(name);
if (type == null) {
type = lookupInheritedDeclaration(name);
}
return type;
}
public Type lookupInheritedDeclaration(String name)
{
ClassType base = getBaseClass();
return (base != null) ? base.lookupDeclaration(name) : null;
}
public boolean isInstanceOf(Type ofType)
{
ClassType cls = this;
while(cls != null) {
if (cls == ofType) {
return true;
}
cls = cls.getBaseClass();
}
return false;
}
public ClassRef getBase()
{
return _base;
}
public ClassType getBaseClass()
{
return (_base != null) ? _base.getClassType() : null;
}
public InterfaceRef[] getInterfaces()
{
return new InterfaceRef[0];
}
public CompilableFunction getConstructor()
{
return _constructor;
}
public AnyClass newInstance()
{
return null;
}
public Any newInstance(Context context, Any[] parameters)
{
return _constructor.execute(context, parameters);
}
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("NativeClass.createDispatcher(" + this + ")", t);
throw context.InternalError("Creation of dispatcher failed: "+t);
}
}
}
return dispatcher;
}
public String getDescriptor()
{
return _descriptor;
}
public int getTypeRef(anvil.codec.ConstantPool pool)
{
return pool.addClass(getDescriptor());
}
public int getConstructorReference(anvil.codec.ConstantPool pool)
{
return 0;
// this should never be called
}
public Any getWrapper()
{
if (_wrapper == null) {
_wrapper = new AnyType(this);
}
return _wrapper;
}
public Any getMethod(Context context, String name)
{
Type type = (Type)_types.get(name);
if (type != null) {
return new AnyType(type);
}
throw context.NoSuchEntity(_qname + '.' + name);
}
public Type getDeclaration(Context context, String name)
{
Type type = (Type)_types.get(name);
if (type != null) {
return type;
}
throw context.NoSuchEntity(_qname + '.' + name);
}
}