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 Micro//S ystems, Inc. Portions Copyright 1997-2007 Sun
028: * Micro//S ystems, 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.util.Random;
045:
046: /**
047: * Represents an pre-parsed Java expression to be later evaluated in a specific JVM context.
048: * The expression can have a 1.4 or 1.5 syntax.
049: *
050: *
051: * Uses Compiler API
052: * 1) Generate a method (like evaluate_<long random number>), which takes all local variables as arguments
053: * 2) Add that method into the current source file
054: * 3) Compile the current source file, like http://www.javabeat.net/javabeat/java6/articles/java_6_0_compiler_api_4.php
055: * 4) Traverse the parsed tree and perform the evaluation - http://java.sun.com/javase/6/docs/jdk/api/javac/tree/com/sun/source/util/JavacTask.html
056: * 5) Instead of (4) it would be cool to be able to do a hot-swap. But we can not add new methods. :-(
057: *
058: *
059: * @author Martin Entlicher
060: */
061: public class Expression2 {
062:
063: private static final String REPLACE_return = "return01234";
064: private static final String REPLACE_class = "class01234";
065:
066: private String strExpression;
067: private String language;
068: private String replace_return;
069: private String replace_class;
070:
071: /**
072: * Creates a new expression by pre-parsing the given String representation of the expression.
073: *
074: * @param expr textual representation of an expression
075: * @param language one of the LANGUAGE_XXX constants
076: * @return pre-parsed Java expression
077: * @throws ParseException if the expression has wrong syntax
078: */
079: public static Expression2 parse(String expr, String language) {
080: //throws ParseException {
081: String replace_return = REPLACE_return;
082: while (expr.indexOf(replace_return) >= 0) {
083: replace_return = "return" + new Random().nextLong(); // NOI18N
084: }
085: String replace_class = REPLACE_class;
086: while (expr.indexOf(replace_class) >= 0) {
087: replace_class = "class" + new Random().nextLong(); // NOI18N
088: }
089: String replacedExpr = replaceSpecialVar(expr, "return",
090: replace_return); // NOI18N
091: replacedExpr = replaceSpecialVar(replacedExpr, "class",
092: replace_class); // NOI18N
093: return new Expression2(expr, language, replace_return,
094: replace_class);
095: }
096:
097: private static String replaceSpecialVar(String expr, String var,
098: String replace_var) {
099: int i = expr.indexOf(var);
100: while (i >= 0) {
101: boolean replace;
102: if (i > 0) {
103: char ch = expr.charAt(i - 1);
104: if (Character.isJavaIdentifierStart(ch)
105: || Character.isJavaIdentifierPart(ch)
106: || ch == '.') {
107: replace = false;
108: } else {
109: replace = true;
110: }
111: } else {
112: replace = true;
113: }
114: if (replace && i < (expr.length() - var.length())) {
115: char ch = expr.charAt(i + var.length());
116: if (Character.isJavaIdentifierPart(ch)) {
117: replace = false;
118: }
119: }
120: if (replace) {
121: expr = expr.substring(0, i) + replace_var
122: + expr.substring(i + var.length());
123: i += replace_var.length();
124: } else {
125: i += var.length();
126: }
127: i = expr.indexOf(var, i);
128: }
129: return expr;
130: }
131:
132: private Expression2(String expression, String language,
133: String replace_return, String replace_class) {
134: strExpression = expression;
135: this .language = language;
136: this .replace_return = replace_return;
137: this .replace_class = replace_class;
138: }
139:
140: /**
141: * Creates an evaluator engine that can be used to evaluate this expression in a given
142: * runtime JVM context.
143: *
144: * @param context a runtime JVM context
145: * @return the evaluator engine
146: */
147: public TreeEvaluator evaluator(EvaluationContext context) {
148: return new TreeEvaluator(this , context);
149: }
150:
151: public String getLanguage() {
152: return language;
153: }
154:
155: public String getExpression() {
156: return strExpression;
157: }
158:
159: String returnReplaced() {
160: return replace_return;
161: }
162:
163: String classReplaced() {
164: return replace_class;
165: }
166: }
|