/*
* $Id: Modules.java,v 1.35 2002/09/16 08:05:02 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.core;
import java.util.Iterator;
import java.util.Enumeration;
import java.util.HashMap;
import anvil.Log;
import anvil.doc.Doc;
import anvil.codec.ConstantPool;
import anvil.server.Zone;
import anvil.script.compiler.NativeNamespace;
import anvil.script.Grammar;
import anvil.script.Name;
import anvil.script.Scope;
import anvil.script.IncrementalScope;
import anvil.script.Type;
import anvil.script.NativeJava;
import anvil.script.Synthetic;
import anvil.script.Module;
import anvil.java.util.Hashlist;
import anvil.java.util.BindingEnumeration;
import anvil.server.Address;
import anvil.script.Dependency;
/**
* class Modules
*
* @author: Jani Lehtim�ki
*/
public class Modules implements NativeJava, IncrementalScope, Module
{
public static final String NAME = "$$native";
public static final Any ANY_NAME = Any.create(NAME);
protected static class SyntheticNamespace
implements IncrementalScope, NativeJava, Synthetic
{
private Scope _parent;
private String _name;
private String _qname;
private Hashlist _types = new Hashlist();
protected SyntheticNamespace(Scope parent, String name)
{
_parent = parent;
_name = name;
}
public String toString()
{
return "SyntheticNamespace(" + _name + ")";
}
public void addDeclaration(Type type)
{
_types.put(type.getName(), type);
}
public String getName()
{
return _name;
}
public final String getQualifiedName()
{
if (_qname == null) {
_qname = Grammar.buildQualifiedName(this);
}
return _qname;
}
public int getType()
{
return NAMESPACE;
}
public Scope getParent()
{
return _parent;
}
public Doc getDocument()
{
return null;
}
public int getTypeRef(ConstantPool pool)
{
return 0;
}
public Enumeration getDeclarations()
{
return _types.elements();
}
public Type lookupDeclaration(String name)
{
return (Type)_types.get(name);
}
}
private static Modules _instance;
public static final Modules getInstance()
{
if (_instance == null) {
synchronized(Modules.class) {
_instance = new Modules();
}
}
return _instance;
}
private Hashlist _types = new Hashlist();
public Modules()
{
addDeclaration(Anvil.__module__);
}
public String toString()
{
return NAME;
}
public void addDeclaration(Type type)
{
_types.put(type.getName(), type);
}
public synchronized void register(String dottedname, NativeNamespace lib)
{
if (!Grammar.isValidIdentifier(lib.getName())) {
throw new RuntimeException("Name of '"+dottedname+"' is invalid");
}
Name name = Grammar.parseDottedName(dottedname);
IncrementalScope scope = this;
int i = 0;
int n = name.size();
while(i < n) {
String s = name.get(i++);
Type type = scope.lookupDeclaration(s);
if (type == null) {
if (i < n) {
SyntheticNamespace ns = new SyntheticNamespace(scope, s);
scope.addDeclaration(ns);
scope = ns;
} else {
scope.addDeclaration(lib);
lib.setParent(scope);
return;
}
} else {
if (type instanceof IncrementalScope) {
scope = (IncrementalScope)type;
} else {
break;
}
}
}
throw new RuntimeException("Library '"+dottedname+"' cannot be embedded into module structure; non-scoped or read-only type encountered");
}
public synchronized void register(String dottedname, String classname)
{
try {
Class cls = Class.forName(classname);
NativeNamespace ns = (NativeNamespace)anvil.script.compiler.Compiled.getstatic(cls, "__module__");
if (ns == null) {
throw new RuntimeException("Static field __module__ is null - couldn't load module '" + classname + "' as '" + dottedname + "'");
}
register(dottedname, ns);
} catch (Throwable t) {
anvil.Log.log().error(t);
throw new RuntimeException("Couldn't load module '" + classname + "' as '" + dottedname + "', reason: "+t);
}
}
public String getName()
{
return NAME;
}
public String getQualifiedName()
{
return NAME;
}
public int getType()
{
return MODULE;
}
public Scope getParent()
{
return null;
}
public Doc getDocument()
{
return null;
}
public int getTypeRef(ConstantPool pool)
{
return 0;
}
public Enumeration getDeclarations()
{
return _types.elements();
}
public Type lookupDeclaration(String name)
{
return (Type)_types.get(name);
}
public Address getAddress()
{
return null;
}
public String getPathinfo()
{
return NAME;
}
public String getDescriptor()
{
return null;
}
public Iterator getDependencies()
{
return null;
}
public Dependency getDependency(Address address)
{
return null;
}
}