/*
* Copyright 2008-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.runtime.liveconnect;
import java.util.*;
import com.sun.java.browser.plugin2.liveconnect.v1.*;
import visage.reflect.*;
public class VisageDelegate implements InvocationDelegate {
public VisageDelegate(Bridge bridge, String scriptClassName) {
this.bridge = bridge;
this.scriptClassName = scriptClassName;
}
public boolean invoke(String methodName,
Object receiver,
Object[] arguments,
boolean isStatic,
boolean objectIsApplet,
Result[] result) throws Exception {
Object[] box = new Object[] { receiver };
InvocationDelegate delegate = getDelegate(box, isStatic, objectIsApplet);
if (delegate == null)
return false;
return delegate.invoke(methodName, (isStatic ? null : box[0]), arguments, isStatic, objectIsApplet, result);
}
public boolean getField(String fieldName,
Object receiver,
boolean isStatic,
boolean objectIsApplet,
Result[] result) throws Exception {
if (objectIsApplet) {
if (fieldName.equalsIgnoreCase("script")) {
result[0] = new Result(new JavaNameSpace(scriptClassName), false);
return true;
}
}
Object[] box = new Object[] { receiver };
InvocationDelegate delegate = getDelegate(box, isStatic, objectIsApplet);
if (delegate == null)
return false;
return delegate.getField(fieldName, (isStatic ? null : box[0]), isStatic, objectIsApplet, result);
}
public boolean setField(String fieldName,
Object receiver,
Object value,
boolean isStatic,
boolean objectIsApplet) throws Exception {
Object[] box = new Object[] { receiver };
InvocationDelegate delegate = getDelegate(box, isStatic, objectIsApplet);
if (delegate == null)
return false;
return delegate.setField(fieldName, (isStatic ? null : box[0]), value, isStatic, objectIsApplet);
}
public boolean hasField(String fieldName,
Object receiver,
boolean isStatic,
boolean objectIsApplet,
boolean[] result) {
if (objectIsApplet) {
if (fieldName.equalsIgnoreCase("script")) {
result[0] = true;
return true;
}
}
Object[] box = new Object[] { receiver };
InvocationDelegate delegate = getDelegate(box, isStatic, objectIsApplet);
if (delegate == null)
return false;
return delegate.hasField(fieldName, (isStatic ? null : box[0]), isStatic, objectIsApplet, result);
}
public boolean hasMethod(String methodName,
Object receiver,
boolean isStatic,
boolean objectIsApplet,
boolean[] result) {
Object[] box = new Object[] { receiver };
InvocationDelegate delegate = getDelegate(box, isStatic, objectIsApplet);
if (delegate == null) {
return false;
}
return delegate.hasMethod(methodName, (isStatic ? null : box[0]), isStatic, objectIsApplet, result);
}
public boolean hasFieldOrMethod(String name,
Object receiver,
boolean isStatic,
boolean objectIsApplet,
boolean[] result) {
if (objectIsApplet) {
if (name.equalsIgnoreCase("script")) {
result[0] = true;
return true;
}
}
Object[] box = new Object[] { receiver };
InvocationDelegate delegate = getDelegate(box, isStatic, objectIsApplet);
if (delegate == null)
return false;
return delegate.hasFieldOrMethod(name, (isStatic ? null : box[0]), isStatic, objectIsApplet, result);
}
public Object findClass(String name) {
if (notVisageClasses.contains(name)) {
return null;
}
try {
VisageClassType clazz = context.findClass(name);
if (clazz != null && clazz.isVisageType()) {
return clazz;
}
} catch (Throwable t) {
}
synchronized(this) {
notVisageClasses.add(name);
}
return null;
}
public Object newInstance(Object clazz,
Object[] arguments) throws Exception {
// FIXME
throw new UnsupportedOperationException("Instantiation of Visage classes not yet supported");
}
//----------------------------------------------------------------------
// Internals only below this point
//
private Bridge bridge;
private String scriptClassName;
private VisageLocal.Context context = VisageLocal.getContext();
private Map<VisageClassType, VisageClassDelegate> classDelegates =
new HashMap<VisageClassType, VisageClassDelegate>();
private Set<String> notVisageClasses = new HashSet<String>();
// We only need a singleton sequence delegate
private VisageSequenceDelegate sequenceDelegate;
private synchronized InvocationDelegate getDelegate(Object[] box, boolean isStatic, boolean objectIsApplet) {
Object obj = box[0];
if ((obj instanceof VisageClassType) ||
(obj instanceof VisageObjectValue)) {
if (isStatic) {
return getClassDelegate((VisageClassType) obj);
} else {
VisageObjectValue visageObj = (VisageObjectValue) obj;
return getClassDelegate(visageObj.getClassType());
}
} else if (obj instanceof VisageSequenceValue) {
if (sequenceDelegate == null) {
sequenceDelegate = new VisageSequenceDelegate(bridge);
}
return sequenceDelegate;
} else if (objectIsApplet) {
// The incoming applet object comes in as a non-VisageObjectValue
// but needs to be identified as such; we could do this check
// for other values as well but we prefer not to due to the cost
VisageObjectValue visageObj = context.mirrorOf(obj);
VisageClassType visageClass = visageObj.getClassType();
if (visageClass.isVisageType()) {
// Upgrade the receiver to an VisageObjectValue
box[0] = visageObj;
return getClassDelegate(visageClass);
}
}
return null;
}
private InvocationDelegate getClassDelegate(VisageClassType visageClass) {
VisageClassDelegate delegate = classDelegates.get(visageClass);
if (delegate == null) {
delegate = new VisageClassDelegate(visageClass, bridge);
classDelegates.put(visageClass, delegate);
}
return delegate;
}
private VisageClassType scriptClass;
private VisageClassType getScriptClass(String className) {
if (scriptClass == null) {
scriptClass = context.findClass(className);
}
return scriptClass;
}
}