/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.visage.tools.script;
import com.sun.tools.mjavac.util.Name;
import com.sun.tools.mjavac.code.*;
import java.lang.reflect.*;
import java.util.*;
import java.lang.ref.*;
import visage.reflect.*;
//import com.sun.tools.mjavac.code.*;
/**
* Run-time context used for evaluating scripts.
* @author Per Bothner
*/
public class VisageScriptContext {
VisageScriptCompiler compiler;
MemoryClassLoader loader;
protected VisageScriptContext() {
}
public VisageScriptContext(ClassLoader parentClassLoader) {
compiler = new VisageScriptCompiler(parentClassLoader);
loader = new MemoryClassLoader(compiler.clbuffers, parentClassLoader);
}
public Symbol lookupSymbol (Name name) {
return compiler.namedImportScope.lookup(name).sym;
}
public Symbol lookupSymbol (String name) {
return lookupSymbol(compiler.names.fromString(name));
}
public boolean containsSymbol (Name name) {
return lookupSymbol(name) != null;
}
public boolean containsSymbol (String name) {
return lookupSymbol(compiler.names.fromString(name)) != null;
}
protected Class loadSymbolClass (Symbol sym) {
String cname = ((Symbol.ClassSymbol) sym.owner).flatname.toString();
try {
return loader.loadClass(cname);
} catch (ClassNotFoundException ex) {
String sname = sym.getSimpleName().toString();
throw new RuntimeException("no class "+cname+" for "+sname, ex);
}
}
VisageVarMember reflectSymbol (Symbol sym) {
SoftReference<VisageVarMember> ref = symbolMap.get(sym);
if (ref != null) {
VisageVarMember rvar = ref.get();
if (rvar != null)
return rvar;
}
String cname = ((Symbol.ClassSymbol) sym.owner).flatname.toString();
String sname = sym.getSimpleName().toString();
Class clazz;
try {
clazz = loader.loadClass(cname);
} catch (ClassNotFoundException ex) {
throw new RuntimeException("no class "+cname+" for "+sname, ex);
}
try {
VisageLocal.Context rcontext = VisageLocal.getContext();
VisageLocal.ClassType rclass = rcontext.makeClassRef(clazz);
VisageVarMember rvar = rclass.getVariable(sname);
ref = new SoftReference(rvar);
symbolMap.put(sym, ref);
return rvar;
}
catch (Exception ex) {
throw new RuntimeException("no field in "+cname+" for "+sname, ex);
}
}
public Object getVarValue (Symbol sym) {
VisageVarMember rvar = reflectSymbol(sym);
VisageValue rvalue = rvar.getValue(null);
return ((VisageLocal.Value) rvalue).asObject();
}
public Object getVarValue(Name name) {
Scope.Entry entry = compiler.namedImportScope.lookup(name);
return getVarValue(entry.sym); // FIXME check for errors
}
public Object getVarValue(String name) {
Name nname = compiler.names.fromString(name);
Scope.Entry entry = compiler.namedImportScope.lookup(nname);
return getVarValue(entry.sym); // FIXME check for errors
}
static WeakHashMap<Symbol,SoftReference<VisageVarMember>> symbolMap =
new WeakHashMap<Symbol,SoftReference<VisageVarMember>>();
public void setVarValue(Symbol sym, Object newValue) {
VisageVarMember rvar = reflectSymbol(sym);
VisageLocal.Context rcontext = VisageLocal.getContext();
rvar.setValue(null, rcontext.mirrorOf(newValue));
}
public void setVarValue(Name name, Object newValue) {
Scope.Entry entry = compiler.namedImportScope.lookup(name);
setVarValue(entry.sym, newValue); // FIXME check for errors
}
public void setVarValue(String name, Object newValue) {
Name nname = compiler.names.fromString(name);
Scope.Entry entry = compiler.namedImportScope.lookup(nname);
setVarValue(entry.sym, newValue); // FIXME check for errors
}
private static Map<Class,Class> wrappers = new HashMap<Class,Class>();
static {
wrappers.put(boolean.class, Boolean.class);
wrappers.put(byte.class, Byte.class);
wrappers.put(char.class, Character.class);
wrappers.put(double.class, Double.class);
wrappers.put(float.class, Float.class);
wrappers.put(int.class, Integer.class);
wrappers.put(long.class, Long.class);
wrappers.put(short.class, Short.class);
}
static Method findMethod(Class clazz, String name, Object[] args) {
Class[] argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++)
argTypes[i] = args[i].getClass();
try {
return clazz.getMethod(name, argTypes);
} catch (NoSuchMethodException e) {
// fall-through
}
for (Method m : clazz.getMethods()) {
if (m.getName().equals(name)) {
if (m.isVarArgs())
return m;
Class[] parameters = m.getParameterTypes();
if (args.length != parameters.length)
continue;
if (argsMatch(argTypes, parameters))
return m;
}
}
return null;
}
static boolean argsMatch(Class[] argTypes, Class[] parameterTypes) {
for (int i = 0; i < argTypes.length; i++) {
Class arg = argTypes[i];
Class param = parameterTypes[i];
if (param.isPrimitive())
param = wrappers.get(param);
if (param == null || !(param.isAssignableFrom(arg)))
return false;
}
return true;
}
}