0001: /*
0002: * Copyright (C) 2004 TiongHiang Lee
0003: *
0004: * This library is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU Lesser General Public
0006: * License as published by the Free Software Foundation; either
0007: * version 2.1 of the License, or (at your option) any later version.
0008: *
0009: * This library is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0012: * Lesser General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU Lesser General Public
0015: * License along with this library; if not, write to the Free Software
0016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0017: *
0018: * Email: thlee@onemindsoft.org
0019: */
0020:
0021: package org.onemind.jxp;
0022:
0023: import java.io.*;
0024: import java.lang.reflect.*;
0025: import java.util.*;
0026: import java.util.logging.Level;
0027: import java.util.logging.Logger;
0028: import org.onemind.commons.invoke.InvocableFunction;
0029: import org.onemind.commons.java.datastructure.NametableStack;
0030: import org.onemind.commons.java.datastructure.ThreadLocalStack;
0031: import org.onemind.commons.java.lang.reflect.ReflectUtils;
0032: import org.onemind.commons.java.util.*;
0033: import org.onemind.jxp.parser.*;
0034: import org.onemind.jxp.util.StaticImport;
0035: import org.onemind.jxp.util.StaticImportUtils;
0036:
0037: /**
0038: * The jxp processor
0039: * @author TiongHiang Lee (thlee@onemindsoft.org)
0040: *
0041: */
0042: public class JxpProcessor implements JxpParserVisitor {
0043:
0044: /** the logger * */
0045: private static final Logger _logger = Logger
0046: .getLogger(JxpProcessor.class.getName());
0047:
0048: /** represent ONE * */
0049: private static final Integer ONE = new Integer(1);
0050:
0051: /** contains zero values for primitive **/
0052: private static final Map PRIMITIVE_DEFAULTS = new HashMap();
0053: static {
0054: PRIMITIVE_DEFAULTS.put(Integer.TYPE, new Integer(0));
0055: PRIMITIVE_DEFAULTS.put(Long.TYPE, new Long(0));
0056: PRIMITIVE_DEFAULTS.put(Float.TYPE, new Float(0));
0057: PRIMITIVE_DEFAULTS.put(Double.TYPE, new Double(0));
0058: PRIMITIVE_DEFAULTS.put(Character.TYPE, new Character((char) 0));
0059: PRIMITIVE_DEFAULTS.put(Byte.TYPE, new Byte((byte) 0));
0060: PRIMITIVE_DEFAULTS.put(Boolean.TYPE, Boolean.FALSE);
0061: }
0062:
0063: /**
0064: * process a file
0065: * @param args the arguments
0066: * @throws Exception if exception
0067: */
0068: public static void main(String[] args) throws Exception {
0069: if (args.length != 2) {
0070: System.out
0071: .println("Usage: java org.onemind.jxp.JxpProcessor <source dir> <page>");
0072: } else {
0073: FilePageSource source = new FilePageSource(args[0]);
0074: JxpContext context = new JxpContext(source);
0075: JxpProcessor processor = new JxpProcessor(context);
0076: Writer writer = new OutputStreamWriter(System.out);
0077: try {
0078: processor.process(args[1], writer,
0079: Collections.EMPTY_MAP);
0080: } catch (Exception e) {
0081: e.printStackTrace();
0082: }
0083: writer.flush();
0084: }
0085: }
0086:
0087: /**
0088: * Represents a user defined function
0089: * @author TiongHiang Lee (thlee@onemindsoft.org)
0090: *
0091: */
0092: private class JxpUserDefinedFunction {
0093:
0094: /** the declarator **/
0095: private SimpleNode _paramSpec;
0096:
0097: /** the block **/
0098: private AstBlock _block;
0099:
0100: /**
0101: * Constructor
0102: * @param dec the declarator
0103: * @param block the function block
0104: */
0105: public JxpUserDefinedFunction(SimpleNode paramSpec,
0106: AstBlock block) {
0107: _paramSpec = paramSpec;
0108: _block = block;
0109: }
0110:
0111: /**
0112: * Get the declarator
0113: * @return the declarator
0114: */
0115: public SimpleNode getParameterSpec() {
0116: return _paramSpec;
0117: }
0118:
0119: /**
0120: * Get the block
0121: * @return the block
0122: */
0123: public AstBlock getBlock() {
0124: return _block;
0125: }
0126: }
0127:
0128: /** a context local keep tracks of current processing context * */
0129: private ThreadLocalStack _contextLocal = new ThreadLocalStack();
0130:
0131: /** the jxp page source * */
0132: private JxpContext _context;
0133:
0134: /** whether do method status **/
0135: //TODO: add as config options
0136: private boolean doMethodStats;
0137:
0138: /** whether to check function argument type **/
0139: private boolean _checkFunctionArgumentType = false;
0140:
0141: /** the method statistic counter **/
0142: private final Counter _methodStats = new Counter();
0143:
0144: /**
0145: * Constructor
0146: * @param source the page source
0147: */
0148: public JxpProcessor(JxpContext context) {
0149: _context = context;
0150: }
0151:
0152: /**
0153: * Get the source
0154: * @return the source
0155: */
0156: public final JxpContext getContext() {
0157: return _context;
0158: }
0159:
0160: /**
0161: * Assign the value assignable target node to the value
0162: * @param node the assignable target
0163: * @param value the value to assign
0164: * @return the value assinged
0165: * @throws ProcessingException if the node is not an assignable
0166: */
0167: protected Object assign(SimpleNode node, Object value)
0168: throws ProcessingException {
0169: Object target = resolveAssignmentTarget(node, true);
0170: if (target instanceof Assignable) {
0171: return ((Assignable) target).assign(value);
0172: } else {
0173: return generateProcessingException(
0174: new IllegalArgumentException(node
0175: + " is not assignable"), node);
0176: }
0177: }
0178:
0179: /**
0180: * Assign a variable in a current nametable stack to the value
0181: * @param name the variable name
0182: * @param value the value
0183: * @return the value assigned
0184: */
0185: protected Object assignVariable(String name, Object value) {
0186: NametableStack ntStack = getCurrentContext()
0187: .getNametableStack();
0188: ntStack.assign(name, value);
0189: return value;
0190: }
0191:
0192: /**
0193: * Call the function of the processor. Call predefined print or println if the method name matched. Otherwise, reflection will
0194: * be used on the processor to invoke method
0195: * @param methodName the method name
0196: * @param args the arguments
0197: * @return the value returned by the method call
0198: * @throws Exception if there's problem calling method
0199: */
0200: protected Object callFunction(String methodName, Object[] args)
0201: throws Exception {
0202: //built-in functions
0203: if (methodName.equals("print")) {
0204: print(args[0]);
0205: return null;
0206: } else if (methodName.equals("println")) {
0207: println(args[0]);
0208: return null;
0209: } else if (methodName.equals("getJxpEnvironment")) {
0210: return getEnvironment();
0211: } else {
0212: JxpProcessingContext context = getCurrentContext();
0213: String functionName = methodName;
0214: if (context.getUserDefinedFunctions().containsKey(
0215: functionName)) {
0216: JxpUserDefinedFunction function = (JxpUserDefinedFunction) context
0217: .getUserDefinedFunctions().get(functionName);
0218: NametableStack nt = context.getNametableStack();
0219: int scope = nt.newLocalScope();
0220: declareFunctionLocals(functionName, function
0221: .getParameterSpec(), args);
0222: try {
0223: Object obj = function.getBlock().jjtAccept(this ,
0224: null);
0225: if (obj == Control.EXIT) {
0226: return obj;
0227: } else if (obj instanceof Control) //return value
0228: {
0229: return ((Control) obj).getObject();
0230: } else {
0231: return obj;
0232: }
0233: } finally {
0234: nt.closeLocalScope(scope);
0235: }
0236: } else {
0237: //try static import
0238: List staticImports = context.getStaticImports();
0239: Iterator it = staticImports.iterator();
0240: while (it.hasNext()) {
0241: StaticImport sImport = (StaticImport) it.next();
0242: InvocableFunction func = sImport.getFunction(
0243: functionName, args);
0244: if (func != null) {
0245: return func.invoke(null, args);
0246: }
0247: }
0248: //lastly, throw exception
0249: throw new NoSuchMethodException("Method " + methodName
0250: + " not found for the Processor");
0251: }
0252: }
0253: }
0254:
0255: /**
0256: * Create the function environment
0257: * @param params the parameters
0258: * @param args the arguments
0259: */
0260: public void declareFunctionLocals(String functionName,
0261: SimpleNode params, Object[] args) throws Exception {
0262: NametableStack ntStack = getCurrentContext()
0263: .getNametableStack();
0264: int n = params.jjtGetNumChildren();
0265: Map defaults = new HashMap();
0266: for (int i = 0; i < args.length; i++) {
0267: if (args[i] instanceof AstNamedArgument) {
0268: SimpleNode arg = (SimpleNode) args[i];
0269: Object value = arg.jjtGetChild(0).jjtAccept(this , null);
0270: defaults.put(arg.getData(), value);
0271: }
0272: }
0273: if (params instanceof AstFormalParameters) {
0274: for (int i = 0; i < n; i++) {
0275: AstFormalParameter param = (AstFormalParameter) params
0276: .jjtGetChild(i);
0277: AstVariableDeclaratorId id = (AstVariableDeclaratorId) param
0278: .jjtGetChild(1);
0279: AstType type = (AstType) param.jjtGetChild(0);
0280: Class paramType = (Class) type.jjtAccept(this , null);
0281:
0282: if (param.jjtGetNumChildren() == 2) {//no defaults
0283: if (args.length <= i) {
0284: throw new IllegalArgumentException(
0285: "Mismatch number of arguments");
0286: } else if (args[i] instanceof AstNamedArgument) {
0287: throw new IllegalArgumentException(
0288: "Expecting required paramater "
0289: + id.getData()
0290: + " for function "
0291: + functionName);
0292: } else {
0293: if (_checkFunctionArgumentType) {//do type checking
0294: if (paramType.isPrimitive()) {
0295: if (args[i] == null) {
0296: throw new IllegalArgumentException(
0297: "Primitive argument "
0298: + id.getData()
0299: + " cannot be null");
0300: } else if (!ReflectUtils
0301: .isPrimitiveInstance(paramType,
0302: args[i])) {
0303: throw new IllegalArgumentException(
0304: "Mismatch argument type for "
0305: + id.getData()
0306: + ". Expecting "
0307: + paramType
0308: .getName());
0309: }
0310: } else if (args[i] != null) {
0311: if (!paramType.isInstance(args[i])) {
0312: throw new IllegalArgumentException(
0313: "Mismatch argument type for "
0314: + id.getData()
0315: + ". Expecting "
0316: + paramType
0317: .getName());
0318: }
0319: }
0320:
0321: }
0322: ntStack.declare((String) id.getData(), args[i]);
0323: }
0324: } else {//has default
0325: if (defaults.containsKey(id.getData())) {
0326: Object value = defaults.remove(id.getData());
0327: ntStack.declare((String) id.getData(), value);
0328: } else {
0329: if (i >= args.length
0330: || args[i] instanceof AstNamedArgument) {
0331: Object value = param.jjtGetChild(2)
0332: .jjtAccept(this , null);
0333: ntStack.declare((String) id.getData(),
0334: value);
0335: } else {
0336: ntStack.declare((String) id.getData(),
0337: args[i]);
0338: }
0339: }
0340: }
0341: }
0342: if (defaults.size() > 0) {
0343: throw new IllegalArgumentException("Unknown default "
0344: + defaults + " for function " + functionName);
0345: }
0346: } else {//assume variable parameters (varargs)
0347: ntStack.declare((String) params.getData(), args);
0348: }
0349: }
0350:
0351: /**
0352: * Throws the exception
0353: * @param e the throwable
0354: * @param node the node that the exception current
0355: * @return will not return since exception will always be thrown
0356: */
0357: private ProcessingException generateProcessingException(
0358: Throwable e, SimpleNode node) {
0359: ProcessingException ex = new ProcessingException(
0360: getCurrentContext().getCurrentPage(), e, node);
0361: return ex;
0362: }
0363:
0364: /**
0365: * Include another page as a part of current page and process it
0366: * @param id the id
0367: * @return the object
0368: * @throws Exception if there's exception
0369: */
0370: protected Object includeCall(String id) throws Exception {
0371: return process(id, getCurrentContext());
0372: }
0373:
0374: /**
0375: * Instantiate an instance of class type using the arguments
0376: * @param type the type to instantiate
0377: * @param args the arguments
0378: * @return the object instantiated
0379: * @throws Exception if there's problem in the instantiation
0380: */
0381: protected Object instantiate(Class type, Object[] args)
0382: throws Exception {
0383: if (_logger.isLoggable(Level.FINEST)) {
0384: _logger.finest("Instantiaing " + type + " with "
0385: + StringUtils.concat(args, ","));
0386: }
0387: return ReflectUtils.newInstance(type, args);
0388: }
0389:
0390: /**
0391: * Invoke the method of object obj with given argument
0392: * @param obj the object
0393: * @param methodName the method name
0394: * @param args the arguments
0395: * @return the value return by the method invoked
0396: * @throws Exception if there's problem invoking the method
0397: */
0398: protected Object invokeMethod(Object obj, String methodName,
0399: Object[] args) throws Exception {
0400: if (_logger.isLoggable(Level.FINEST)) {
0401: _logger.finest("Invoking " + obj.getClass() + "."
0402: + methodName + "(" + StringUtils.concat(args, ",")
0403: + ")");
0404: }
0405: if (obj == this ) {
0406: return callFunction(methodName, args);
0407: } else {
0408: if (doMethodStats) {
0409: _methodStats.count(methodName);
0410: }
0411: if (obj instanceof JxpInvocable) {
0412: JxpInvocable invocable = (JxpInvocable) obj;
0413: if (invocable.canInvoke(methodName, args)) {
0414: return invocable.invoke(methodName, args);
0415: }
0416: } //else fall through
0417: return ReflectUtils.invoke(obj, methodName, args);
0418: }
0419: }
0420:
0421: /**
0422: * Look up a variable in current nametable stack
0423: * @param variableName the variable name
0424: * @return the value of the variable
0425: * @throws NoSuchFieldException the the variable cannot be found
0426: */
0427: protected Object lookupVariable(String variableName)
0428: throws NoSuchFieldException {
0429: NametableStack ntStack = getCurrentContext()
0430: .getNametableStack();
0431: if (!ntStack.containsName(variableName)) {
0432: throw new NoSuchFieldException("Variable/Function "
0433: + variableName + " is not declared before");
0434: }
0435: Object v = ntStack.access(variableName);
0436: if (_logger.isLoggable(Level.FINEST)) {
0437: _logger.finest("Looking up variable " + variableName
0438: + " found " + v);
0439: }
0440: return v;
0441: }
0442:
0443: /**
0444: * print the object by printing o.toString() using writer of current context. If the object is null, "null" will be printed.
0445: * @param o the object
0446: * @throws IOException if there's problem doing the printing
0447: */
0448: protected void print(Object o) throws IOException {
0449: if (o == null) {
0450: print("null");
0451: } else {
0452: print(o.toString());
0453: }
0454: }
0455:
0456: /**
0457: * Print the string using writer of current context
0458: * @param s the string
0459: * @throws IOException if there's io problem TODO: make to flag IOException to avoid call writes again
0460: */
0461: protected void print(String s) throws IOException {
0462: Writer writer = getCurrentContext().getWriter();
0463: try {
0464: writer.write(s);
0465: } catch (Exception e) {
0466: _logger.throwing(getClass().getName(), "print", e);
0467: }
0468: }
0469:
0470: /**
0471: * print the object with the line delimiter "\n"
0472: * @param o the object
0473: * @throws IOException if there's problem doing the printing
0474: */
0475: protected void println(Object o) throws IOException {
0476: print(o + "\n");
0477: }
0478:
0479: /**
0480: * print the object with the line delimiter "\n"
0481: * @param s the string
0482: * @throws IOException if there's problem doing the printing
0483: */
0484: protected void println(String s) throws IOException {
0485: print(s + "\n");
0486: }
0487:
0488: /**
0489: * Process a page with empty environment
0490: */
0491: public Object process(String id, Writer writer) throws Exception {
0492: return process(id, writer, Collections.EMPTY_MAP);
0493: }
0494:
0495: /**
0496: * process the page identified by id with the context given
0497: * @param id the id
0498: * @param env the environment
0499: * @return value return by this page
0500: * @throws Exception if there's problem doing the printing
0501: */
0502: public Object process(String id, Writer writer, Map env)
0503: throws Exception {
0504: JxpProcessingContext procContext = _context
0505: .createProcessingContext(env, writer);
0506: int scope = _contextLocal.pushLocal(procContext);
0507: try {
0508: return process(id, procContext);
0509: } finally {
0510: _contextLocal.popLocalUtil(scope);
0511: }
0512: }
0513:
0514: /**
0515: * Processing a page identified by id in current context
0516: * @param id the id
0517: * @return the value return by the processing
0518: * @throws Exception if there's problem doing the printing
0519: */
0520: protected Object process(String id, JxpProcessingContext context)
0521: throws Exception {
0522: //resolve the actual id
0523: String scriptId = id;
0524: JxpPage currentPage = context.getCurrentPage();
0525: if (currentPage != null && !id.startsWith("/")) //relative path
0526: {
0527: String prefix = StringUtils.substringBeforeLast(currentPage
0528: .getName(), "/");
0529: if (prefix != null) {
0530: scriptId = FileUtils.concatFilePath(prefix, id);
0531: }
0532: }
0533: JxpPage page = _context.getPageSource().getJxpPage(scriptId);
0534: try {
0535: context.pushPage(page);
0536: return visit(page.getJxpDocument(), null);
0537: } finally {
0538: context.popPage(page);
0539: }
0540: }
0541:
0542: /**
0543: * Get the current processing context
0544: * @return the current processing context
0545: */
0546: public JxpProcessingContext getCurrentContext() {
0547: return (JxpProcessingContext) _contextLocal.getLocal();
0548: }
0549:
0550: /**
0551: * Process a page identified by id in current context
0552: * @param id the id
0553: * @return the value return by the page
0554: * @throws Exception if there's problem doing the printing
0555: */
0556: protected Object processCall(String id) throws Exception {
0557: JxpProcessingContext context = getCurrentContext();
0558: int scope = context.getNametableStack().newScope();
0559: try {
0560: return process(id, context);
0561: } finally {
0562: context.getNametableStack().closeScope(scope);
0563: }
0564: }
0565:
0566: /**
0567: * Resolve the arguments for function or method call
0568: * @param node the node
0569: * @param context the context
0570: * @return object array containing the resolved argument values
0571: * @throws Exception if there's problem
0572: */
0573: protected Object[] resolveArguments(AstArguments node,
0574: JxpProcessingContext context) throws Exception {
0575: int n = node.jjtGetNumChildren();
0576: Object[] args = new Object[n];
0577: for (int i = 0; i < n; i++) {
0578: args[i] = node.jjtGetChild(i).jjtAccept(this , context);
0579: }
0580: return args;
0581: }
0582:
0583: /**
0584: * Resolve the array dimensions needed
0585: * @param node the ArrayDims node
0586: * @param context the processing context
0587: * @return the int array containing the dimensions info
0588: * @throws Exception if there's problem resolving the dimension
0589: */
0590: protected int[] resolveArrayDims(AstArrayDims node,
0591: JxpProcessingContext context) throws Exception {
0592: int[] dims = new int[node.jjtGetNumChildren()];
0593: for (int i = 0; i < node.jjtGetNumChildren(); i++) {
0594: Object o = node.jjtGetChild(i).jjtAccept(this , context);
0595: if (o instanceof Number) {
0596: dims[i] = ((Number) o).intValue();
0597: } else {
0598: throw generateProcessingException(
0599: new IllegalArgumentException("Array dimension "
0600: + o + " is not a number"), node);
0601: }
0602: }
0603: return dims;
0604: }
0605:
0606: /**
0607: * Resolve the assignment target. Exception will be thrown if the node is not assignable and throwExcpetion is true. Otherwise
0608: * null will be return if the node cannot be resolved to assignment target.
0609: * @param node the simple node or the target
0610: * @param throwException whether to throw exception
0611: * @return the target
0612: * @throws ProcessingException if the target cannot be resolved
0613: */
0614: protected Assignable resolveAssignmentTarget(SimpleNode node,
0615: boolean throwException) throws ProcessingException {
0616: if (node instanceof AstName) {
0617: AstName name = (AstName) node;
0618: List l = (List) name.getData();
0619: JxpProcessingContext context = getCurrentContext();
0620: if (l.size() == 1) {
0621: String variableName = (String) l.get(0);
0622: // first case
0623: if (context.getNametableStack().containsName(
0624: variableName)) {
0625: return new VariableAssignable((String) l.get(0),
0626: context);
0627: } else {
0628: //second case
0629: JxpPage page = context.getCurrentPage();
0630: if (page.hasStaticVariable(variableName)) {
0631: return new StaticVariableAssignable((String) l
0632: .get(0), page);
0633: }
0634: throw generateProcessingException(
0635: new IllegalArgumentException("Variable "
0636: + variableName
0637: + " has not been declared."), node);
0638: }
0639: } else {
0640: //TODO: how about assigning to a field? arr
0641: if (throwException) {
0642: throw generateProcessingException(
0643: new IllegalArgumentException(node
0644: + " is not assignable"), node);
0645: } else {
0646: return null;
0647: }
0648: }
0649: } else if (node instanceof AstArrayReference) {
0650: try {
0651: Object obj = node.jjtGetChild(0).jjtAccept(this , null);
0652: if (obj == null) {
0653: throw generateProcessingException(
0654: new NullPointerException(),
0655: (SimpleNode) node.jjtGetChild(0));
0656: }
0657: if (!obj.getClass().isArray()) {
0658: throw generateProcessingException(
0659: new IllegalArgumentException(
0660: "Argument is not an array"),
0661: (SimpleNode) node.jjtGetChild(0));
0662: }
0663: Object dimObj = node.jjtGetChild(1).jjtAccept(this ,
0664: null);
0665: int dim = 0;
0666: if (dimObj instanceof Number) {
0667: dim = ((Number) dimObj).intValue();
0668: } else {
0669: throw generateProcessingException(
0670: new IllegalArgumentException(
0671: "Invalid index type "
0672: + dimObj.getClass()
0673: + " for array"), node);
0674: }
0675: return new ArrayAssignable(obj, dim);
0676: } catch (ProcessingException e) {
0677: throw (ProcessingException) e;
0678: } catch (Exception e) {
0679: throw generateProcessingException(e, node);
0680: }
0681: } else { //TODO: other kind of assignable such as array etc
0682: if (throwException) {
0683: throw generateProcessingException(
0684: new IllegalArgumentException(node
0685: + " is not assignable"), node);
0686: } else {
0687: return null;
0688: }
0689: }
0690: }
0691:
0692: /**
0693: * Resolve the class. Call the current context for resolving since the imports in context specific
0694: * @param className the class name
0695: * @return the class
0696: */
0697: protected final Class resolveClass(String className) {
0698: return getCurrentContext().resolveClass(className);
0699: }
0700:
0701: /**
0702: * Resolve the field on and object. Also resolve the array length field
0703: * @param obj the object
0704: * @param fieldName the field name
0705: * @return the field value
0706: * @throws Exception if the field cannot be resolved
0707: */
0708: protected Object resolveField(Object obj, String fieldName)
0709: throws Exception {
0710: if (_logger.isLoggable(Level.FINEST)) {
0711: _logger.finest("Resolving field " + fieldName + " of "
0712: + obj);
0713: }
0714: if (obj == null) {
0715: throw new NoSuchFieldException("Cannot find field "
0716: + fieldName + " for null");
0717: }
0718: if (fieldName.equals("class")) {
0719: if (obj instanceof Class) {
0720: return (Class) obj;
0721: } else {
0722: throw new IllegalStateException(
0723: ".class cannot be apply to " + obj);
0724: }
0725: }
0726: if (fieldName.equals("length")) { //check if is array
0727: if (obj.getClass().isArray()) {
0728: return new Integer(Array.getLength(obj));
0729: } //otherwise just pass through
0730: }
0731: if (obj instanceof JxpInvocable) {
0732: JxpInvocable invocable = (JxpInvocable) obj;
0733: if (invocable.canInvoke(fieldName, null)) {
0734: return invocable.invoke(fieldName, null);
0735: }
0736: }
0737: if (obj instanceof Map) {
0738: return ((Map) obj).get(fieldName);
0739: } //otherwise just pass through to use reflection
0740: Field f = null;
0741: if (obj instanceof Class) {
0742: f = ((Class) obj).getField(fieldName);
0743: } else {
0744: f = obj.getClass().getField(fieldName);
0745: }
0746: return f.get(obj);
0747: }
0748:
0749: /**
0750: * Resolve a object given the name in current processing context. It cound be variable, or class
0751: * @param l containing series of identifier
0752: * @return the object associated with the name
0753: * @throws Exception if there's problem resolving the name
0754: */
0755: protected Object resolveName(List l) throws Exception {
0756: Object current = null;
0757: JxpProcessingContext context = getCurrentContext();
0758: NametableStack ntStack = context.getNametableStack();
0759: for (int i = 0; i < l.size(); i++) {
0760: String s = (String) l.get(i);
0761: if (i == 0) {
0762: //first case, variable
0763: if (ntStack.containsName(s)) {
0764: current = ntStack.access(s); //lookup variable
0765: } else {//second case, page static
0766: JxpPage page = context.getCurrentPage();
0767: if (page.hasStaticVariable(s)) {
0768: current = page.getStaticVariable(s);
0769: } else {
0770: //third case, resolve class
0771: current = resolveClass(s);
0772: if (current == null) {
0773: throw new NoSuchFieldException("Variable "
0774: + s + " has not been declared");
0775: }
0776: }
0777: }
0778: } else {
0779: current = resolveField(current, s);
0780: }
0781: }
0782: return current;
0783: }
0784:
0785: /**
0786: * Concat the ASTName to a dotted name notation
0787: * @param name the ASTName object
0788: * @return the dotted name string
0789: */
0790: private String toDottedName(AstName name) {
0791: return StringUtils.concat((List) name.getData(), ".");
0792: }
0793:
0794: /**
0795: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArguments, java.lang.Object)
0796: */
0797: public Object visit(AstArguments node, Object data)
0798: throws Exception {
0799: throw new IllegalStateException(
0800: "visit(AstArguments, Object) should not be called");
0801: }
0802:
0803: /**
0804: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArrayAllocationExpression, java.lang.Object)
0805: */
0806: public Object visit(AstArrayAllocationExpression node, Object data)
0807: throws Exception {
0808: String className = toDottedName((AstName) node.jjtGetChild(0));
0809: Class type = resolveClass(className);
0810: if (type == null) {
0811: throw generateProcessingException(
0812: new ClassNotFoundException(
0813: "No definition found for " + className),
0814: node);
0815: }
0816: SimpleNode n = (SimpleNode) node.jjtGetChild(1);
0817: if (n instanceof AstArrayDims) {
0818: int[] dims = resolveArrayDims((AstArrayDims) n,
0819: getCurrentContext());
0820: return Array.newInstance(type, dims);
0821: } else { //must be ArrayInitializer
0822: return n.jjtAccept(this , type);
0823: }
0824: }
0825:
0826: /**
0827: * (non-Javadoc)
0828: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArrayDims, java.lang.Object)
0829: */
0830: public Object visit(AstArrayDims node, Object data)
0831: throws Exception {
0832: throw generateProcessingException(new IllegalStateException(
0833: "AstArrayDims are not supposed to be called"), node);
0834: }
0835:
0836: /**
0837: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArrayInitializer, java.lang.Object)
0838: */
0839: public Object visit(AstArrayInitializer node, Object data)
0840: throws Exception {
0841: Class type = (data instanceof Class) ? (Class) data
0842: : Object.class;
0843: int dim = node.jjtGetNumChildren();
0844: List l = new ArrayList();
0845: Class elementType = null;
0846: for (int i = 0; i < dim; i++) {
0847: Object element = node.jjtGetChild(i).jjtAccept(this , type);
0848: //make sure the element type is correct
0849: if (element != null) {
0850: elementType = element.getClass(); //save for latter
0851: if (!elementType.isArray()) {//must be primitive - check it
0852: if (!type.isAssignableFrom(element.getClass())) {
0853: throw generateProcessingException(
0854: new IllegalArgumentException(
0855: "Illegal element " + element
0856: + " in "
0857: + type.getName()
0858: + " array"),
0859: (SimpleNode) node.jjtGetChild(i));
0860: }
0861: }
0862: } else {
0863: if (type.isPrimitive()) {
0864: throw generateProcessingException(
0865: new IllegalArgumentException(
0866: "Illegal element " + element
0867: + " in " + type.getName()
0868: + " array"),
0869: (SimpleNode) node.jjtGetChild(i));
0870: }
0871: }
0872: l.add(element);
0873: }
0874: if (elementType != null) {
0875: Object[] array = (Object[]) Array.newInstance(elementType,
0876: l.size());
0877: return l.toArray(array);
0878: } else {
0879: return l.toArray();
0880: }
0881: }
0882:
0883: /**
0884: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArrayReference, java.lang.Object)
0885: */
0886: public Object visit(AstArrayReference node, Object data)
0887: throws Exception {
0888: Object obj = node.jjtGetChild(0).jjtAccept(this , data);
0889: if (obj != null && obj.getClass().isArray()) {
0890: Object dimObj = node.jjtGetChild(1).jjtAccept(this , data);
0891: int dim = 0;
0892: if (dimObj instanceof Number) {
0893: dim = ((Number) dimObj).intValue();
0894: } else {
0895: throw generateProcessingException(
0896: new IllegalArgumentException(
0897: "Invalid index type "
0898: + dimObj.getClass()
0899: + " for array"), node);
0900: }
0901: if (_logger.isLoggable(Level.FINEST)) {
0902: _logger.finest("Resolving array reference of " + obj
0903: + "[" + dim + "]");
0904: }
0905: return Array.get(obj, dim);
0906: } else {
0907: throw generateProcessingException(
0908: new IllegalArgumentException(
0909: "Cannot get array referernce of non-array "
0910: + obj), node);
0911: }
0912: }
0913:
0914: /**
0915: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstAssertStatement, java.lang.Object)
0916: */
0917: public Object visit(AstAssertStatement node, Object data)
0918: throws Exception {
0919: for (int i = 0; i < node.jjtGetNumChildren(); i++) {
0920: Boolean assertion = Evaluator.toBoolean(node.jjtGetChild(i)
0921: .jjtAccept(this , data));
0922: if (!assertion.booleanValue()) {
0923: throw generateProcessingException(new AssertionError(
0924: "Assertion error "), (SimpleNode) node
0925: .jjtGetChild(i));
0926: }
0927: }
0928: return Boolean.TRUE;
0929: }
0930:
0931: /**
0932: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstAssignExpression, java.lang.Object)
0933: */
0934: public Object visit(AstAssignExpression node, Object data)
0935: throws Exception {
0936: Object value = node.jjtGetChild(1).jjtAccept(this , data);
0937: return assign((SimpleNode) node.jjtGetChild(0), value);
0938: }
0939:
0940: /**
0941: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstAndAssignExpression, java.lang.Object)
0942: */
0943: public Object visit(AstBitwiseAndAssignExpression node, Object data)
0944: throws Exception {
0945: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
0946: .jjtGetChild(1).jjtAccept(this , data);
0947: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
0948: .bitwiseAnd(origValue, value));
0949: }
0950:
0951: /**
0952: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBitAndExpression, java.lang.Object)
0953: */
0954: public Object visit(AstBitwiseAndExpression node, Object data)
0955: throws Exception {
0956: return Evaluator.bitwiseAnd(node.jjtGetChild(0).jjtAccept(this ,
0957: data), node.jjtGetChild(1).jjtAccept(this , data));
0958: }
0959:
0960: /**
0961: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstTildeUnaryExpression, java.lang.Object)
0962: */
0963: public Object visit(AstBitwiseComplementExpression node, Object data)
0964: throws Exception {
0965: return Evaluator.bitwiseComplement(node.jjtGetChild(0)
0966: .jjtAccept(this , data));
0967: }
0968:
0969: /**
0970: * (non-Javadoc)
0971: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBitwiseOrAssignExpression, java.lang.Object)
0972: */
0973: public Object visit(AstBitwiseOrAssignExpression node, Object data)
0974: throws Exception {
0975: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
0976: .jjtGetChild(1).jjtAccept(this , data);
0977: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
0978: .bitwiseOr(origValue, value));
0979: }
0980:
0981: /**
0982: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstInclusiveOrExpression, java.lang.Object)
0983: */
0984: public Object visit(AstBitwiseOrExpression node, Object data)
0985: throws Exception {
0986: return Evaluator.bitwiseOr(node.jjtGetChild(0).jjtAccept(this ,
0987: data), node.jjtGetChild(1).jjtAccept(this , data));
0988: }
0989:
0990: /**
0991: * (non-Javadoc)
0992: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBitwiseXOrAssignExpression, java.lang.Object)
0993: */
0994: public Object visit(AstBitwiseXOrAssignExpression node, Object data)
0995: throws Exception {
0996: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
0997: .jjtGetChild(1).jjtAccept(this , data);
0998: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
0999: .bitwiseXOr(origValue, value));
1000: }
1001:
1002: /**
1003: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstExclusiveOrExpression, java.lang.Object)
1004: */
1005: public Object visit(AstBitwiseXOrExpression node, Object data)
1006: throws Exception {
1007: return Evaluator.bitwiseXOr(node.jjtGetChild(0).jjtAccept(this ,
1008: data), node.jjtGetChild(1).jjtAccept(this , data));
1009: }
1010:
1011: /**
1012: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBlock, java.lang.Object)
1013: */
1014: public Object visit(AstBlock node, Object data) throws Exception {
1015: JxpProcessingContext context = getCurrentContext();
1016: int scope = context.getNametableStack().newScope();
1017: Object obj = null;
1018: SimpleNode childNode = null;
1019: int i = 0;
1020: try {
1021: for (i = 0; i < node.jjtGetNumChildren(); i++) {
1022: childNode = (SimpleNode) node.jjtGetChild(i);
1023: obj = childNode.jjtAccept(this , data);
1024: if (obj instanceof Control) {
1025: break;
1026: }
1027: }
1028: } catch (ProcessingException pe) {
1029: throw pe;
1030: } catch (Exception e) {
1031: throw generateProcessingException(e, childNode);
1032: } finally {
1033: context.getNametableStack().closeScope(scope);
1034: }
1035: return obj;
1036: }
1037:
1038: /**
1039: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBreakStatement, java.lang.Object)
1040: */
1041: public Object visit(AstBreakStatement node, Object data)
1042: throws Exception {
1043: return Control.BREAK;
1044: }
1045:
1046: /**
1047: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstCase, java.lang.Object)
1048: */
1049: public Object visit(AstCase node, Object data) throws Exception {
1050: throw generateProcessingException(new IllegalStateException(
1051: "Switch case: are not suppossed to be called"), node);
1052: }
1053:
1054: /**
1055: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstCastExpression, java.lang.Object)
1056: */
1057: public Object visit(AstCastExpression node, Object data)
1058: throws Exception {
1059: return node.jjtGetChild(1).jjtAccept(this , data);
1060: }
1061:
1062: /**
1063: * {@inheritDoc}
1064: */
1065: public Object visit(AstCatchBlock node, Object data)
1066: throws Exception {
1067: throw generateProcessingException(new IllegalStateException(
1068: "This should not be called"), node);
1069: }
1070:
1071: /**
1072: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstConditionalAndExpression, java.lang.Object)
1073: */
1074: public Object visit(AstConditionalAndExpression node, Object data)
1075: throws Exception {
1076: Boolean b1 = Evaluator.toBoolean(node.jjtGetChild(0).jjtAccept(
1077: this , data));
1078: if (!b1.booleanValue()) {
1079: return Boolean.FALSE;
1080: }
1081: Boolean b2 = Evaluator.toBoolean(node.jjtGetChild(1).jjtAccept(
1082: this , data));
1083: if (!b2.booleanValue()) {
1084: return Boolean.FALSE;
1085: } else {
1086: return Boolean.TRUE;
1087: }
1088: }
1089:
1090: /**
1091: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstConditionalOrExpression, java.lang.Object)
1092: */
1093: public Object visit(AstConditionalOrExpression node, Object data)
1094: throws Exception {
1095: Boolean b1 = Evaluator.toBoolean(node.jjtGetChild(0).jjtAccept(
1096: this , data));
1097: if (b1.booleanValue()) {
1098: return Boolean.TRUE;
1099: }
1100: Boolean b2 = Evaluator.toBoolean(node.jjtGetChild(1).jjtAccept(
1101: this , data));
1102: if (b2.booleanValue()) {
1103: return Boolean.TRUE;
1104: } else {
1105: return Boolean.FALSE;
1106: }
1107: }
1108:
1109: /**
1110: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstContent, java.lang.Object)
1111: */
1112: public Object visit(AstContent node, Object data) throws Exception {
1113: Object content = node.getData();
1114: print(content);
1115: return content;
1116: }
1117:
1118: /**
1119: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstContinueStatement, java.lang.Object)
1120: */
1121: public Object visit(AstContinueStatement node, Object data)
1122: throws Exception {
1123: return Control.CONTINUE;
1124: }
1125:
1126: /**
1127: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstSlashAssignExpression, java.lang.Object)
1128: */
1129: public Object visit(AstDivideAssignExpression node, Object data)
1130: throws Exception {
1131: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
1132: .jjtGetChild(1).jjtAccept(this , data);
1133: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
1134: .divide(origValue, value));
1135: }
1136:
1137: /**
1138: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstSlashExpression, java.lang.Object)
1139: */
1140: public Object visit(AstDivideExpression node, Object data)
1141: throws Exception {
1142: return Evaluator.divide(node.jjtGetChild(0).jjtAccept(this ,
1143: data), node.jjtGetChild(1).jjtAccept(this , data));
1144: }
1145:
1146: /**
1147: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstDoStatement, java.lang.Object)
1148: */
1149: public Object visit(AstDoStatement node, Object data)
1150: throws Exception {
1151: Node condition = node.jjtGetChild(1);
1152: Boolean b = null;
1153: Object returnValue = null;
1154: do {
1155: returnValue = node.jjtGetChild(0).jjtAccept(this , data);
1156: if (returnValue instanceof Control) {
1157: if (returnValue == Control.CONTINUE) {
1158: returnValue = null;
1159: } else if (returnValue == Control.BREAK) {
1160: returnValue = null;
1161: break;
1162: } else { //must be return w/wo object
1163: break;
1164: }
1165: }
1166: b = Evaluator.toBoolean(condition.jjtAccept(this , data));
1167: } while (b.booleanValue());
1168: return returnValue;
1169: }
1170:
1171: /**
1172: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstEmptyStatement, java.lang.Object)
1173: */
1174: public Object visit(AstEmptyStatement node, Object data)
1175: throws Exception {
1176: return null;
1177: }
1178:
1179: /**
1180: * @see org.onemind.jxp.parser.JxpParserVisitor#visit(jxp.parser.AstEQExpression, java.lang.Object)
1181: */
1182: public Object visit(AstEQExpression node, Object data)
1183: throws Exception {
1184: Object o1 = node.jjtGetChild(0).jjtAccept(this , data), o2 = node
1185: .jjtGetChild(1).jjtAccept(this , data);
1186: return Evaluator.eq(o1, o2);
1187: }
1188:
1189: /**
1190: * (non-Javadoc)
1191: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstField, java.lang.Object)
1192: */
1193: public Object visit(AstField node, Object data) throws Exception {
1194: throw generateProcessingException(
1195: new IllegalStateException(
1196: "visit(AstField, Object) is not supposed to be called"),
1197: node);
1198: }
1199:
1200: /**
1201: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstFieldDeclaration, java.lang.Object)
1202: */
1203: public Object visit(AstFieldDeclaration node, Object data)
1204: throws Exception {
1205: Boolean isStatic = (node.getData() == null) ? Boolean.FALSE
1206: : Boolean.TRUE;
1207: Object[] passOn = new Object[] { node.jjtGetChild(0), isStatic };
1208: //ignore the type
1209: for (int i = 1; i < node.jjtGetNumChildren(); i++) {
1210: node.jjtGetChild(i).jjtAccept(this , passOn);
1211: }
1212: return null;
1213: }
1214:
1215: /**
1216: * (non-Javadoc)
1217: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstFieldReference, java.lang.Object)
1218: */
1219: public Object visit(AstFieldReference node, Object data)
1220: throws Exception {
1221: Object o1 = node.jjtGetChild(0).jjtAccept(this , data);
1222: String fieldName = (String) ((SimpleNode) node.jjtGetChild(1))
1223: .getData();
1224: return resolveField(o1, fieldName);
1225: }
1226:
1227: /**
1228: * {@inheritDoc}
1229: */
1230: public Object visit(AstFinallyBlock node, Object data)
1231: throws Exception {
1232: return node.jjtGetChild(0).jjtAccept(this , data);
1233: //pass on
1234: }
1235:
1236: /**
1237: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstForInit, java.lang.Object)
1238: */
1239: public Object visit(AstForInit node, Object data) throws Exception {
1240: return node.childrenAccept(this , data);
1241: }
1242:
1243: /**
1244: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstFormalParameter, java.lang.Object)
1245: */
1246: public Object visit(AstFormalParameter node, Object data)
1247: throws Exception {
1248: throw generateProcessingException(
1249: new IllegalStateException(
1250: "visit(AstFormalParameter, Object) are not supposed to be called"),
1251: node);
1252: }
1253:
1254: /**
1255: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstFormalParameters, java.lang.Object)
1256: */
1257: public Object visit(AstFormalParameters node, Object data)
1258: throws Exception {
1259: throw generateProcessingException(
1260: new UnsupportedOperationException(
1261: "Unsupported Language Feature"), node);
1262: }
1263:
1264: /**
1265: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstForStatement, java.lang.Object)
1266: */
1267: public Object visit(AstForStatement node, Object data)
1268: throws Exception {
1269: JxpProcessingContext context = getCurrentContext();
1270: SimpleNode forInit = null, forCondition = null, forUpdate = null, statements = null;
1271: for (int i = 0; i < node.jjtGetNumChildren() - 1; i++) {
1272: SimpleNode n = (SimpleNode) node.jjtGetChild(i);
1273: if (n instanceof AstForInit) {
1274: forInit = n;
1275: } else if (n instanceof AstForUpdate) {
1276: forUpdate = n;
1277: } else {
1278: forCondition = n;
1279: }
1280: }
1281: statements = (SimpleNode) node.jjtGetChild(node
1282: .jjtGetNumChildren() - 1);
1283: int newscope = context.getNametableStack().newScope(); //this must be in front of for init
1284: if (forInit != null) {
1285: forInit.jjtAccept(this , data);
1286: }
1287: Boolean condition = Boolean.TRUE;
1288: if (forCondition != null) {
1289: condition = Evaluator.toBoolean(forCondition.jjtAccept(
1290: this , data));
1291: }
1292: Object returnValue = null;
1293: try {
1294: while (condition.booleanValue()) {
1295: returnValue = statements.jjtAccept(this , data);
1296: if (returnValue == Control.CONTINUE) {
1297: returnValue = null;
1298: //let it pass
1299: } else if (returnValue == Control.BREAK) {
1300: returnValue = null;
1301: break;
1302: } else if (returnValue instanceof Control) { //must be return w/wo object
1303: break;
1304: }
1305: if (forUpdate != null) {
1306: forUpdate.jjtAccept(this , data);
1307: }
1308: if (forCondition != null) {
1309: condition = Evaluator.toBoolean(forCondition
1310: .jjtAccept(this , data));
1311: }
1312: }
1313: } finally {
1314: context.getNametableStack().closeScope(newscope);
1315: }
1316: return returnValue;
1317: }
1318:
1319: /**
1320: * (non-Javadoc)
1321: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstForUpdate, java.lang.Object)
1322: */
1323: public Object visit(AstForUpdate node, Object data)
1324: throws Exception {
1325: return node.childrenAccept(this , data);
1326: }
1327:
1328: /**
1329: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstGEExpression, java.lang.Object)
1330: */
1331: public Object visit(AstGEExpression node, Object data)
1332: throws Exception {
1333: Object o1 = node.jjtGetChild(0).jjtAccept(this , data), o2 = node
1334: .jjtGetChild(1).jjtAccept(this , data);
1335: return Evaluator.ge(o1, o2);
1336: }
1337:
1338: /**
1339: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstGTExpression, java.lang.Object)
1340: */
1341: public Object visit(AstGTExpression node, Object data)
1342: throws Exception {
1343: Object o1 = node.jjtGetChild(0).jjtAccept(this , data), o2 = node
1344: .jjtGetChild(1).jjtAccept(this , data);
1345: return Evaluator.gt(o1, o2);
1346: }
1347:
1348: /**
1349: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstHookExpression, java.lang.Object)
1350: */
1351: public Object visit(AstHookExpression node, Object data)
1352: throws Exception {
1353: Object returnValue = node.jjtGetChild(0).jjtAccept(this , data);
1354: if (returnValue instanceof Boolean) {
1355: if (Boolean.TRUE.equals(returnValue)) {
1356: return node.jjtGetChild(1).jjtAccept(this , data);
1357: } else {
1358: return node.jjtGetChild(2).jjtAccept(this , data);
1359: }
1360: } else {
1361: throw generateProcessingException(
1362: new IllegalArgumentException(
1363: "condition of hook expression is not a boolean expression"),
1364: node);
1365: }
1366: }
1367:
1368: /**
1369: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstIfStatement, java.lang.Object)
1370: */
1371: public Object visit(AstIfStatement node, Object data)
1372: throws Exception {
1373: Boolean condition = Evaluator.toBoolean(node.jjtGetChild(0)
1374: .jjtAccept(this , data));
1375: if (condition.booleanValue()) {
1376: return node.jjtGetChild(1).jjtAccept(this , data);
1377: } else {
1378: if (node.jjtGetNumChildren() > 2) {
1379: return node.jjtGetChild(2).jjtAccept(this , data);
1380: } else {
1381: return null;
1382: }
1383: }
1384: }
1385:
1386: /**
1387: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstImportDeclaration, java.lang.Object)
1388: */
1389: public Object visit(AstImportDeclaration node, Object data)
1390: throws Exception {
1391: JxpProcessingContext context = getCurrentContext();
1392: String packageName = toDottedName((AstName) node.jjtGetChild(0));
1393: String className = (String) node.getData();
1394: String importName = packageName + "." + className;
1395: context.getImports().addImport(importName);
1396: if (_logger.isLoggable(Level.FINEST)) {
1397: _logger.finest("Add import " + importName);
1398: _logger.finest(context.getImports().getPackages()
1399: .toString());
1400: }
1401: return null;
1402: }
1403:
1404: /**
1405: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstInstanceOfExpression, java.lang.Object)
1406: */
1407: public Object visit(AstInstanceOfExpression node, Object data)
1408: throws Exception {
1409: Object obj = node.jjtGetChild(0).jjtAccept(this , data); //the object
1410: if (obj == null) {
1411: return Boolean.FALSE; //always false
1412: } else {
1413: Class c = (Class) node.jjtGetChild(1).jjtAccept(this , data);
1414: return Boolean.valueOf(c.isInstance(obj));
1415: }
1416: }
1417:
1418: /**
1419: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstJxpDocument, java.lang.Object)
1420: */
1421: public Object visit(AstJxpDocument node, Object data)
1422: throws Exception {
1423: int i = 0;
1424: int n = node.jjtGetNumChildren();
1425: Object returnValue = null;
1426: SimpleNode statement = null;
1427: try {
1428: while (i < n) {
1429: statement = (SimpleNode) node.jjtGetChild(i);
1430: returnValue = statement.jjtAccept(this , data);
1431: if (returnValue instanceof Control) {
1432: return returnValue;
1433: }
1434: i++;
1435: }
1436: } catch (ProcessingException pe) {
1437: throw pe;
1438: } catch (Exception e) {
1439: throw generateProcessingException(e, statement);
1440: }
1441: return null;
1442: }
1443:
1444: /**
1445: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLabeledStatement, java.lang.Object)
1446: */
1447: public Object visit(AstLabeledStatement node, Object data)
1448: throws Exception {
1449: throw generateProcessingException(
1450: new UnsupportedOperationException(
1451: "Labeled statement: Unsupported Language Feature"),
1452: node);
1453: }
1454:
1455: /**
1456: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLEExpression, java.lang.Object)
1457: */
1458: public Object visit(AstLEExpression node, Object data)
1459: throws Exception {
1460: Object o1 = node.jjtGetChild(0).jjtAccept(this , data), o2 = node
1461: .jjtGetChild(1).jjtAccept(this , data);
1462: return Evaluator.le(o1, o2);
1463: }
1464:
1465: /**
1466: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLiteral, java.lang.Object)
1467: */
1468: public Object visit(AstLiteral node, Object data) throws Exception {
1469: return node.getData();
1470: }
1471:
1472: /**
1473: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBangUnaryExpression, java.lang.Object)
1474: */
1475: public Object visit(AstLogicalComplementExpression node, Object data)
1476: throws Exception {
1477: Boolean b = Evaluator.toBoolean(node.jjtGetChild(0).jjtAccept(
1478: this , data));
1479: return Boolean.valueOf(!b.booleanValue());
1480: }
1481:
1482: /**
1483: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLShiftAssignExpression, java.lang.Object)
1484: */
1485: public Object visit(AstLShiftAssignExpression node, Object data)
1486: throws Exception {
1487: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
1488: .jjtGetChild(1).jjtAccept(this , data);
1489: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
1490: .leftShift(origValue, value));
1491: }
1492:
1493: /**
1494: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLShiftExpression, java.lang.Object)
1495: */
1496: public Object visit(AstLShiftExpression node, Object data)
1497: throws Exception {
1498: return Evaluator.leftShift(node.jjtGetChild(0).jjtAccept(this ,
1499: data), node.jjtGetChild(1).jjtAccept(this , data));
1500: }
1501:
1502: /**
1503: * (non-Javadoc)
1504: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLTExpression, java.lang.Object)
1505: */
1506: public Object visit(AstLTExpression node, Object data)
1507: throws Exception {
1508: Object o1 = node.jjtGetChild(0).jjtAccept(this , data), o2 = node
1509: .jjtGetChild(1).jjtAccept(this , data);
1510: return Evaluator.lt(o1, o2);
1511: }
1512:
1513: /**
1514: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMethodCall, java.lang.Object)
1515: */
1516: public Object visit(AstMethodCall node, Object data)
1517: throws Exception {
1518: String methodName = (String) node.getData();
1519: Object[] args = resolveArguments((AstArguments) node
1520: .jjtGetChild(0), getCurrentContext());
1521: if (args.length == 0) {
1522: if (methodName.equals("flush")) {
1523: flush();
1524: return null;
1525: }
1526: } else if (args[0] instanceof String && args.length == 1) {
1527: /*
1528: if (methodName.equals("process"))
1529: {
1530: return processCall((String) args[0]);
1531: } else
1532: */
1533: if (methodName.equals("include")) {
1534: return includeCall((String) args[0]);
1535: }
1536: }
1537: try {
1538: return invokeMethod(this , methodName, args);
1539: } catch (ProcessingException e) {
1540: throw e;
1541: } catch (InvocationTargetException e) {
1542: Throwable t = e.getTargetException();
1543: throw generateProcessingException(t, node);
1544: } catch (Exception e) {
1545: throw generateProcessingException(e, node);
1546: }
1547: }
1548:
1549: /**
1550: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMethodDeclaration, java.lang.Object)
1551: */
1552: public Object visit(AstFunctionDeclaration node, Object data)
1553: throws Exception {
1554: int i = 0;
1555: SimpleNode declarator = null;
1556: do {
1557: declarator = (SimpleNode) node.jjtGetChild(i++);
1558: } while (!(declarator instanceof AstFunctionDeclarator));
1559: //child is FunctionDeclarator now
1560: SimpleNode block = null;
1561: int n = node.jjtGetNumChildren();
1562: if (i < n) {
1563: do {
1564: block = (SimpleNode) node.jjtGetChild(i++);
1565: } while (!(block instanceof AstBlock) && i < n);
1566: }
1567: return getCurrentContext().getUserDefinedFunctions().put(
1568: (String) declarator.getData(),
1569: new JxpUserDefinedFunction((SimpleNode) declarator
1570: .jjtGetChild(0), (AstBlock) block));
1571: }
1572:
1573: /**
1574: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMethodDeclarator, java.lang.Object)
1575: */
1576: public Object visit(AstFunctionDeclarator node, Object data)
1577: throws Exception {
1578: throw generateProcessingException(
1579: new IllegalStateException(
1580: "visit(AstFunctionDeclarator,Object) is not meant to be called."),
1581: node);
1582: }
1583:
1584: /**
1585: * (non-Javadoc)
1586: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMethodInvocation, java.lang.Object)
1587: */
1588: public Object visit(AstMethodInvocation node, Object data)
1589: throws Exception {
1590: // the prefix node
1591: Object obj = node.jjtGetChild(0).jjtAccept(this , data);
1592: SimpleNode methodCall = (SimpleNode) node.jjtGetChild(1);
1593: String methodName = (String) methodCall.getData();
1594: if (obj == null) {
1595: throw generateProcessingException(new NullPointerException(
1596: "Cannot invoke method " + methodName
1597: + "(...) of null at "), node);
1598: }
1599: Object[] args = resolveArguments((AstArguments) methodCall
1600: .jjtGetChild(0), getCurrentContext());
1601: try {
1602: return invokeMethod(obj, methodName, args);
1603: } catch (InvocationTargetException e) {
1604: Throwable t = e.getTargetException();
1605: throw generateProcessingException(t, node);
1606: } catch (Exception e) {
1607: throw generateProcessingException(e, node);
1608: }
1609: }
1610:
1611: /**
1612: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMinusAssignExpression, java.lang.Object)
1613: */
1614: public Object visit(AstMinusAssignExpression node, Object data)
1615: throws Exception {
1616: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
1617: .jjtGetChild(1).jjtAccept(this , data);
1618: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
1619: .minus(origValue, value));
1620: }
1621:
1622: /**
1623: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMinusExpression, java.lang.Object)
1624: */
1625: public Object visit(AstMinusExpression node, Object data)
1626: throws Exception {
1627: return Evaluator.minus(node.jjtGetChild(0)
1628: .jjtAccept(this , data), node.jjtGetChild(1).jjtAccept(
1629: this , data));
1630: }
1631:
1632: /**
1633: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstStarAssignExpression, java.lang.Object)
1634: */
1635: public Object visit(AstMultiplyAssignExpression node, Object data)
1636: throws Exception {
1637: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
1638: .jjtGetChild(1).jjtAccept(this , data);
1639: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
1640: .multiply(origValue, value));
1641: }
1642:
1643: /**
1644: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMultiplyExpression, java.lang.Object)
1645: */
1646: public Object visit(AstMultiplyExpression node, Object data)
1647: throws Exception {
1648: return Evaluator.multiply(node.jjtGetChild(0).jjtAccept(this ,
1649: data), node.jjtGetChild(1).jjtAccept(this , data));
1650: }
1651:
1652: /**
1653: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstName, java.lang.Object)
1654: */
1655: public Object visit(AstName node, Object data) throws Exception {
1656: List l = (List) node.getData();
1657: try {
1658: return resolveName(l);
1659: } catch (Exception e) {
1660: throw generateProcessingException(e, node);
1661: }
1662: }
1663:
1664: /**
1665: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstNameList, java.lang.Object)
1666: */
1667: public Object visit(AstNameList node, Object data) throws Exception {
1668: throw generateProcessingException(
1669: new IllegalStateException(
1670: "visit(ASTNameList, Object) not supposed to be called"),
1671: node);
1672: }
1673:
1674: /**
1675: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstNEExpression, java.lang.Object)
1676: */
1677: public Object visit(AstNEExpression node, Object data)
1678: throws Exception {
1679: Object o1 = node.jjtGetChild(0).jjtAccept(this , data), o2 = node
1680: .jjtGetChild(1).jjtAccept(this , data);
1681: return Evaluator.ne(o1, o2);
1682: }
1683:
1684: /**
1685: * (non-Javadoc)
1686: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstObjectAllocationExpression, java.lang.Object)
1687: */
1688: public Object visit(AstObjectAllocationExpression node, Object data)
1689: throws Exception {
1690: String className = toDottedName((AstName) node.jjtGetChild(0));
1691: Class type = getCurrentContext().resolveClass(className);
1692: if (type == null) {
1693: throw generateProcessingException(
1694: new ClassNotFoundException(
1695: "No definition found for " + className),
1696: node);
1697: }
1698: Object[] args = resolveArguments((AstArguments) node
1699: .jjtGetChild(1), getCurrentContext());
1700: try {
1701: return instantiate(type, args);
1702: } catch (InvocationTargetException e) {
1703: Throwable t = e.getTargetException();
1704: throw generateProcessingException(t, node);
1705: } catch (Exception e) {
1706: throw generateProcessingException(e, node);
1707: }
1708: }
1709:
1710: /**
1711: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPlusAssignExpression, java.lang.Object)
1712: */
1713: public Object visit(AstPlusAssignExpression node, Object data)
1714: throws Exception {
1715: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
1716: .jjtGetChild(1).jjtAccept(this , data);
1717: return assign((SimpleNode) node.jjtGetChild(0), Evaluator.plus(
1718: origValue, value));
1719: }
1720:
1721: /**
1722: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPlusExpression, java.lang.Object)
1723: */
1724: public Object visit(AstPlusExpression node, Object data)
1725: throws Exception {
1726: Object o1 = node.jjtGetChild(0).jjtAccept(this , data), o2 = node
1727: .jjtGetChild(1).jjtAccept(this , data);
1728: return Evaluator.plus(o1, o2);
1729: }
1730:
1731: /**
1732: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPostfixDecrementExpression, java.lang.Object)
1733: */
1734: public Object visit(AstPostDecrementExpression node, Object data)
1735: throws Exception {
1736: Object returnValue = node.jjtGetChild(0).jjtAccept(this , data);
1737: Object newValue = Evaluator.minus(returnValue, ONE);
1738: if (resolveAssignmentTarget((SimpleNode) node.jjtGetChild(0),
1739: false) != null) {
1740: assign((SimpleNode) node.jjtGetChild(0), newValue);
1741: }
1742: return returnValue;
1743: }
1744:
1745: /**
1746: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPostfixIncrementExpression, java.lang.Object)
1747: */
1748: public Object visit(AstPostIncrementExpression node, Object data)
1749: throws Exception {
1750: Object returnValue = node.jjtGetChild(0).jjtAccept(this , data);
1751: Object newValue = Evaluator.plus(returnValue, ONE);
1752: if (resolveAssignmentTarget((SimpleNode) node.jjtGetChild(0),
1753: false) != null) {
1754: assign((SimpleNode) node.jjtGetChild(0), newValue);
1755: }
1756: return returnValue;
1757: }
1758:
1759: /**
1760: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPreDecrementExpression, java.lang.Object)
1761: */
1762: public Object visit(AstPreDecrementExpression node, Object data)
1763: throws Exception {
1764: Object returnValue = node.jjtGetChild(0).jjtAccept(this , data);
1765: Object newValue = Evaluator.minus(returnValue, ONE);
1766: //TODO: improve performance
1767: if (resolveAssignmentTarget((SimpleNode) node.jjtGetChild(0),
1768: false) != null) {
1769: assign((SimpleNode) node.jjtGetChild(0), newValue);
1770: }
1771: return newValue;
1772: }
1773:
1774: /**
1775: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPreIncrementExpression, java.lang.Object)
1776: */
1777: public Object visit(AstPreIncrementExpression node, Object data)
1778: throws Exception {
1779: Object returnValue = node.jjtGetChild(0).jjtAccept(this , data);
1780: Object newValue = Evaluator.plus(returnValue, ONE);
1781: //TODO: improve performance
1782: if (resolveAssignmentTarget((SimpleNode) node.jjtGetChild(0),
1783: false) != null) {
1784: assign((SimpleNode) node.jjtGetChild(0), newValue);
1785: }
1786: return newValue;
1787: }
1788:
1789: /**
1790: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPrimaryExpression, java.lang.Object)
1791: */
1792: public Object visit(AstPrimaryExpression node, Object data)
1793: throws Exception {
1794: throw generateProcessingException(
1795: new IllegalStateException(
1796: "visit(AstPrimaryExpression, Object) not supposed to be called."),
1797: node);
1798: }
1799:
1800: /**
1801: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPrimarySuffix, java.lang.Object)
1802: */
1803: public Object visit(AstPrimarySuffix node, Object data)
1804: throws Exception {
1805: throw generateProcessingException(
1806: new IllegalStateException(
1807: "visit(AstPrimarySuffix, Object) not supposed to be called."),
1808: node);
1809: }
1810:
1811: /**
1812: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPrimitiveType, java.lang.Object)
1813: */
1814: public Object visit(AstPrimitiveType node, Object data)
1815: throws Exception {
1816: throw generateProcessingException(
1817: new IllegalStateException(
1818: "visit(AstPrimitiveType, Object) not supposed to be called."),
1819: node);
1820: }
1821:
1822: /**
1823: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPrintStatement, java.lang.Object)
1824: */
1825: public Object visit(AstPrintStatement node, Object data)
1826: throws Exception {
1827: print(node.jjtGetChild(0).jjtAccept(this , data));
1828: return null;
1829: }
1830:
1831: /**
1832: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRemainderExpression, java.lang.Object)
1833: */
1834: public Object visit(AstRemainderExpression node, Object data)
1835: throws Exception {
1836: return Evaluator.remainder(node.jjtGetChild(0).jjtAccept(this ,
1837: data), node.jjtGetChild(1).jjtAccept(this , data));
1838: }
1839:
1840: /**
1841: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRemAssignExpression, java.lang.Object)
1842: */
1843: public Object visit(AstRemAssignExpression node, Object data)
1844: throws Exception {
1845: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
1846: .jjtGetChild(1).jjtAccept(this , data);
1847: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
1848: .remainder(origValue, value));
1849: }
1850:
1851: /**
1852: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstReturnStatement, java.lang.Object)
1853: */
1854: public Object visit(AstReturnStatement node, Object data)
1855: throws Exception {
1856: if (node.jjtGetNumChildren() > 0) {
1857: return new Control(node.jjtGetChild(0)
1858: .jjtAccept(this , data));
1859: } else {
1860: return Control.RETURN;
1861: }
1862: }
1863:
1864: /**
1865: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRSignedShiftAssignExpression, java.lang.Object)
1866: */
1867: public Object visit(AstRSignedShiftAssignExpression node,
1868: Object data) throws Exception {
1869: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
1870: .jjtGetChild(1).jjtAccept(this , data);
1871: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
1872: .rightSignedShift(origValue, value));
1873: }
1874:
1875: /**
1876: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRSignedShiftExpression, java.lang.Object)
1877: */
1878: public Object visit(AstRSignedShiftExpression node, Object data)
1879: throws Exception {
1880: return Evaluator.rightUnsignedShift(node.jjtGetChild(0)
1881: .jjtAccept(this , data), node.jjtGetChild(1).jjtAccept(
1882: this , data));
1883: }
1884:
1885: /**
1886: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRUnsignedShiftAssignExpression, java.lang.Object)
1887: */
1888: public Object visit(AstRUnsignedShiftAssignExpression node,
1889: Object data) throws Exception {
1890: Object origValue = node.jjtGetChild(0).jjtAccept(this , data), value = node
1891: .jjtGetChild(1).jjtAccept(this , data);
1892: return assign((SimpleNode) node.jjtGetChild(0), Evaluator
1893: .rightUnsignedShift(origValue, value));
1894: }
1895:
1896: /**
1897: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRUnsignedShiftExpression, java.lang.Object)
1898: */
1899: public Object visit(AstRUnsignedShiftExpression node, Object data)
1900: throws Exception {
1901: return Evaluator.rightUnsignedShift(node.jjtGetChild(0)
1902: .jjtAccept(this , data), node.jjtGetChild(1).jjtAccept(
1903: this , data));
1904: }
1905:
1906: /**
1907: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstStatementExpressionList, java.lang.Object)
1908: */
1909: public Object visit(AstStatementExpressionList node, Object data)
1910: throws Exception {
1911: throw generateProcessingException(
1912: new IllegalStateException(
1913: "visit(AstStatementExpressionList, Object) not supposed to be called."),
1914: node);
1915: }
1916:
1917: /**
1918: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstSwitchStatement, java.lang.Object)
1919: */
1920: public Object visit(AstSwitchStatement node, Object data)
1921: throws Exception {
1922: Object switchValue = node.jjtGetChild(0).jjtAccept(this , data); //resolve the value first
1923: if (switchValue == null) {
1924: throw generateProcessingException(
1925: new IllegalArgumentException(
1926: "Switch value cannot be null"), node);
1927: }
1928: int n = node.jjtGetNumChildren();
1929: boolean matchCase = false;
1930: for (int i = 1; i < n; i++) {
1931: AstCase case_ = (AstCase) node.jjtGetChild(i);
1932: int caseChildren = case_.jjtGetNumChildren();
1933: if (!matchCase) //haven't match before
1934: {//try to match the case
1935: if (caseChildren == 1) {//must be the default: calse
1936: matchCase = true;
1937: } else {
1938: Object caseValue = case_.jjtGetChild(0).jjtAccept(
1939: this , null);
1940: if (caseValue == null) {
1941: throw generateProcessingException(
1942: new IllegalArgumentException(
1943: "Switch case value cannot be null"),
1944: case_);
1945: }
1946: if (switchValue.equals(caseValue)) {
1947: matchCase = true;
1948: }
1949: }
1950: }
1951: if (matchCase) {
1952: Object obj = case_.jjtGetChild(caseChildren - 1)
1953: .jjtAccept(this , null);
1954: if (obj == Control.BREAK) {
1955: return null;
1956: } else if (obj instanceof Control) {//either return or exit
1957: return obj;
1958: } //else just continue to fall through
1959: }
1960: }
1961: return null;
1962: }
1963:
1964: /**
1965: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstSynchronizedStatement, java.lang.Object)
1966: */
1967: public Object visit(AstSynchronizedStatement node, Object data)
1968: throws Exception {
1969: Object obj = node.jjtGetChild(0).jjtAccept(this , data);
1970: if (obj == null) {
1971: throw generateProcessingException(
1972: new IllegalArgumentException(
1973: "Cannot synchronize on null"), node);
1974: } else {
1975: synchronized (obj) {
1976: return node.jjtGetChild(1).jjtAccept(this , data);
1977: }
1978: }
1979: }
1980:
1981: /**
1982: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstThrowStatement, java.lang.Object)
1983: */
1984: public Object visit(AstThrowStatement node, Object data)
1985: throws Exception {
1986: Object o = node.jjtGetChild(0).jjtAccept(this , data);
1987: if (o instanceof Exception) {
1988: throw (Exception) o;
1989: } else {
1990: throw generateProcessingException(
1991: new IllegalArgumentException(
1992: "Cannot throw non-exception " + o), node);
1993: }
1994: }
1995:
1996: /**
1997: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstTryStatement, java.lang.Object)
1998: */
1999: public Object visit(AstTryStatement node, Object data)
2000: throws Exception {
2001: int n = node.jjtGetNumChildren();
2002: int i = 0;
2003: try {
2004: SimpleNode block = (SimpleNode) node.jjtGetChild(0);
2005: return block.jjtAccept(this , data);
2006: } catch (Throwable e) {
2007: JxpProcessingContext context = getCurrentContext();
2008: Throwable realCause = e;
2009: if (realCause instanceof ProcessingException
2010: && realCause.getCause() != null) {
2011: realCause = realCause.getCause();
2012: }
2013: for (i = 1; i < n; i++) {
2014: SimpleNode handlerBlock = (SimpleNode) node
2015: .jjtGetChild(i);
2016: if (handlerBlock instanceof AstCatchBlock) {
2017: //catchblock
2018: //SimpleNode formalParameter = (SimpleNode) handlerBlock.jjtGetChild(0);
2019: AstType type = (AstType) handlerBlock
2020: .jjtGetChild(0);
2021: Class c = (Class) type.jjtAccept(this , data);
2022: if (c.isAssignableFrom(realCause.getClass())) {
2023: int scope = context.getNametableStack()
2024: .newScope();
2025: try {
2026: AstVariableDeclaratorId id = (AstVariableDeclaratorId) handlerBlock
2027: .jjtGetChild(1);
2028: context.getNametableStack().declare(
2029: (String) id.getData(), realCause);
2030: return handlerBlock.jjtGetChild(2)
2031: .jjtAccept(this , data); //execute the catch block
2032: } catch (Exception eAgain) {
2033: //again
2034: throw generateProcessingException(eAgain,
2035: (SimpleNode) handlerBlock
2036: .jjtGetChild(1));
2037: } finally {
2038: context.getNametableStack().closeScope(
2039: scope);
2040: }
2041: }
2042: }
2043: } //exception has no handler
2044: if (e instanceof ProcessingException) {
2045: throw (ProcessingException) e; //rethrown - should be because of block
2046: } else {
2047: throw new IllegalStateException(
2048: "Should be ProcessingException after try block");
2049: }
2050: } finally {
2051: if (i < n) { //still something un
2052: SimpleNode block = (SimpleNode) node.jjtGetChild(n - 1);
2053: if (block instanceof AstFinallyBlock) {
2054: block.jjtAccept(this , data);
2055: }
2056: }
2057: }
2058: }
2059:
2060: /**
2061: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstUnaryMinusExpression, java.lang.Object)
2062: */
2063: public Object visit(AstUnaryMinusExpression node, Object data)
2064: throws Exception {
2065: return Evaluator.negate(node.jjtGetChild(0).jjtAccept(this ,
2066: data));
2067: }
2068:
2069: /**
2070: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstUnaryPlusExpression, java.lang.Object)
2071: */
2072: public Object visit(AstUnaryPlusExpression node, Object data)
2073: throws Exception {
2074: return node.jjtGetChild(0).jjtAccept(this , data);
2075: }
2076:
2077: /**
2078: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstVariableDeclarator, java.lang.Object)
2079: */
2080: public Object visit(AstVariableDeclarator node, Object data)
2081: throws Exception {
2082: Object[] passOn = (Object[]) data;
2083: Object value = null;
2084: if (node.jjtGetNumChildren() > 1) { //has initializer
2085: value = node.jjtGetChild(1).jjtAccept(this , null);
2086: } else {
2087: AstType type = (AstType) passOn[0];
2088: if (type.jjtGetChild(0) instanceof AstPrimitiveType) {
2089: AstPrimitiveType primitive = (AstPrimitiveType) type
2090: .jjtGetChild(0);
2091: value = PRIMITIVE_DEFAULTS.get(primitive.getData());
2092: }
2093: }
2094: String variableName = (String) ((AstVariableDeclaratorId) node
2095: .jjtGetChild(0)).getData();
2096: if (((Boolean) passOn[1]).booleanValue()) {//static variable flag, pass from visit(AstFieldDeclaration)
2097: JxpPage page = getCurrentContext().getCurrentPage();
2098: if (!page.hasStaticVariable(variableName)) {
2099: page.declareStaticVariable(variableName, value);
2100: }
2101: return value;
2102: } else {
2103: getCurrentContext().getNametableStack().declare(
2104: variableName, value);
2105: return value;
2106: }
2107: }
2108:
2109: /**
2110: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstWhileStatement, java.lang.Object)
2111: */
2112: public Object visit(AstWhileStatement node, Object data)
2113: throws Exception {
2114: Node condition = node.jjtGetChild(0);
2115: Boolean b = Evaluator
2116: .toBoolean(condition.jjtAccept(this , data));
2117: Object returnValue = null;
2118: while (b.booleanValue()) {
2119: returnValue = node.jjtGetChild(1).jjtAccept(this , data);
2120: if (returnValue instanceof Control) {
2121: if (returnValue == Control.CONTINUE) {
2122: returnValue = null; //clear up
2123: } else if (returnValue == Control.BREAK) {
2124: returnValue = null; //clear up
2125: break;
2126: } else { //must be return w/wo object
2127: break;
2128: }
2129: }
2130: b = Evaluator.toBoolean(condition.jjtAccept(this , data));
2131: }
2132: return returnValue;
2133: }
2134:
2135: /**
2136: * @see jxp.parser.JxpParserVisitor#visit(jxp.parser.SimpleNode, java.lang.Object)
2137: */
2138: public Object visit(SimpleNode node, Object data) throws Exception {
2139: throw new IllegalStateException("Illegal state");
2140: }
2141:
2142: /**
2143: * Flush the writer
2144: * @throws IOException if there's io exception
2145: */
2146: public void flush() throws IOException {
2147: getCurrentContext().getWriter().flush();
2148: }
2149:
2150: /**
2151: * {@inheritDoc}
2152: * @todo support array type
2153: * TODO support array type
2154: */
2155: public Object visit(AstType node, Object data) throws Exception {
2156: Node child = node.jjtGetChild(0);
2157: Class c = null;
2158: if (child instanceof AstName) {
2159: AstName name = (AstName) child;
2160: String className = toDottedName(name);
2161: c = getCurrentContext().resolveClass(className);
2162: if (c == null) {
2163: throw generateProcessingException(
2164: new ClassNotFoundException("Class " + className
2165: + " not found"), node);
2166: }
2167: } else {//primitive type
2168: c = (Class) ((AstPrimitiveType) child).getData();
2169: }
2170: //TODO: work on the dimension
2171: return c;
2172: }
2173:
2174: /**
2175: * Get the method stats
2176: * @return the method stats
2177: */
2178: public Counter getMethodStats() {
2179: return _methodStats;
2180: }
2181:
2182: /**
2183: * {@inheritDoc}
2184: */
2185: public Object visit(AstVariableDeclaratorId node, Object data)
2186: throws Exception {
2187: // TODO Auto-generated method stub
2188: throw generateProcessingException(
2189: new IllegalStateException(
2190: "visit(AstVariableDeclaratorId,Object) should not be called directly"),
2191: node);
2192: }
2193:
2194: /**
2195: * {@inheritDoc}
2196: */
2197: public Object visit(AstExitStatement node, Object data)
2198: throws Exception {
2199: return Control.EXIT;
2200: }
2201:
2202: /**
2203: * {@inheritDoc}
2204: */
2205: public Object visit(AstStaticImportDeclaration node, Object data)
2206: throws Exception {
2207: JxpProcessingContext context = getCurrentContext();
2208: AstName name = (AstName) node.jjtGetChild(0);
2209: String className = toDottedName(name);
2210: Class c = context.resolveClass(className);
2211: if (c == null) {
2212: throw generateProcessingException(
2213: new IllegalArgumentException(
2214: "Cannot resolve class " + className), node);
2215: }
2216: StaticImport si = StaticImportUtils.getStaticImport(c);
2217: context.addStaticImport(si);
2218: Iterator it = si.getStaticFields().entrySet().iterator();
2219: NametableStack ntStack = context.getNametableStack();
2220: while (it.hasNext()) {
2221: Map.Entry entry = (Map.Entry) it.next();
2222: ntStack.declare((String) entry.getKey(), entry.getValue());
2223: }
2224: return null;
2225: }
2226:
2227: /**
2228: * {@inheritDoc}
2229: */
2230: public Object visit(AstVariableParameters node, Object data)
2231: throws Exception {
2232: throw generateProcessingException(
2233: new IllegalStateException(
2234: "visit(AstVariableParameters) should not be called directly"),
2235: node);
2236: }
2237:
2238: /**
2239: * {@inheritDoc}
2240: */
2241: public Object visit(AstEnhancedForStatement node, Object data)
2242: throws Exception {
2243: JxpProcessingContext context = getCurrentContext();
2244: String variable = (String) node.getData();
2245: Node statements = node.jjtGetChild(2);
2246: Object colObj = node.jjtGetChild(1).jjtAccept(this , data);
2247: if (colObj instanceof Collection) {//must be
2248: Object returnValue = null;
2249: Iterator it = ((Collection) colObj).iterator();
2250: int newscope = context.getNametableStack().newScope();
2251: try {
2252: context.getNametableStack().declare(variable, null);
2253: while (it.hasNext()) {
2254: assignVariable(variable, it.next());
2255: returnValue = statements.jjtAccept(this , data);
2256: if (returnValue == Control.CONTINUE) {
2257: returnValue = null;
2258: //let it pass
2259: } else if (returnValue == Control.BREAK) {
2260: returnValue = null;
2261: break;
2262: } else if (returnValue instanceof Control) { //must be return w/wo object
2263: break;
2264: }
2265: }
2266: return returnValue;
2267: } finally {
2268: context.getNametableStack().closeScope(newscope);
2269: }
2270: } else {
2271: throw generateProcessingException(
2272: new IllegalArgumentException(
2273: "Expression for enhanced for loop must be collection, get "
2274: + colObj + " instead"), node);
2275: }
2276: }
2277:
2278: public void setDoMethodStats(boolean flag) {
2279: doMethodStats = flag;
2280: }
2281:
2282: public Object visit(AstNamedArgument node, Object data)
2283: throws Exception {
2284: return node; //process it later
2285: }
2286:
2287: /**
2288: * Get current environment
2289: * @return the environment
2290: */
2291: public Map getEnvironment() {
2292: return getCurrentContext().getNametableStack().asMap();
2293: }
2294:
2295: /**
2296: * Return the checkFunctionArgumentType
2297: * @return the checkFunctionArgumentType.
2298: */
2299: protected final boolean isCheckFunctionArgumentType() {
2300: return _checkFunctionArgumentType;
2301: }
2302:
2303: /**
2304: * Set the checkFunctionArgumentType
2305: * @param checkFunctionArgumentType The checkFunctionArgumentType to set.
2306: */
2307: protected final void setCheckFunctionArgumentType(
2308: boolean checkFunctionArgumentType) {
2309: _checkFunctionArgumentType = checkFunctionArgumentType;
2310: }
2311:
2312: public Object visit(AstPageDirective node, Object data)
2313: throws Exception {
2314: Map m = (Map) node.getData();
2315: if (m.containsKey("import")) {
2316: String imports = (String) m.get("import");
2317: JxpProcessingContext context = getCurrentContext();
2318: StringTokenizer st = new StringTokenizer(imports, ",");
2319: while (st.hasMoreTokens()) {
2320: String im = st.nextToken();
2321: context.getImports().addImport(im);
2322: }
2323: }
2324: return null;
2325: }
2326:
2327: public Object visit(AstIncludeDirective node, Object data)
2328: throws Exception {
2329: return null;
2330: }
2331:
2332: public Object visit(AstIsEmptyExpression node, Object data)
2333: throws Exception {
2334: Object obj = node.jjtGetChild(0).jjtAccept(this, data);
2335: return Boolean.valueOf(StringUtils.isNullOrEmpty(obj));
2336: }
2337:
2338: }
|