/* * $Id: BeanShellExpressionValidator.java,v 1.1 2006/09/28 04:59:19 swampwallaby Exp $ * * Copyright (c) 2008-2013 by Brent Easton * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package bsh; import java.io.StringReader; import java.util.ArrayList; import java.util.List; /** * Validate a single line BeanShell expression. * Build a list of variable references in the expression. * * This Class must be defined in package bsh to allow access to * package visible elements in the bsh library. * */ public class BeanShellExpressionValidator { protected String expression; protected List<String> variables = new ArrayList<String>(); protected List<String> methods = new ArrayList<String>(); protected String error; protected boolean valid = false; /** * Build a new Validator and validate the expression * @param expression Expression to validate */ public BeanShellExpressionValidator(String expression) { this.expression = expression; valid = validate(); } /** * Is the expression valid? * @return valid */ public boolean isValid() { return valid; } protected void setValid(boolean b) { valid = b; } /** * Return a list of Variable references in the expression * @return List of variables */ public List<String> getVariables() { return variables; } /** * Return a list of Methods called by the expression * @return List of Methods */ public List<String> getMethods() { return methods; } /** * Return an Error Message if no valid * @return */ public String getError() { return error; } protected void setError(String s) { error = s; } /** * Validate the expression * * @return Expression validity */ protected boolean validate() { final String expr = stripBraces(expression); setError(""); try { Parser p = new Parser(new StringReader(expr + ";")); for (;;) { if (p.Line()) { return true; } else { final SimpleNode node = p.popNode(); if (! processNode(node)) { return false; } } } } catch (ParseException e) { setError(e.getMessage()); return false; } catch (TokenMgrError e) { setError(e.getMessage()); return false; } } /** * If the expression is surrounded by Vassal expression braces {} * replace them with spaces so that it will validate and report errors * in the correct location * * @param s Expression * @return stripped expression */ public static String stripBraces(String s) { String expr = s; if (s.trim().startsWith("{") && s.trim().endsWith("}")) { final int start = s.indexOf("{"); final int end = s.lastIndexOf("}"); StringBuffer buffer = new StringBuffer(s.length()); for (int i = 0; i < s.length(); i++) { if (i == start || i == end) { buffer.append(' '); } else { buffer.append(s.charAt(i)); } } expr = buffer.toString(); } return expr; } /** * Process a Parser Node and extract any Variable and Method references. * Assignemnts are not allowed in an expression, so flag as an error * @param node Parser Node */ protected boolean processNode (SimpleNode node) { if (node == null) { return true; } if (node instanceof BSHAmbiguousName) { final String name = ((BSHAmbiguousName) node).getText().trim(); if ((node.parent instanceof BSHMethodInvocation)) { if (! methods.contains(name)) { methods.add(name); } } else if (! variables.contains(name)) { variables.add(name); } } else if (node instanceof BSHAssignment) { setError("Assignemts (=) not allowed in Expressions. See Help"); return false; } else { if (node.children != null) { for (int i = 0; i < node.children.length; i++) { if (! processNode(node.getChild(i))) { return false; } } } } return true; } }