001: /**
002: * MVEL (The MVFLEX Expression Language)
003: *
004: * Copyright (C) 2007 Christopher Brock, MVFLEX/Valhalla Project and the Codehaus
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: */package org.mvel.optimizers;
019:
020: import org.mvel.compiler.AbstractParser;
021: import static org.mvel.util.PropertyTools.isIdentifierPart;
022:
023: import static java.lang.Character.isWhitespace;
024: import static java.lang.Thread.currentThread;
025: import java.lang.reflect.Method;
026:
027: /**
028: * @author Christopher Brock
029: */
030: public class AbstractOptimizer extends AbstractParser {
031: protected static final int BEAN = 0;
032: protected static final int METH = 1;
033: protected static final int COL = 2;
034:
035: protected int start = 0;
036:
037: protected Object tryStaticAccess() {
038: int begin = cursor;
039: try {
040: /**
041: * Try to resolve this *smartly* as a static class reference.
042: *
043: * This starts at the end of the token and starts to step backwards to figure out whether
044: * or not this may be a static class reference. We search for method calls simply by
045: * inspecting for ()'s. The first union area we come to where no brackets are present is our
046: * test-point for a class reference. If we find a class, we pass the reference to the
047: * property accessor along with trailing methods (if any).
048: *
049: */
050: boolean meth = false;
051: int depth = 0;
052: int last = length;
053: for (int i = length - 1; i > 0; i--) {
054: switch (expr[i]) {
055: case '.':
056: if (!meth) {
057: try {
058: cursor = last;
059: return currentThread()
060: .getContextClassLoader().loadClass(
061: new String(expr, 0, last));
062: } catch (ClassNotFoundException e) {
063: Class cls = currentThread()
064: .getContextClassLoader().loadClass(
065: new String(expr, 0, i));
066: String name = new String(expr, i + 1,
067: expr.length - i - 1);
068: try {
069: return cls.getField(name);
070: } catch (NoSuchFieldException nfe) {
071: for (Method m : cls.getMethods()) {
072: if (name.equals(m.getName()))
073: return m;
074: }
075: return null;
076: }
077: }
078: }
079:
080: meth = false;
081: last = i;
082: break;
083: case ')':
084: if (depth++ == 0)
085: meth = true;
086: break;
087: case '(':
088: depth--;
089: break;
090:
091: case '\'':
092: while (--i > 0) {
093: if (expr[i] == '\'' && expr[i - 1] != '\\') {
094: break;
095: }
096: }
097: break;
098:
099: case '"':
100: while (--i > 0) {
101: if (expr[i] == '"' && expr[i - 1] != '\\') {
102: break;
103: }
104: }
105: break;
106: }
107: }
108: } catch (Exception cnfe) {
109: cursor = begin;
110: }
111:
112: return null;
113: }
114:
115: protected int nextSubToken() {
116: skipWhitespace();
117:
118: switch (expr[start = cursor]) {
119: case '[':
120: return COL;
121: case '.':
122: skipWhitespace();
123: if ((start + 1) != length && expr[cursor = ++start] == '?') {
124: cursor = ++start;
125: fields = -1;
126: }
127: break;
128: }
129:
130: //noinspection StatementWithEmptyBody
131: while (++cursor < length && isIdentifierPart(expr[cursor]))
132: ;
133:
134: if (cursor != length) {
135: skipWhitespace();
136: switch (expr[cursor]) {
137: case '[':
138: return COL;
139: case '(':
140: return METH;
141: default:
142: return BEAN;
143: }
144: }
145:
146: return 0;
147: }
148:
149: protected String capture() {
150: /**
151: * Trim off any whitespace.
152: */
153: return new String(expr, start = trimRight(start),
154: trimLeft(cursor) - start);
155: }
156:
157: protected void whiteSpaceSkip() {
158: if (cursor < length)
159: //noinspection StatementWithEmptyBody
160: while (isWhitespace(expr[cursor]) && ++cursor != length)
161: ;
162: }
163:
164: protected boolean scanTo(char c) {
165: for (; cursor != length; cursor++) {
166: if (expr[cursor] == c) {
167: return true;
168: }
169: }
170: return false;
171: }
172:
173: protected int containsStringLiteralTermination() {
174: int pos = cursor;
175: for (pos--; pos != 0; pos--) {
176: if (expr[pos] == '\'' || expr[pos] == '"')
177: return pos;
178: else if (!isWhitespace(expr[pos]))
179: return pos;
180: }
181: return -1;
182: }
183: }
|