⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 luajavaapi.java

📁 luajava应用
💻 JAVA
字号:
/*
 * $Id: LuaJavaAPI.java,v 1.4 2006/12/22 14:06:40 thiago Exp $
 * Copyright (C) 2003-2007 Kepler Project.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package org.keplerproject.luajava;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * Class that contains functions accessed by lua.
 * 
 * @author Thiago Ponte
 */
public final class LuaJavaAPI
{

  private LuaJavaAPI()
  {
  }

  /**
   * Java implementation of the metamethod __index
   * 
   * @param luaState int that indicates the state used
   * @param obj Object to be indexed
   * @param methodName the name of the method
   * @return number of returned objects
   */
  public static int objectIndex(int luaState, Object obj, String methodName)
      throws LuaException
  {
    LuaState L = LuaStateFactory.getExistingState(luaState);

    synchronized (L)
    {
      int top = L.getTop();

      Object[] objs = new Object[top - 1];

      Class clazz;

      if (obj instanceof Class)
      {
        clazz = (Class) obj;
      }
      else
      {
        clazz = obj.getClass();
      }

      Method[] methods = clazz.getMethods();
      Method method = null;

      // gets method and arguments
      for (int i = 0; i < methods.length; i++)
      {
        if (!methods[i].getName().equals(methodName))

          continue;

        Class[] parameters = methods[i].getParameterTypes();
        if (parameters.length != top - 1)
          continue;

        boolean okMethod = true;

        for (int j = 0; j < parameters.length; j++)
        {
          try
          {
            objs[j] = compareTypes(L, parameters[j], j + 2);
          }
          catch (Exception e)
          {
            okMethod = false;
            break;
          }
        }

        if (okMethod)
        {
          method = methods[i];
          break;
        }

      }

      // If method is null means there isn't one receiving the given arguments
      if (method == null)
      {
        throw new LuaException("Invalid method call. No such method.");
      }

      Object ret;
      try
      {
        if(Modifier.isPublic(method.getModifiers()))
        {
          method.setAccessible(true);
        }
        
        if (obj instanceof Class)
        {
          ret = method.invoke(null, objs);
        }
        else
        {
          ret = method.invoke(obj, objs);
        }
      }
      catch (Exception e)
      {
        throw new LuaException(e);
      }

      // Void function returns null
      if (ret == null)
      {
        return 0;
      }

      // push result
      L.pushObjectValue(ret);

      return 1;
    }
  }

  /**
   * Java function to be called when a java Class metamethod __index is called.
   * This function returns 1 if there is a field with searchName and 2 if there
   * is a method if the searchName
   * 
   * @param luaState int that represents the state to be used
   * @param clazz class to be indexed
   * @param searchName name of the field or method to be accessed
   * @return number of returned objects
   * @throws LuaException
   */
  public static int classIndex(int luaState, Class clazz, String searchName)
      throws LuaException
  {
    synchronized (LuaStateFactory.getExistingState(luaState))
    {
      int res;

      res = checkField(luaState, clazz, searchName);

      if (res != 0)
      {
        return 1;
      }

      res = checkMethod(luaState, clazz, searchName);

      if (res != 0)
      {
        return 2;
      }

      return 0;
    }
  }

  /**
   * Pushes a new instance of a java Object of the type className
   * 
   * @param luaState int that represents the state to be used
   * @param className name of the class
   * @return number of returned objects
   * @throws LuaException
   */
  public static int javaNewInstance(int luaState, String className)
      throws LuaException
  {
    LuaState L = LuaStateFactory.getExistingState(luaState);

    synchronized (L)
    {
      Class clazz;
      try
      {
        clazz = Class.forName(className);
      }
      catch (ClassNotFoundException e)
      {
        throw new LuaException(e);
      }
      Object ret = getObjInstance(L, clazz);

      L.pushJavaObject(ret);

      return 1;
    }
  }

