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.modifiers;
020:
021: import java.io.Serializable;
022: import java.util.Collection;
023: import java.util.LinkedList;
024:
025: import org.apache.jmeter.engine.event.LoopIterationEvent;
026: import org.apache.jmeter.engine.event.LoopIterationListener;
027: import org.apache.jmeter.processor.PreProcessor;
028: import org.apache.jmeter.testelement.AbstractTestElement;
029: import org.apache.jmeter.testelement.TestElement;
030: import org.apache.jmeter.testelement.property.BooleanProperty;
031: import org.apache.jmeter.testelement.property.CollectionProperty;
032: import org.apache.jmeter.testelement.property.PropertyIterator;
033: import org.apache.jmeter.threads.JMeterVariables;
034: import org.apache.jorphan.logging.LoggingManager;
035: import org.apache.log.Logger;
036:
037: public class UserParameters extends AbstractTestElement implements
038: Serializable, PreProcessor, LoopIterationListener {
039: private static final Logger log = LoggingManager
040: .getLoggerForClass();
041:
042: public static final String NAMES = "UserParameters.names";// $NON-NLS-1$
043:
044: public static final String THREAD_VALUES = "UserParameters.thread_values";// $NON-NLS-1$
045:
046: public static final String PER_ITERATION = "UserParameters.per_iteration";// $NON-NLS-1$
047:
048: /*
049: * Although the lock appears to be an instance lock, in fact the lock is
050: * shared between all threads in a thread group, but different thread groups
051: * have different locks - see the clone() method below
052: *
053: * The lock ensures that all the variables are processed together, which is
054: * important for functions such as __CSVRead and _StringFromFile.
055: */
056: private Integer lock = new Integer(0);
057:
058: public CollectionProperty getNames() {
059: return (CollectionProperty) getProperty(NAMES);
060: }
061:
062: public CollectionProperty getThreadLists() {
063: return (CollectionProperty) getProperty(THREAD_VALUES);
064: }
065:
066: /**
067: * The list of names of the variables to hold values. This list must come in
068: * the same order as the sub lists that are given to
069: * {@link #setThreadLists(Collection)}.
070: */
071: public void setNames(Collection list) {
072: setProperty(new CollectionProperty(NAMES, list));
073: }
074:
075: /**
076: * The list of names of the variables to hold values. This list must come in
077: * the same order as the sub lists that are given to
078: * {@link #setThreadLists(CollectionProperty)}.
079: */
080: public void setNames(CollectionProperty list) {
081: setProperty(list);
082: }
083:
084: /**
085: * The thread list is a list of lists. Each list within the parent list is a
086: * collection of values for a simulated user. As many different sets of
087: * values can be supplied in this fashion to cause JMeter to set different
088: * values to variables for different test threads.
089: */
090: public void setThreadLists(Collection threadLists) {
091: setProperty(new CollectionProperty(THREAD_VALUES, threadLists));
092: }
093:
094: /**
095: * The thread list is a list of lists. Each list within the parent list is a
096: * collection of values for a simulated user. As many different sets of
097: * values can be supplied in this fashion to cause JMeter to set different
098: * values to variables for different test threads.
099: */
100: public void setThreadLists(CollectionProperty threadLists) {
101: setProperty(threadLists);
102: }
103:
104: private CollectionProperty getValues() {
105: CollectionProperty threadValues = (CollectionProperty) getProperty(THREAD_VALUES);
106: if (threadValues.size() > 0) {
107: return (CollectionProperty) threadValues
108: .get(getThreadContext().getThreadNum()
109: % threadValues.size());
110: }
111: return new CollectionProperty("noname", new LinkedList());
112: }
113:
114: public boolean isPerIteration() {
115: return getPropertyAsBoolean(PER_ITERATION);
116: }
117:
118: public void setPerIteration(boolean perIter) {
119: setProperty(new BooleanProperty(PER_ITERATION, perIter));
120: }
121:
122: public void process() {
123: if (log.isDebugEnabled()) {
124: log.debug(Thread.currentThread().getName()
125: + " process " + isPerIteration());//$NON-NLS-1$
126: }
127: if (!isPerIteration()) {
128: setValues();
129: }
130: }
131:
132: private void setValues() {
133: synchronized (lock) {
134: if (log.isDebugEnabled()) {
135: log.debug(Thread.currentThread().getName()
136: + " Running up named: " + getName());//$NON-NLS-1$
137: }
138: PropertyIterator namesIter = getNames().iterator();
139: PropertyIterator valueIter = getValues().iterator();
140: JMeterVariables jmvars = getThreadContext().getVariables();
141: while (namesIter.hasNext() && valueIter.hasNext()) {
142: String name = namesIter.next().getStringValue();
143: String value = valueIter.next().getStringValue();
144: if (log.isDebugEnabled()) {
145: log
146: .debug(Thread.currentThread().getName()
147: + " saving variable: " + name + "=" + value);//$NON-NLS-1$
148: }
149: jmvars.put(name, value);
150: }
151: }
152: }
153:
154: /**
155: * @see LoopIterationListener#iterationStart(LoopIterationEvent)
156: */
157: public void iterationStart(LoopIterationEvent event) {
158: if (log.isDebugEnabled()) {
159: log.debug(Thread.currentThread().getName()
160: + " iteration start " + isPerIteration());//$NON-NLS-1$
161: }
162: if (isPerIteration()) {
163: setValues();
164: }
165: }
166:
167: /*
168: * (non-Javadoc) A new instance is created for each thread group, and the
169: * clone() method is then called to create copies for each thread in a
170: * thread group. This means that the lock object is common to a thread
171: * group; separate thread groups have separate locks. If this is not
172: * intended, the lock object could be made static.
173: *
174: * @see java.lang.Object#clone()
175: */
176: public Object clone() {
177: UserParameters up = (UserParameters) super .clone();
178: up.lock = lock; // ensure that clones share the same lock object
179: return up;
180: }
181:
182: /*
183: * (non-Javadoc)
184: *
185: * @see AbstractTestElement#mergeIn(TestElement)
186: */
187: protected void mergeIn(TestElement element) {
188: // super.mergeIn(element);
189: }
190: }
|