001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.debugger.jpda.expr;
043:
044: import java.io.StringReader;
045: import java.util.Random;
046:
047: /**
048: * Represents an pre-parsed Java expression to be later evaluated in a specific JVM context.
049: * The expression can have a 1.4 or 1.5 syntax.
050: *
051: * @author Maros Sandor
052: */
053: public class Expression {
054:
055: public static final String LANGUAGE_JAVA_1_4 = JavaParser.LANGUAGE_JAVA_1_4;
056: public static final String LANGUAGE_JAVA_1_5 = JavaParser.LANGUAGE_JAVA_1_5;
057:
058: private static final String REPLACE_return = "return01234";
059: private static final String REPLACE_class = "class01234";
060:
061: private String strExpression;
062: private String language;
063: private SimpleNode root;
064: private String replace_return;
065: private String replace_class;
066:
067: /**
068: * Creates a new expression by pre-parsing the given String representation of the expression.
069: *
070: * @param expr textual representation of an expression
071: * @param language one of the LANGUAGE_XXX constants
072: * @return pre-parsed Java expression
073: * @throws ParseException if the expression has wrong syntax
074: */
075: public static Expression parse(String expr, String language)
076: throws ParseException {
077: String replace_return = REPLACE_return;
078: while (expr.indexOf(replace_return) >= 0) {
079: replace_return = "return" + new Random().nextLong(); // NOI18N
080: }
081: String replace_class = REPLACE_class;
082: while (expr.indexOf(replace_class) >= 0) {
083: replace_class = "class" + new Random().nextLong(); // NOI18N
084: }
085: String replacedExpr = replaceSpecialVar(expr, "return",
086: replace_return); // NOI18N
087: replacedExpr = replaceSpecialVar(replacedExpr, "class",
088: replace_class); // NOI18N
089: StringReader reader = new StringReader(replacedExpr);
090: try {
091: JavaParser parser = new JavaParser(reader);
092: parser.setTargetJDK(language);
093: SimpleNode root = parser.Expression();
094: return new Expression(expr, language, root, replace_return,
095: replace_class);
096: } catch (Error e) {
097: throw new ParseException(e.getMessage());
098: } finally {
099: reader.close();
100: }
101: }
102:
103: private static String replaceSpecialVar(String expr, String var,
104: String replace_var) {
105: int i = expr.indexOf(var);
106: while (i >= 0) {
107: boolean replace;
108: if (i > 0) {
109: char ch = expr.charAt(i - 1);
110: if (Character.isJavaIdentifierStart(ch)
111: || Character.isJavaIdentifierPart(ch)
112: || ch == '.') {
113: replace = false;
114: } else {
115: replace = true;
116: }
117: } else {
118: replace = true;
119: }
120: if (replace && i < (expr.length() - var.length())) {
121: char ch = expr.charAt(i + var.length());
122: if (Character.isJavaIdentifierPart(ch)) {
123: replace = false;
124: }
125: }
126: if (replace) {
127: expr = expr.substring(0, i) + replace_var
128: + expr.substring(i + var.length());
129: i += replace_var.length();
130: } else {
131: i += var.length();
132: }
133: i = expr.indexOf(var, i);
134: }
135: return expr;
136: }
137:
138: private Expression(String expression, String language,
139: SimpleNode root, String replace_return, String replace_class) {
140: strExpression = expression;
141: this .language = language;
142: this .root = root;
143: this .replace_return = replace_return;
144: this .replace_class = replace_class;
145: }
146:
147: /**
148: * Creates an evaluator engine that can be used to evaluate this expression in a given
149: * runtime JVM context.
150: *
151: * @param context a runtime JVM context
152: * @return the evaluator engine
153: */
154: public Evaluator evaluator(EvaluationContext context) {
155: return new Evaluator(this , context);
156: }
157:
158: SimpleNode getRoot() {
159: return root;
160: }
161:
162: public String getLanguage() {
163: return language;
164: }
165:
166: public String getExpression() {
167: return strExpression;
168: }
169:
170: String returnReplaced() {
171: return replace_return;
172: }
173:
174: String classReplaced() {
175: return replace_class;
176: }
177: }
|