View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2001-2004 Open World Ltd
4   // Copyright (C) 2005 Kevin Rogers
5   //
6   // This file is part of MillScript.
7   //
8   // MillScript is free software; you can redistribute it and/or modify it under
9   // the terms of the GNU General Public License as published by the Free
10  // Software Foundation; either version 2 of the License, or (at your option)
11  // any later version.
12  //
13  // MillScript is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  // more details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA  02111-1307  USA
21  ////////////////////////////////////////////////////////////////////////////////
22  package org.millscript.millscript.functions;
23  
24  import org.millscript.millscript.alert.Alerts;
25  import org.millscript.millscript.vm.Machine;
26  
27  import java.lang.reflect.Method;
28  import java.util.Arrays;
29  
30  /**
31   * This class implements the MillScript <code>javaFunction</code> function.
32   */
33  public class JavaFunctionFunction extends Function {
34  
35      /**
36       * @see org.millscript.millscript.functions.Function#apply(org.millscript.millscript.vm.Machine, int)
37       */
38      @Override
39      public void apply( final Machine mc, final int nargs ) {
40          if ( nargs < 2 ) {
41              throw(
42                  Alerts.eval(
43                      "Insufficient arguments",
44                      "javaFunction requires at least two arguments"
45                  ).mishap()
46              );
47          }
48          int num = nargs - 2;
49          Class[] ptypes = new Class[ num ];
50          for ( int i = num - 1; i >= 0; i-- ) {
51              String cname = mc.popString();
52              try {
53                  ptypes[ i ] = ParameterType.findClass( cname );
54              } catch ( ClassNotFoundException ex ) {
55                  throw(
56                      Alerts.eval(
57                          "No such class",
58                          "There does not appear to be a class by that name"
59                      ).culprit( "class name", cname ).mishap()
60                  );
61              }
62          }
63          String methodName = mc.popString();
64          String className = mc.popString();
65          mc.pushObject( javaFunction( className, methodName, ptypes ) );
66      }
67  
68      /**
69       * Returns a <code>Function</code> to access the method with the specified
70       * parameters in the specified Java class.
71       *
72       * @param className the Java class containing the method
73       * @param methodName    the Java method we want to invoke
74       * @param ptypes    the parameter types for the method
75       * @return  a <code>Function</code> to invoke the specified method
76       */
77      static Function javaFunction( final String className, final String methodName, final Class[] ptypes ) {
78          try {
79              Class c = Class.forName( className );
80              Method[] methods = c.getMethods();
81              for ( int i = 0; i < methods.length; i++ ) {
82                  Method method = methods[ i ];
83                  if (
84                      method.getName().equals( methodName ) &&
85                      Arrays.equals( method.getParameterTypes(), ptypes )
86                  ) {
87                      // Make a function to invoke this method
88                      return JMethod.make( method );
89                  }
90              }
91          } catch ( ClassNotFoundException ex ) {
92              throw(
93                  Alerts.eval(
94                      "Class cannot be found",
95                      null
96                  ).culprit( "class name", className ).mishap()
97              );
98          }
99          throw(
100             Alerts.eval(
101                 "No such method for this class",
102                 "The class does not define a method of that name"
103             ).
104             culprit( "method name", methodName ).
105             culprit( "class name", className ).
106             mishap()
107         );
108     }
109 
110 }