package org.mozilla.javascript;
import static org.mozilla.javascript.RhinoHelper.RHINO;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.nominanuda.zen.common.Check;
import com.nominanuda.zen.stereotype.Factory;
/**
* this class is supposed to be immutable by other parts of the framework !! beware
*
*/
public class ScopeFactory implements Factory<Scriptable> {
private final static int FIXED_ROOT = ScriptableObject.DONTENUM | ScriptableObject.READONLY;
private ScriptableObject cachedScope = null;
private RhinoEmbedding embedding;
@Override
public int hashCode() {
return toString().hashCode();
}
@Override
public boolean equals(Object obj) {
if(obj == null || ! (obj instanceof ScopeFactory)) {
return false;
}
return toString().equals(obj.toString());
}
private final String toStringVal;
@Override
public String toString() {
return toStringVal;
}
private List<String> sourceScripts = Collections.emptyList();
private List<Class<? extends Script>> compiledScripts = Collections.emptyList();
private List<Class<? extends Scriptable>> definedClasses = Collections.emptyList();
private Map<String, Object> javaObjects = Collections.emptyMap();
private boolean sealed = false;
private boolean immutable = false;
private boolean allowJavaPackageAccess = false;
public ScopeFactory(List<String> _sourceScripts,
List<Class<? extends Script>> _compiledScripts,
List<Class<? extends Scriptable>> _definedClasses,
Map<String, Object> _javaObjects,
boolean _sealed) {
immutable = true;
if(_sourceScripts != null) sourceScripts = _sourceScripts;
if(_compiledScripts != null) compiledScripts = _compiledScripts;
if(_definedClasses != null) definedClasses = _definedClasses;
if(_javaObjects != null) javaObjects = _javaObjects;
sealed = _sealed;
toStringVal =
new Boolean(sealed).toString()
+ sourceScripts.toString()
+ compiledScripts.toString()
+ definedClasses.toString()
+ javaObjects.toString();
}
public ScopeFactory() {
toStringVal = toString();
}
public boolean isSealed() {
return sealed;
}
public List<String> getSourceScripts() {
return sourceScripts;
}
public List<Class<? extends Script>> getCompiledScripts() {
return compiledScripts;
}
public List<Class<? extends Scriptable>> getDefinedClasses() {
return definedClasses;
}
public Map<String, Object> getJavaObjects() {
return javaObjects;
}
@Override
public Scriptable get() throws RuntimeException {
return create();
}
public Scriptable create() throws RuntimeException {
Context cx = Context.getCurrentContext();
if(cx == null) {
try {
cx = embedding != null
? cx = embedding.enterContext()
: Context.enter();
return createInContext(cx);
} finally {
Context.exit();
}
} else {
return createInContext(cx);
}
}
public Scriptable createInCurrentContext() throws RuntimeException {
return createInContext(Context.getCurrentContext());
}
public Scriptable createInContext(Context cx) throws RuntimeException {
if (cachedScope != null) {
return this.isSealed() ? cachedScope : RHINO.protocloneScriptable(cx, cachedScope);
} else {
ScriptableObject s;
try {
s = RHINO.createTopScope(cx, allowJavaPackageAccess);
} catch (Exception e) {
throw new RuntimeException(e);
}
for (String k : this.getJavaObjects().keySet()) {
s.defineProperty(k, this.getJavaObjects().get(k), FIXED_ROOT);
}
for (Class<? extends Scriptable> cl : this.getDefinedClasses()) {
RHINO.defineClassInScope(s, cl);
// TODO remove me
// if(MixedHostObject.class.isAssignableFrom(cl)){
// handleMixedHostObject(cl, s, cx);
// }
}
for (Class<? extends Script> cl : this.getCompiledScripts()) {
Script script = RHINO.instantiate(cl, cx);
RHINO.evaluateScript(script, cx, s);
}
for (String path : this.getSourceScripts()) {
Reader r;
try {
r = new InputStreamReader(new URL(path).openStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
RHINO.evaluateReader(cx, r, path, s);
}
if (this.isSealed()) {
s.sealObject();
}
cachedScope = s;
return this.isSealed() ? s : RHINO.protocloneScriptable(cx, s);
}
}
public void setAllowJavaPackageAccess(boolean allowJavaPackageAccess) {
this.allowJavaPackageAccess = allowJavaPackageAccess;
cachedScope = null; // reset;
}
public void setSourceScripts(List<String> sourceScripts) {
Check.illegalstate.assertFalse(immutable);
this.sourceScripts = sourceScripts;
cachedScope = null; // reset;
}
public void setCompiledScripts(List<Class<? extends Script>> compiledScripts) {
Check.illegalstate.assertFalse(immutable);
this.compiledScripts = compiledScripts;
cachedScope = null; // reset;
}
public void setDefinedClasses(List<Class<? extends Scriptable>> definedClasses) {
Check.illegalstate.assertFalse(immutable);
this.definedClasses = definedClasses;
cachedScope = null; // reset;
}
public void setJavaObjects(Map<String, Object> javaObjects) {
Check.illegalstate.assertFalse(immutable);
this.javaObjects = javaObjects;
cachedScope = null; // reset;
}
public void setSealed(boolean sealed) {
Check.illegalstate.assertFalse(immutable);
this.sealed = sealed;
}
public void setEmbedding(RhinoEmbedding embedding) {
this.embedding = embedding;
}
public boolean isAllowJavaPackageAccess() {
return allowJavaPackageAccess;
}
}