001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.dev.shell.moz;
017:
018: import com.google.gwt.dev.shell.CompilingClassLoader;
019: import com.google.gwt.dev.shell.JavaDispatch;
020: import com.google.gwt.dev.shell.JavaDispatchImpl;
021: import com.google.gwt.dev.shell.JsValue;
022: import com.google.gwt.dev.shell.JsValueGlue;
023: import com.google.gwt.dev.shell.moz.LowLevelMoz.DispatchMethod;
024: import com.google.gwt.dev.shell.moz.LowLevelMoz.DispatchObject;
025:
026: import java.lang.reflect.Field;
027: import java.lang.reflect.Method;
028:
029: /**
030: * Wraps an arbitrary Java Object as a Dispatch component. The class was
031: * motivated by the need to expose Java objects into JavaScript.
032: *
033: * An instance of this class with no target is used to globally access all
034: * static methods or fields.
035: */
036: class GeckoDispatchAdapter implements DispatchObject {
037:
038: private final CompilingClassLoader classLoader;
039:
040: private final JavaDispatch javaDispatch;
041:
042: /**
043: * This constructor initializes as the static dispatcher, which handles only
044: * static method calls and field references.
045: *
046: * @param cl this class's classLoader
047: */
048: GeckoDispatchAdapter(CompilingClassLoader cl) {
049: javaDispatch = new JavaDispatchImpl(cl);
050: classLoader = cl;
051: }
052:
053: /**
054: * This constructor initializes a dispatcher, around a particular instance.
055: *
056: * @param cl this class's classLoader
057: * @param target the object being wrapped as an IDispatch
058: */
059: GeckoDispatchAdapter(CompilingClassLoader cl, Object target) {
060: javaDispatch = new JavaDispatchImpl(cl, target);
061: classLoader = cl;
062: }
063:
064: /**
065: * Retrieve a field and store in the passed JsValue. This function is called
066: * exclusively from native code.
067: *
068: * @param name name of the field to retrieve
069: * @param jsValue a reference to the JsValue object to receive the value of
070: * the field
071: */
072: public void getField(String name, int jsRootedValue) {
073: JsValueMoz jsValue = new JsValueMoz(jsRootedValue);
074: // TODO(jat): factor out remaining code into platform-independent code
075: int dispId = classLoader.getDispId(name);
076: if (dispId < 0) {
077: // no field by that name, return undefined
078: jsValue.setUndefined();
079: return;
080: }
081: if (javaDispatch.isField(dispId)) {
082: Field field = javaDispatch.getField(dispId);
083: JsValueGlue.set(jsValue, classLoader, field.getType(),
084: javaDispatch.getFieldValue(dispId));
085: return;
086: } else {
087: Method method = javaDispatch.getMethod(dispId);
088: DispatchMethod dispMethod = (DispatchMethod) classLoader
089: .getMethodDispatch(method);
090: if (dispMethod == null) {
091: dispMethod = new MethodDispatch(classLoader, method);
092: classLoader.putMethodDispatch(method, dispMethod);
093: }
094: jsValue.setWrappedFunction(method.toString(), dispMethod);
095: }
096: }
097:
098: public Object getTarget() {
099: return javaDispatch.getTarget();
100: }
101:
102: public void setField(String name, int jsRootedValue) {
103: JsValue jsValue = new JsValueMoz(jsRootedValue);
104: int dispId = classLoader.getDispId(name);
105: if (dispId < 0) {
106: // no field by that name
107: // TODO: expandos?
108: throw new RuntimeException("No such field " + name);
109: }
110: if (javaDispatch.isMethod(dispId)) {
111: throw new RuntimeException("Cannot reassign method " + name);
112: }
113: Field field = javaDispatch.getField(dispId);
114: Object val = JsValueGlue.get(jsValue, field.getType(),
115: "setField");
116: javaDispatch.setFieldValue(dispId, val);
117: }
118: }
|