001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: /*
020: * Created on Jul 25, 2003
021: */
022: package org.apache.jmeter.engine.util;
023:
024: import java.io.IOException;
025: import java.io.StringReader;
026: import java.util.LinkedList;
027:
028: import org.apache.jmeter.engine.StandardJMeterEngine;
029: import org.apache.jmeter.functions.Function;
030: import org.apache.jmeter.functions.InvalidVariableException;
031: import org.apache.jmeter.testelement.TestListener;
032: import org.apache.jorphan.logging.LoggingManager;
033: import org.apache.log.Logger;
034:
035: /**
036: * @author ano ano
037: */
038: class FunctionParser {
039: Logger log = LoggingManager.getLoggerForClass();
040:
041: /**
042: * Compile a general string into a list of elements for a CompoundVariable.
043: */
044: LinkedList compileString(String value)
045: throws InvalidVariableException {
046: StringReader reader = new StringReader(value);
047: LinkedList result = new LinkedList();
048: StringBuffer buffer = new StringBuffer();
049: char previous = ' ';
050: char[] current = new char[1];
051: try {
052: while (reader.read(current) == 1) {
053: if (current[0] == '\\') {
054: previous = current[0];
055: if (reader.read(current) == 0) {
056: break;
057: }
058: if (current[0] != '$' && current[0] != ','
059: && current[0] != '\\') {
060: buffer.append(previous);
061: }
062: previous = ' ';
063: buffer.append(current[0]);
064: continue;
065: } else if (current[0] == '{' && previous == '$') {
066: buffer.deleteCharAt(buffer.length() - 1);
067: if (buffer.length() > 0) {
068: result.add(buffer.toString());
069: buffer.setLength(0);
070: }
071: result.add(makeFunction(reader));
072: previous = ' ';
073: } else {
074: buffer.append(current[0]);
075: previous = current[0];
076: }
077: }
078: if (buffer.length() > 0) {
079: result.add(buffer.toString());
080: }
081: } catch (IOException e) {
082: log.error("Error parsing function: " + value, e);
083: result.clear();
084: result.add(value);
085: }
086: if (result.size() == 0) {
087: result.add("");
088: }
089: return result;
090: }
091:
092: /**
093: * Compile a string into a function or SimpleVariable.
094: */
095: Object makeFunction(StringReader reader)
096: throws InvalidVariableException {
097: char[] current = new char[1];
098: char previous = ' ';
099: StringBuffer buffer = new StringBuffer();
100: Object function;
101: try {
102: while (reader.read(current) == 1) {
103: if (current[0] == '\\') {
104: if (reader.read(current) == 0) {
105: break;
106: }
107: previous = ' ';
108: buffer.append(current[0]);
109: continue;
110: } else if (current[0] == '(' && previous != ' ') {
111: String funcName = buffer.toString();
112: function = CompoundVariable
113: .getNamedFunction(funcName);
114: buffer.setLength(0);
115: if (function instanceof Function) {
116: ((Function) function)
117: .setParameters(parseParams(reader));
118: if (reader.read(current) == 0
119: || current[0] != '}') {
120: reader.reset();// set to start of string
121: char[] cb = new char[100];
122: reader.read(cb);// return deliberately ignored
123: throw new InvalidVariableException(
124: "Expected } after " + funcName
125: + " function call in "
126: + new String(cb));
127: }
128: if (function instanceof TestListener) {
129: StandardJMeterEngine
130: .register((TestListener) function);
131: }
132: return function;
133: }
134: continue;
135: } else if (current[0] == '}') {
136: function = CompoundVariable.getNamedFunction(buffer
137: .toString());
138: buffer.setLength(0);
139: return function;
140: } else {
141: buffer.append(current[0]);
142: previous = current[0];
143: }
144: }
145: } catch (IOException e) {
146: log
147: .error("Error parsing function: "
148: + buffer.toString(), e);
149: return null;
150: }
151: log.warn("Probably an invalid function string: "
152: + buffer.toString());
153: return buffer.toString();
154: }
155:
156: /**
157: * Compile a String into a list of parameters, each made into a
158: * CompoundVariable.
159: */
160: LinkedList parseParams(StringReader reader)
161: throws InvalidVariableException {
162: LinkedList result = new LinkedList();
163: StringBuffer buffer = new StringBuffer();
164: char[] current = new char[1];
165: char previous = ' ';
166: int functionRecursion = 0;
167: int parenRecursion = 0;
168: try {
169: while (reader.read(current) == 1) {
170: if (current[0] == '\\') {
171: buffer.append(current[0]);
172: if (reader.read(current) == 0) {
173: break;
174: }
175: previous = ' ';
176: buffer.append(current[0]);
177: continue;
178: } else if (current[0] == ',' && functionRecursion == 0) {
179: CompoundVariable param = new CompoundVariable();
180: param.setParameters(buffer.toString());
181: buffer.setLength(0);
182: result.add(param);
183: } else if (current[0] == ')' && functionRecursion == 0
184: && parenRecursion == 0) {
185: CompoundVariable param = new CompoundVariable();
186: param.setParameters(buffer.toString());
187: buffer.setLength(0);
188: result.add(param);
189: return result;
190: } else if (current[0] == '{' && previous == '$') {
191: buffer.append(current[0]);
192: previous = current[0];
193: functionRecursion++;
194: } else if (current[0] == '}' && functionRecursion > 0) {
195: buffer.append(current[0]);
196: previous = current[0];
197: functionRecursion--;
198: } else if (current[0] == ')' && functionRecursion == 0
199: && parenRecursion > 0) {
200: buffer.append(current[0]);
201: previous = current[0];
202: parenRecursion--;
203: } else if (current[0] == '(' && functionRecursion == 0) {
204: buffer.append(current[0]);
205: previous = current[0];
206: parenRecursion++;
207: } else {
208: buffer.append(current[0]);
209: previous = current[0];
210: }
211: }
212: } catch (IOException e) {
213: log
214: .error("Error parsing function: "
215: + buffer.toString(), e);
216: }
217: log.warn("Probably an invalid function string: "
218: + buffer.toString());
219: CompoundVariable var = new CompoundVariable();
220: var.setParameters(buffer.toString());
221: result.add(var);
222: return result;
223: }
224: }
|