  /**
   * javaNew returns a new instance of a given clazz
   * 
   * @param luaState int that represents the state to be used
   * @param clazz class to be instanciated
   * @return number of returned objects
   * @throws LuaException
   */
  public static int javaNew(int luaState, Class clazz) throws LuaException
  {
    LuaState L = LuaStateFactory.getExistingState(luaState);

    synchronized (L)
    {
      Object ret = getObjInstance(L, clazz);

      L.pushJavaObject(ret);

      return 1;
    }
  }

  /**
   * Calls the static method <code>methodName</code> in class <code>className</code>
   * that receives a LuaState as first parameter.
   * @param luaState int that represents the state to be used
   * @param className name of the class that has the open library method
   * @param methodName method to open library
   * @return number of returned objects
   * @throws LuaException
   */
  public static int javaLoadLib(int luaState, String className, String methodName)
  	throws LuaException
  {
    LuaState L = LuaStateFactory.getExistingState(luaState);
    
    synchronized (L)
    {
      Class clazz;
      try
      {
        clazz = Class.forName(className);
      }
      catch (ClassNotFoundException e)
      {
        throw new LuaException(e);
      }

      try
      {
        Method mt = clazz.getMethod(methodName, new Class[] {LuaState.class});
        Object obj = mt.invoke(null, new Object[] {L});
        
        if (obj != null && obj instanceof Integer)
        {
          return ((Integer) obj).intValue();
        }
        else
          return 0;
      }
      catch (Exception e)
      {
        throw new LuaException("Error on calling method. Library could not be loaded. " + e.getMessage());
      }
    }
  }

  private static Object getObjInstance(LuaState L, Class clazz)
      throws LuaException
  {
    synchronized (L)
    {
	    int top = L.getTop();
	
	    Object[] objs = new Object[top - 1];
	
	    Constructor[] constructors = clazz.getConstructors();
	    Constructor constructor = null;
	
	    // gets method and arguments
	    for (int i = 0; i < constructors.length; i++)
	    {
	      Class[] parameters = constructors[i].getParameterTypes();
	      if (parameters.length != top - 1)
	        continue;
	
	      boolean okConstruc = true;
	
	      for (int j = 0; j < parameters.length; j++)
	      {
	        try
	        {
	          objs[j] = compareTypes(L, parameters[j], j + 2);
	        }
	        catch (Exception e)
	        {
	          okConstruc = false;
	          break;
	        }
	      }
	
	      if (okConstruc)
	      {
	        constructor = constructors[i];
	        break;
	      }
	
	    }
	
	    // If method is null means there isn't one receiving the given arguments
	    if (constructor == null)
	    {
	      throw new LuaException("Invalid method call. No such method.");
	    }
	
	    Object ret;
	    try
	    {
	      ret = constructor.newInstance(objs);
	    }
	    catch (Exception e)
	    {
	      throw new LuaException(e);
	    }
	
	    if (ret == null)
	    {
	      throw new LuaException("Couldn't instantiate java Object");
	    }
	
	    return ret;
    }
  }

  /**
   * Checks if there is a field on the obj with the given name
   * 
   * @param luaState int that represents the state to be used
   * @param obj object to be inspected
   * @param fieldName name of the field to be inpected
   * @return number of returned objects
   */
  public static int checkField(int luaState, Object obj, String fieldName)
  	throws LuaException
  {
    LuaState L = LuaStateFactory.getExistingState(luaState);

    synchronized (L)
    {
      Field field = null;
      Class objClass;

      if (obj instanceof Class)
      {
        objClass = (Class) obj;
      }
      else
      {
        objClass = obj.getClass();
      }

      try
      {
        field = objClass.getField(fieldName);
      }
      catch (Exception e)
      {
        return 0;
      }

      if (field == null)
      {
        return 0;
      }

      Object ret = null;
      try
      {
        ret = field.get(obj);
      }
      catch (Exception e1)
      {
        return 0;
      }

      if (obj == null)
      {
        return 0;
      }

      L.pushObjectValue(ret);

      return 1;
    }
  }

