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: package org.apache.jmeter.threads;
020:
021: import java.util.HashMap;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.LinkedList;
025: import java.util.List;
026: import java.util.ListIterator;
027: import java.util.Map;
028: import java.util.Set;
029:
030: import org.apache.jmeter.assertions.Assertion;
031: import org.apache.jmeter.config.ConfigTestElement;
032: import org.apache.jmeter.control.Controller;
033: import org.apache.jmeter.control.TransactionController;
034: import org.apache.jmeter.control.TransactionSampler;
035: import org.apache.jmeter.engine.event.LoopIterationListener;
036: import org.apache.jmeter.processor.PostProcessor;
037: import org.apache.jmeter.processor.PreProcessor;
038: import org.apache.jmeter.samplers.SampleListener;
039: import org.apache.jmeter.samplers.Sampler;
040: import org.apache.jmeter.testbeans.TestBeanHelper;
041: import org.apache.jmeter.testelement.AbstractTestElement;
042: import org.apache.jmeter.testelement.TestElement;
043: import org.apache.jmeter.timers.Timer;
044: import org.apache.jorphan.collections.HashTree;
045: import org.apache.jorphan.collections.HashTreeTraverser;
046: import org.apache.jorphan.logging.LoggingManager;
047: import org.apache.log.Logger;
048:
049: public class TestCompiler implements HashTreeTraverser {
050: private static final Logger log = LoggingManager
051: .getLoggerForClass();
052:
053: private LinkedList stack = new LinkedList();
054:
055: private Map samplerConfigMap = new HashMap();
056:
057: private Map transactionControllerConfigMap = new HashMap();
058:
059: private HashTree testTree;
060:
061: /*
062: * This set keeps track of which ObjectPairs have been seen Its purpose is
063: * not entirely clear (please document if you know!) but it is needed,..
064: */
065: private static Set pairing = new HashSet();
066:
067: //List loopIterListeners = new ArrayList();
068:
069: public TestCompiler(HashTree testTree, JMeterVariables vars) {
070: this .testTree = testTree;
071: }
072:
073: /**
074: * Clears the pairing Set Called by StandardJmeterEngine at the start of a
075: * test run.
076: */
077: public static void initialize() {
078: // synch is probably not needed as only called before run starts
079: synchronized (pairing) {
080: pairing.clear();
081: }
082: }
083:
084: public SamplePackage configureSampler(Sampler sampler) {
085: SamplePackage pack = (SamplePackage) samplerConfigMap
086: .get(sampler);
087: pack.setSampler(sampler);
088: configureWithConfigElements(sampler, pack.getConfigs());
089: runPreProcessors(pack.getPreProcessors());
090: return pack;
091: }
092:
093: public SamplePackage configureTransactionSampler(
094: TransactionSampler transactionSampler) {
095: TransactionController controller = transactionSampler
096: .getTransactionController();
097: SamplePackage pack = (SamplePackage) transactionControllerConfigMap
098: .get(controller);
099: pack.setSampler(transactionSampler);
100: return pack;
101: }
102:
103: private void runPreProcessors(List preProcessors) {
104: Iterator iter = preProcessors.iterator();
105: while (iter.hasNext()) {
106: PreProcessor ex = (PreProcessor) iter.next();
107: if (log.isDebugEnabled()) {
108: log.debug("Running preprocessor: "
109: + ((AbstractTestElement) ex).getName());
110: }
111: TestBeanHelper.prepare((TestElement) ex);
112: ex.process();
113: }
114: }
115:
116: public void done(SamplePackage pack) {
117: pack.recoverRunningVersion();
118: }
119:
120: public void addNode(Object node, HashTree subTree) {
121: stack.addLast(node);
122: }
123:
124: public void subtractNode() {
125: log.debug("Subtracting node, stack size = " + stack.size());
126: TestElement child = (TestElement) stack.getLast();
127: trackIterationListeners(stack);
128: if (child instanceof Sampler) {
129: saveSamplerConfigs((Sampler) child);
130: } else if (child instanceof TransactionController) {
131: saveTransactionControllerConfigs((TransactionController) child);
132: }
133: stack.removeLast();
134: if (stack.size() > 0) {
135: ObjectPair pair = new ObjectPair(child, (TestElement) stack
136: .getLast());
137: synchronized (pairing) {// Called from multiple threads
138: if (!pairing.contains(pair)) {
139: pair.addTestElements();
140: pairing.add(pair);
141: }
142: }
143: }
144: }
145:
146: private void trackIterationListeners(LinkedList p_stack) {
147: TestElement child = (TestElement) p_stack.getLast();
148: if (child instanceof LoopIterationListener) {
149: ListIterator iter = p_stack.listIterator(p_stack.size());
150: while (iter.hasPrevious()) {
151: TestElement item = (TestElement) iter.previous();
152: if (item == child) {
153: continue;
154: }
155: if (item instanceof Controller) {
156: TestBeanHelper.prepare(child);
157: ((Controller) item)
158: .addIterationListener((LoopIterationListener) child);
159: break;
160: }
161: }
162: }
163: }
164:
165: public void processPath() {
166: }
167:
168: private void saveSamplerConfigs(Sampler sam) {
169: List configs = new LinkedList();
170: List modifiers = new LinkedList();
171: List controllers = new LinkedList();
172: List responseModifiers = new LinkedList();
173: List listeners = new LinkedList();
174: List timers = new LinkedList();
175: List assertions = new LinkedList();
176: LinkedList posts = new LinkedList();
177: LinkedList pres = new LinkedList();
178: for (int i = stack.size(); i > 0; i--) {
179: addDirectParentControllers(controllers, (TestElement) stack
180: .get(i - 1));
181: Iterator iter = testTree.list(stack.subList(0, i))
182: .iterator();
183: List tempPre = new LinkedList();
184: List tempPost = new LinkedList();
185: while (iter.hasNext()) {
186: TestElement item = (TestElement) iter.next();
187: if ((item instanceof ConfigTestElement)) {
188: configs.add(item);
189: }
190: if (item instanceof SampleListener) {
191: listeners.add(item);
192: }
193: if (item instanceof Timer) {
194: timers.add(item);
195: }
196: if (item instanceof Assertion) {
197: assertions.add(item);
198: }
199: if (item instanceof PostProcessor) {
200: tempPost.add(item);
201: }
202: if (item instanceof PreProcessor) {
203: tempPre.add(item);
204: }
205: }
206: pres.addAll(0, tempPre);
207: posts.addAll(0, tempPost);
208: }
209:
210: SamplePackage pack = new SamplePackage(configs, modifiers,
211: responseModifiers, listeners, timers, assertions,
212: posts, pres, controllers);
213: pack.setSampler(sam);
214: pack.setRunningVersion(true);
215: samplerConfigMap.put(sam, pack);
216: }
217:
218: private void saveTransactionControllerConfigs(
219: TransactionController tc) {
220: List configs = new LinkedList();
221: List modifiers = new LinkedList();
222: List controllers = new LinkedList();
223: List responseModifiers = new LinkedList();
224: List listeners = new LinkedList();
225: List timers = new LinkedList();
226: List assertions = new LinkedList();
227: LinkedList posts = new LinkedList();
228: LinkedList pres = new LinkedList();
229: for (int i = stack.size(); i > 0; i--) {
230: addDirectParentControllers(controllers, (TestElement) stack
231: .get(i - 1));
232: Iterator iter = testTree.list(stack.subList(0, i))
233: .iterator();
234: while (iter.hasNext()) {
235: TestElement item = (TestElement) iter.next();
236: if (item instanceof SampleListener) {
237: listeners.add(item);
238: }
239: if (item instanceof Assertion) {
240: assertions.add(item);
241: }
242: }
243: }
244:
245: SamplePackage pack = new SamplePackage(configs, modifiers,
246: responseModifiers, listeners, timers, assertions,
247: posts, pres, controllers);
248: pack.setSampler(new TransactionSampler(tc, tc.getName()));
249: pack.setRunningVersion(true);
250: transactionControllerConfigMap.put(tc, pack);
251: }
252:
253: /**
254: * @param controllers
255: * @param i
256: */
257: private void addDirectParentControllers(List controllers,
258: TestElement maybeController) {
259: if (maybeController instanceof Controller) {
260: log.debug("adding controller: " + maybeController
261: + " to sampler config");
262: controllers.add(maybeController);
263: }
264: }
265:
266: private static class ObjectPair {
267: TestElement child, parent;
268:
269: public ObjectPair(TestElement one, TestElement two) {
270: this .child = one;
271: this .parent = two;
272: }
273:
274: public void addTestElements() {
275: if (parent instanceof Controller
276: && (child instanceof Sampler || child instanceof Controller)) {
277: parent.addTestElement(child);
278: }
279: }
280:
281: public int hashCode() {
282: return child.hashCode() + parent.hashCode();
283: }
284:
285: public boolean equals(Object o) {
286: if (o instanceof ObjectPair) {
287: return child == ((ObjectPair) o).child
288: && parent == ((ObjectPair) o).parent;
289: }
290: return false;
291: }
292: }
293:
294: private void configureWithConfigElements(Sampler sam, List configs) {
295: Iterator iter = configs.iterator();
296: while (iter.hasNext()) {
297: ConfigTestElement config = (ConfigTestElement) iter.next();
298: sam.addTestElement(config);
299: }
300: }
301: }
|