blob: 162f41374bef8d1b59bbde9b540ea7e1e1c9ba75 [file] [log] [blame]
package org.apache.bsf.engines.javascript;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import javax.script.Namespace;
import javax.script.ScriptContext;
import org.apache.bsf.util.AbstractNamespace;
import org.apache.bsf.util.SimpleEntrySet;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ImporterTopLevel;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Undefined;
/**
* ScriptableNamespace implements Scriptable interface which the native Rhino
* Engine can access directly. It porvides various mechanisms to locate, store,
* wrap, unwrap Java objects when needed.
*
* @author Nandika Jayawardana <nandika@opensource.lk>
* @author Sanka Samaranayake <ssanka@gmail.com>
*
*/
public class RhinoNamespaceBridge extends AbstractNamespace implements Scriptable, Namespace {
/** */
protected Scriptable scope = null;
/** */
protected RhinoScriptEngine engine = null;
/** */
protected Namespace engineNamespace = null;
/** */
protected Namespace globalNamespace = null;
public RhinoNamespaceBridge(RhinoScriptEngine engine, ScriptableObject scope) {
this.engine = engine;
this.scope = scope;
this.engineNamespace = null;
}
public RhinoNamespaceBridge(Namespace engineNamespace, ScriptableObject scope) {
this.engineNamespace = engineNamespace;
this.scope = scope;
this.engine = null;
}
public RhinoNamespaceBridge(RhinoScriptEngine engine) {
ImporterTopLevel importer = new ImporterTopLevel();
Context cx = Context.getCurrentContext();
/* CHECK ME */
if (cx == null) {
try {
cx = Context.enter();
importer.initStandardObjects(cx, false);
Context.exit();
} catch (Exception ex) {
System.err.println("Error : " + ex.getMessage());
}
} else {
importer.initStandardObjects(cx, false);
}
this.scope = importer;
this.engine = engine;
this.engineNamespace = null;
}
public RhinoNamespaceBridge(Namespace engineNamespace) {
ImporterTopLevel importer = new ImporterTopLevel();
Context cx = Context.getCurrentContext();
/* CHECK ME */
if (cx == null) {
try {
cx = Context.enter();
importer.initStandardObjects(cx, false);
Context.exit();
} catch (Exception ex) {
System.err.println("Error : " + ex.getMessage());
}
} else {
importer.initStandardObjects(cx, false);
}
this.scope = importer;
this.engineNamespace = engineNamespace;
this.engine = null;
}
public void put(String key, Object value) {
getLocalNamespace().put(key, value);
}
public Object get(String key) {
Object retValue = getLocalNamespace().get(key);
if (retValue != null && !(retValue instanceof Undefined)) {
return retValue;
} else if (getGlobalNamespace() != null &&
getGlobalNamespace().get(key) != null) {
return getGlobalNamespace().get(key);
}
retValue = scope.get(key, scope);
if (retValue instanceof Undefined || retValue == NOT_FOUND) {
return null;
} else if (retValue instanceof NativeJavaObject) {
return ((NativeJavaObject) retValue).unwrap();
} else {
return retValue; // CHECK ME
}
}
public void remove(String key) {
getLocalNamespace().remove(key);
scope.delete(key);
}
public String[] getNames() {
ArrayList myList = new ArrayList();
Iterator iter = getLocalNamespace().keySet().iterator();
while (iter.hasNext()) {
myList.add(iter.next());
}
Object[] ids = scope.getIds();
for (int i = 0; i < ids.length; i++) {
if (!(myList.contains(ids[i]))) {
myList.add(ids[i]);
}
}
String[] myArray = new String[myList.size()];
iter = myList.iterator();
int i = 0;
while (iter.hasNext()) {
myArray[i] = (String) iter.next();
i++;
}
return (String[]) myList.toArray();
}
public String getClassName() {
return scope.getClassName();
}
public Object get(String name, Scriptable start) {
Object retValue;
if (start == this) {
if (name != "Function") {
retValue = getLocalNamespace().get(name);
if (((retValue == null) || (retValue instanceof Undefined))
&& (getGlobalNamespace() != null)) {
retValue = getGlobalNamespace().get(name);
}
if (retValue != null) {
Context cx = Context.getCurrentContext();
if (cx == null) {
try {
cx = Context.enter();
/* must wrap a native Java object before presenting
* it to native Rhino Interpreter
*/
retValue = cx.getWrapFactory().wrap(
cx, scope, retValue, null);
} finally {
Context.exit();
}
}
return retValue;
}
}
return scope.get(name, scope);
}
return scope.get(name, start);
}
public Object get(int index, Scriptable start) {
return scope.get(index, start);
}
public boolean has(String name, Scriptable start) {
return ((getLocalNamespace().get(name) != null)
|| scope.has(name, start));
}
public boolean has(int index, Scriptable start) {
return scope.has(index, start);
}
public void put(String name, Scriptable start, Object value) {
if (this == start) {
value = (value instanceof NativeJavaObject)
?((NativeJavaObject) value).unwrap()
: value;
put(name, value);
} else {
scope.put(name, start, value);
}
}
public void put(int index, Scriptable start, Object value) {
scope.put(index, start, value);
}
public void delete(String name) {
remove(name);
}
public void delete(int index) {
scope.delete(index);
}
public Scriptable getPrototype() {
return scope.getPrototype();
}
public void setPrototype(Scriptable prototype) {
scope.setPrototype(prototype);
}
public Scriptable getParentScope() {
return scope.getParentScope();
}
public void setParentScope(Scriptable parent) {
scope.setParentScope(parent);
}
public Object[] getIds() {
String[] names = getNames();
Object[] ids = new Object[names.length];
System.arraycopy(names, 0, ids, 0, ids.length);
return ids;
}
public Object getDefaultValue(Class hint) {
return scope.getDefaultValue(hint);
}
public boolean hasInstance(Scriptable instance) {
return scope.hasInstance(instance);
}
// followings should be taken to NamespaceIml and extends from it instead
// of AbstractNamespace
public Set entrySet() {
return new SimpleEntrySet(this);
}
public Object get(Object key) {
if (key == null || !(key instanceof String)) {
throw new IllegalArgumentException("key is null or is not a String");
}
return get((String)key);
}
// public void setLocalNamespace(Namespace namespace) {
// }
public Namespace getGlobalNamespace() {
return globalNamespace;
}
public Namespace getLocalNamespace() {
if (engine != null) {
return engine.getNamespace(ScriptContext.ENGINE_SCOPE);
}
if (engineNamespace != null) {
return engineNamespace;
}
throw new IllegalStateException("Engine Namespace is not set");
}
public Object put(Object key, Object value) {
if (key == null || !(key instanceof String)) {
throw new IllegalArgumentException("key is null or is not a String");
}
put((String) key, value);
return value;
}
public Object remove(Object key) {
if (key == null || !(key instanceof String)) {
throw new IllegalArgumentException("key is null or is not a String");
}
Object value = get(key);
remove((String) key);
return value;
}
public void setGlobalNamespace(Namespace globalNamespace) {
this.globalNamespace = globalNamespace;
}
}