/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.jmeter.control; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.jmeter.engine.event.LoopIterationEvent; import org.apache.jmeter.engine.event.LoopIterationListener; import org.apache.jmeter.samplers.Sampler; import org.apache.jmeter.testelement.AbstractTestElement; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.threads.TestCompiler; import org.apache.jmeter.threads.TestCompilerHelper; import org.apache.jorphan.logging.LoggingManager; import org.apache.log.Logger; import com.pontetec.stonesoup.trace.Tracer; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.PrintStream; import java.util.HashMap; import java.util.Map; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import fi.iki.elonen.NanoHTTPD; import java.io.UnsupportedEncodingException; import java.io.File; import java.util.regex.Matcher; import java.util.regex.Pattern; /** *
* This class is the basis for all the controllers. * It also implements SimpleController. *
** The main entry point is next(), which is called by by JMeterThread as follows: *
*
* while (running && (sampler = controller.next()) != null)
*
* Determines the next sampler to be processed. *
* ** If isDone, returns null. *
* ** Gets the list element using current pointer. * If this is null, calls {@link #nextIsNull()}. *
* ** If the list element is a sampler, calls {@link #nextIsASampler(Sampler)}, * otherwise calls {@link #nextIsAController(Controller)} *
* ** If any of the called methods throws NextIsNullException, returns null, * otherwise the value obtained above is returned. *
* * @return the next sampler or null */ public Sampler next() { fireIterEvents(); if (log.isDebugEnabled()) { log.debug("Calling next on: " + this.getClass().getName()); } if (isDone()) { return null; } Sampler returnValue = null; try { TestElement currentElement = getCurrentElement(); setCurrentElement(currentElement); if (currentElement == null) { // incrementCurrent(); returnValue = nextIsNull(); } else { if (currentElement instanceof Sampler) { returnValue = nextIsASampler((Sampler) currentElement); } else { // must be a controller returnValue = nextIsAController((Controller) currentElement); } } } catch (NextIsNullException e) { // NOOP } return returnValue; } /** * @see org.apache.jmeter.control.Controller#isDone() */ public boolean isDone() { return done; } protected void setDone(boolean done) { this.done = done; } protected boolean isFirst() { return first; } public void setFirst(boolean b) { first = b; } /** * Called by next() if the element is a Controller, * and returns the next sampler from the controller. * If this is null, then updates the current pointer and makes recursive call to next(). * @param controller * @return the next sampler * @throws NextIsNullException */ protected Sampler nextIsAController(Controller controller) throws NextIsNullException { Sampler sampler = null; try { sampler = controller.next(); } catch (StackOverflowError soe) { // See bug 50618 Catches a StackOverflowError when a condition returns // always false (after at least one iteration with return true) log.warn("StackOverflowError detected"); // $NON-NLS-1$ throw new NextIsNullException("StackOverflowError detected", soe); } if (sampler == null) { currentReturnedNull(controller); sampler = next(); } return sampler; } /** * Increment the current pointer and return the element. * Called by next() if the element is a sampler. * (May be overriden by sub-classes). * * @param element * @return input element * @throws NextIsNullException */ protected Sampler nextIsASampler(Sampler element) throws NextIsNullException { incrementCurrent(); return element; } /** * Called by next() when getCurrentElement() returns null. * Reinitialises the controller. * * @return null (always, for this class) * @throws NextIsNullException */ protected Sampler nextIsNull() throws NextIsNullException { reInitialize(); return null; } /** * {@inheritDoc} */ public void triggerEndOfLoop() { reInitialize(); } /** * Called to re-initialize a index of controller's elements (Bug 50032) * */ protected void reInitializeSubController() { boolean wasFlagSet = getThreadContext().setIsReinitializingSubControllers(); try { TestElement currentElement = getCurrentElement(); if (currentElement != null) { if (currentElement instanceof Sampler) { nextIsASampler((Sampler) currentElement); } else { // must be a controller if (nextIsAController((Controller) currentElement) != null) { reInitializeSubController(); } } } } catch (NextIsNullException e) { // NOOP } finally { if (wasFlagSet) { getThreadContext().unsetIsReinitializingSubControllers(); } } } /** * If the controller is done, remove it from the list, * otherwise increment to next entry in list. * * @param c controller */ protected void currentReturnedNull(Controller c) { if (c.isDone()) { removeCurrentElement(); } else { incrementCurrent(); } } /** * Gets the SubControllers attribute of the GenericController object * * @return the SubControllers value */ protected List
* Gets the element indicated by the current
index, if one exists,
* from the subControllersAndSamplers
list.
*
* If the subControllersAndSamplers
list is empty,
* then set done = true, and throw NextIsNullException.
*