All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.dev.shell.JsValueOOPHM Maven / Gradle / Ivy

There is a newer version: 2.11.0
Show newest version
/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.shell;

import com.google.gwt.dev.shell.BrowserChannel.JsObjectRef;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * Represents a JavaScript value in OOPHM.
 */
public class JsValueOOPHM extends JsValue {
  /**
   * OOPHM implementation of the DispatchObject interface.
   */
  static class DispatchObjectOOPHM implements DispatchObject {

    private final CompilingClassLoader classLoader;

    private final JavaDispatchImpl javaDispatch;

    public DispatchObjectOOPHM(CompilingClassLoader ccl) {
      javaDispatch = new JavaDispatchImpl(ccl);
      classLoader = ccl;
    }

    public DispatchObjectOOPHM(CompilingClassLoader ccl, Object val) {
      javaDispatch = new JavaDispatchImpl(ccl, val);
      classLoader = ccl;
    }

    @Override
    public JsValue getField(int dispId) {
      JsValueOOPHM jsValue = new JsValueOOPHM();
      if (javaDispatch.isField(dispId)) {
        Field field = javaDispatch.getField(dispId);
        JsValueGlue.set(jsValue, classLoader, field.getType(),
            javaDispatch.getFieldValue(dispId));
      } else {
        MethodAdaptor method = javaDispatch.getMethod(dispId);
        AccessibleObject obj = method.getUnderlyingObject();
        DispatchMethod dispMethod = (DispatchMethod) classLoader.getWrapperForObject(obj);
        if (dispMethod == null) {
          dispMethod = new MethodDispatch(classLoader, method);
          classLoader.putWrapperForObject(obj, dispMethod);
        }
        jsValue.setWrappedFunction(method.toString(), dispMethod);
      }
      return jsValue;
    }

    @Override
    public JsValue getField(String name) {
      int dispId = getFieldId(name);
      if (dispId < 0) {
        // no field by that name, return undefined
        return new JsValueOOPHM();
      }
      return getField(dispId);
    }

    @Override
    public int getFieldId(String name) {
      return classLoader.getDispId(name);
    }

    @Override
    public Object getTarget() {
      return javaDispatch.getTarget();
    }

    @Override
    public void setField(int dispId, JsValue jsValue) {
      if (javaDispatch.isMethod(dispId)) {
        throw new RuntimeException("Cannot reassign method "
            + javaDispatch.getMethod(dispId).getName());
      }
      Field field = javaDispatch.getField(dispId);
      Object val = JsValueGlue.get(jsValue, classLoader, field.getType(),
          "setField");
      javaDispatch.setFieldValue(dispId, val);
    }

    @Override
    public void setField(String name, JsValue jsValue) {
      int dispId = getFieldId(name);
      if (dispId < 0) {
        // no field by that name, and we do not support expands on Java objects
        throw new RuntimeException("No such field " + name);
      }
      setField(dispId, jsValue);
    }
  }

  /**
   * Class used to identify a JavaScript undefined value.
   */
  private static class UndefinedValue {
  }

  private static final ThreadLocal> dispatchObjectCache = new ThreadLocal>();

  private static final UndefinedValue undefValue = new UndefinedValue();

  /**
   * Underlying value.
   *
   * This may be one of:
   *
   * 
   *   - Boolean instance
   *   - Integer instance
   *   - Double instance
   *   - String instance
   *   - null
   *   - undefValue
   * 
*/ private Object value; /** * Create a JsValueMoz object representing the undefined value. */ public JsValueOOPHM() { this.value = undefValue; } @Override public boolean getBoolean() { return (Boolean) value; } @Override public int getInt() { return (Integer) value; } @Override public DispatchObject getJavaObjectWrapper() { return (DispatchObject) value; } /** * @return the value as a JsObjectRef. * * Fails if isJavascriptObject() is false. */ public JsObjectRef getJavascriptObject() { return (JsObjectRef) value; } @Override public int getJavaScriptObjectPointer() { assert isJavaScriptObject(); return ((JsObjectRef) value).getRefid(); } @Override public double getNumber() { return ((Number) value).doubleValue(); } @Override public String getString() { return (String) value; } @Override public String getTypeString() { if (isBoolean()) { return "boolean"; } else if (isInt()) { return "int"; } else if (isJavaScriptObject()) { JsObjectRef objRef = (JsObjectRef) value; return "JavaScript object(" + objRef.getRefid() + ")"; } else if (isNull()) { return "null"; } else if (isNumber()) { return "number"; } else if (isString()) { return "string"; } else if (isUndefined()) { return "undefined"; } else if (isWrappedJavaFunction()) { return "Java Method"; } else if (isWrappedJavaObject()) { return "Java Object " + value.getClass().getName(); } return "unexpected value type"; } @Override public DispatchMethod getWrappedJavaFunction() { return (DispatchMethod) value; } @Override public Object getWrappedJavaObject() { return ((DispatchObject) value).getTarget(); } @Override public boolean isBoolean() { return value instanceof Boolean; } @Override public boolean isInt() { return value instanceof Integer; } @Override public boolean isJavaScriptObject() { return value instanceof JsObjectRef; } @Override public boolean isNull() { return value == null; } @Override public boolean isNumber() { return value instanceof Number; } @Override public boolean isString() { return value instanceof String; } @Override public boolean isUndefined() { return value == undefValue; } @Override public boolean isWrappedJavaFunction() { return value instanceof DispatchMethod; } @Override public boolean isWrappedJavaObject() { return value instanceof DispatchObject; } @Override public void setBoolean(boolean val) { value = Boolean.valueOf(val); } /* * TODO(jat): remove this method */ @Override public void setByte(byte val) { value = Integer.valueOf(val); } /* * TODO(jat): remove this method */ @Override public void setChar(char val) { value = Integer.valueOf(val); } @Override public void setDouble(double val) { value = Double.valueOf(val); } @Override public void setInt(int val) { value = Integer.valueOf(val); } public void setJavascriptObject(JsObjectRef jsObject) { value = jsObject; } @Override public void setNull() { value = null; } /* * TODO(jat): remove this method */ @Override public void setShort(short val) { value = Integer.valueOf(val); } @Override public void setString(String val) { value = val; } @Override public void setUndefined() { value = undefValue; } @Override public void setValue(JsValue other) { value = ((JsValueOOPHM) other).value; } /** * Wrap a function call to a Java method in this JavaScript value. * * @param methodName the name of the method to invoke * @param dispatchMethod the wrapper object */ public void setWrappedFunction(String methodName, DispatchMethod dispatchMethod) { value = dispatchMethod; } @Override public void setWrappedJavaObject(CompilingClassLoader cl, T val) { if (val == null) { setNull(); return; } if (val instanceof DispatchObject) { value = val; } else { Map cache = dispatchObjectCache.get(); if (cache == null) { cache = new IdentityHashMap(); dispatchObjectCache.set(cache); } DispatchObject dispObj = cache.get(val); if (dispObj == null) { dispObj = new DispatchObjectOOPHM(cl, val); cache.put(val, dispObj); } value = dispObj; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy