PageRenderTime 37ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-0-pre5/bsh/BSHPrimarySuffix.java

#
Java | 216 lines | 123 code | 24 blank | 69 comment | 17 complexity | f0de1882d345e066a7419d2e1633b056 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*****************************************************************************
  2. * *
  3. * This file is part of the BeanShell Java Scripting distribution. *
  4. * Documentation and updates may be found at http://www.beanshell.org/ *
  5. * *
  6. * Sun Public License Notice: *
  7. * *
  8. * The contents of this file are subject to the Sun Public License Version *
  9. * 1.0 (the "License"); you may not use this file except in compliance with *
  10. * the License. A copy of the License is available at http://www.sun.com *
  11. * *
  12. * The Original Code is BeanShell. The Initial Developer of the Original *
  13. * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
  14. * (C) 2000. All Rights Reserved. *
  15. * *
  16. * GNU Public License Notice: *
  17. * *
  18. * Alternatively, the contents of this file may be used under the terms of *
  19. * the GNU Lesser General Public License (the "LGPL"), in which case the *
  20. * provisions of LGPL are applicable instead of those above. If you wish to *
  21. * allow use of your version of this file only under the terms of the LGPL *
  22. * and not to allow others to use your version of this file under the SPL, *
  23. * indicate your decision by deleting the provisions above and replace *
  24. * them with the notice and other provisions required by the LGPL. If you *
  25. * do not delete the provisions above, a recipient may use your version of *
  26. * this file under either the SPL or the LGPL. *
  27. * *
  28. * Patrick Niemeyer (pat@pat.net) *
  29. * Author of Learning Java, O'Reilly & Associates *
  30. * http://www.pat.net/~pat/ *
  31. * *
  32. *****************************************************************************/
  33. /*
  34. Warning: this is a hack... should be unified with BSHLHSPrimarySuffix
  35. */
  36. package bsh;
  37. import java.util.Hashtable;
  38. import java.lang.reflect.Array;
  39. import java.lang.reflect.InvocationTargetException;
  40. class BSHPrimarySuffix extends SimpleNode
  41. {
  42. public static final int
  43. CLASS = 0,
  44. INDEX = 1,
  45. NAME = 2,
  46. PROPERTY = 3;
  47. public int operation;
  48. Object index;
  49. public String field;
  50. BSHPrimarySuffix(int id) { super(id); }
  51. /*
  52. Perform a suffix operation on the given object and return the
  53. new value.
  54. obj will be a Node when suffix evaluation begins, allowing us to
  55. interpret it contextually. (e.g. for .class) Thereafter it will be
  56. a normal object.
  57. */
  58. public Object doSuffix(
  59. Object obj, CallStack callstack, Interpreter interpreter)
  60. throws EvalError
  61. {
  62. // Handle ".class" suffix operation
  63. /*
  64. if ( operation == CLASS )
  65. if ( obj instanceof BSHAmbiguousName ) {
  66. NameSpace namespace = callstack.top();
  67. return ((BSHAmbiguousName)obj).toClass( namespace );
  68. } else
  69. throw new EvalError(
  70. "Attemp to .class on non class...", this);
  71. */
  72. if ( operation == CLASS )
  73. if ( obj instanceof BSHType ) {
  74. NameSpace namespace = callstack.top();
  75. return ((BSHType)obj).getType( namespace );
  76. } else
  77. throw new EvalError(
  78. "Attemp to invoke .class on non class.", this);
  79. // Handle other suffix operations
  80. /*
  81. eval( ) the node to an object
  82. Note: This construct is now necessary where the node may be
  83. an ambiguous name. If this becomes common we might want to
  84. make a static method nodeToObject() or something.
  85. */
  86. if ( obj instanceof SimpleNode )
  87. if ( obj instanceof BSHAmbiguousName )
  88. obj = ((BSHAmbiguousName)obj).toObject(callstack, interpreter);
  89. else
  90. obj = ((SimpleNode)obj).eval(callstack, interpreter);
  91. try
  92. {
  93. switch(operation)
  94. {
  95. case INDEX:
  96. return doIndex(obj, callstack, interpreter );
  97. case NAME:
  98. return doName(obj, callstack, interpreter );
  99. case PROPERTY:
  100. return doProperty(obj, callstack, interpreter );
  101. default:
  102. throw new InterpreterError("LHS suffix");
  103. }
  104. }
  105. catch(ReflectError e)
  106. {
  107. throw new EvalError("reflection error: " + e, this);
  108. }
  109. catch(InvocationTargetException e)
  110. {
  111. throw new TargetError(
  112. "target exception", e.getTargetException(), this, true);
  113. }
  114. }
  115. /*
  116. Field access or a method invocation
  117. Field access might be .length on an array
  118. */
  119. private Object doName(
  120. Object obj, CallStack callstack, Interpreter interpreter)
  121. throws EvalError, ReflectError, InvocationTargetException
  122. {
  123. if(field.equals("length") && obj.getClass().isArray())
  124. return new Primitive(Array.getLength(obj));
  125. if (jjtGetNumChildren() == 0)
  126. // field access
  127. return Reflect.getObjectField(obj, field);
  128. else
  129. {
  130. // method invocation
  131. Object[] oa = ((BSHArguments)jjtGetChild(0)).getArguments(
  132. callstack, interpreter);
  133. try {
  134. return Reflect.invokeObjectMethod(interpreter, obj, field, oa, this);
  135. } catch ( EvalError ee ) {
  136. // catch and re-throw to get line number right
  137. throw new EvalError( ee.getMessage(), this );
  138. }
  139. }
  140. }
  141. private Object doIndex(
  142. Object obj, CallStack callstack, Interpreter interpreter)
  143. throws EvalError, ReflectError
  144. {
  145. if(!obj.getClass().isArray())
  146. throw new EvalError("Not an array", this);
  147. int index;
  148. try
  149. {
  150. Primitive val = (Primitive)(((SimpleNode)jjtGetChild(0)).eval(
  151. callstack, interpreter ));
  152. index = val.intValue();
  153. }
  154. catch(Exception e)
  155. {
  156. throw new EvalError("You can only index arrays by integer types", this);
  157. }
  158. return Reflect.getIndex(obj, index);
  159. }
  160. private Object doProperty(
  161. Object obj, CallStack callstack, Interpreter interpreter )
  162. throws EvalError
  163. {
  164. if(obj == Primitive.VOID)
  165. throw new EvalError("Attempt to access property on undefined variable or class name", this);
  166. if(obj instanceof Primitive)
  167. throw new EvalError("Attempt to access property on a primitive", this);
  168. Object value = ((SimpleNode)jjtGetChild(0)).eval(
  169. callstack, interpreter);
  170. if(!(value instanceof String))
  171. throw new EvalError("Property expression must be a String or identifier.", this);
  172. // property style access to hashtable
  173. if(obj instanceof Hashtable)
  174. {
  175. Object val = ((Hashtable)obj).get((String)value);
  176. if(val == null)
  177. val = Primitive.NULL;
  178. return val;
  179. }
  180. try
  181. {
  182. return Reflect.getObjectProperty(obj, (String)value);
  183. }
  184. catch(ReflectError e)
  185. {
  186. Interpreter.debug(e.toString());
  187. throw new EvalError("No such property: " + value, this);
  188. }
  189. }
  190. }