  /**
   * Checks to see if there is a method with the given name.
   * 
   * @param luaState int that represents the state to be used
   * @param obj object to be inspected
   * @param methodName name of the field to be inpected
   * @return number of returned objects
   */
  public static int checkMethod(int luaState, Object obj, String methodName)
  {
    LuaState L = LuaStateFactory.getExistingState(luaState);

    synchronized (L)
    {
      Class clazz;

      if (obj instanceof Class)
      {
        clazz = (Class) obj;
      }
      else
      {
        clazz = obj.getClass();
      }

      Method[] methods = clazz.getMethods();

      for (int i = 0; i < methods.length; i++)
      {
        if (methods[i].getName().equals(methodName))
          return 1;
      }

      return 0;
    }
  }

  /**
   * Function that creates an object proxy and pushes it into the stack
   * 
   * @param luaState int that represents the state to be used
   * @param implem interfaces implemented separated by comma (<code>,</code>)
   * @return number of returned objects
   * @throws LuaException
   */
  public static int createProxyObject(int luaState, String implem)
    throws LuaException
  {
    LuaState L = LuaStateFactory.getExistingState(luaState);

    synchronized (L)
    {
      try
      {
        if (!(L.isTable(2)))
          throw new LuaException(
              "Parameter is not a table. Can't create proxy.");

        LuaObject luaObj = L.getLuaObject(2);

        Object proxy = luaObj.createProxy(implem);
        L.pushJavaObject(proxy);
      }
      catch (Exception e)
      {
        throw new LuaException(e);
      }

      return 1;
    }
  }

  private static Object compareTypes(LuaState L, Class parameter, int idx)
    throws LuaException
  {
    boolean okType = true;
    Object obj = null;

    if (L.isBoolean(idx))
    {
      if (parameter.isPrimitive())
      {
        if (parameter != Boolean.TYPE)
        {
          okType = false;
        }
      }
      else if (!parameter.isAssignableFrom(Boolean.class))
      {
        okType = false;
      }
      obj = new Boolean(L.toBoolean(idx));
    }
    else if (L.type(idx) == LuaState.LUA_TSTRING.intValue())
    {
      if (!parameter.isAssignableFrom(String.class))
      {
        okType = false;
      }
      else
      {
        obj = L.toString(idx);
      }
    }
    else if (L.isFunction(idx))
    {
      if (!parameter.isAssignableFrom(LuaObject.class))
      {
        okType = false;
      }
      else
      {
        obj = L.getLuaObject(idx);
      }
    }
    else if (L.isTable(idx))
    {
      if (!parameter.isAssignableFrom(LuaObject.class))
      {
        okType = false;
      }
      else
      {
        obj = L.getLuaObject(idx);
      }
    }
    else if (L.type(idx) == LuaState.LUA_TNUMBER.intValue())
    {
      Double db = new Double(L.toNumber(idx));
      
      obj = LuaState.convertLuaNumber(db, parameter);
      if (obj == null)
      {
        okType = false;
      }
    }
    else if (L.isUserdata(idx))
    {
      if (L.isObject(idx))
      {
        Object userObj = L.getObjectFromUserdata(idx);
        if (!parameter.isAssignableFrom(userObj.getClass()))
        {
          okType = false;
        }
        else
        {
          obj = userObj;
        }
      }
      else
      {
        if (!parameter.isAssignableFrom(LuaObject.class))
        {
          okType = false;
        }
        else
        {
          obj = L.getLuaObject(idx);
        }
      }
    }
    else if (L.isNil(idx))
    {
      obj = null;
    }
    else
    {
      throw new LuaException("Invalid Parameters.");
    }

    if (!okType)
    {
      throw new LuaException("Invalid Parameter.");
    }

    return obj;
  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -