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.control;
020:
021: import java.util.ArrayList;
022: import java.util.Enumeration;
023: import java.util.List;
024:
025: import javax.swing.tree.TreeNode;
026:
027: import org.apache.jmeter.gui.GuiPackage;
028: import org.apache.jmeter.gui.tree.JMeterTreeNode;
029: import org.apache.jmeter.testelement.TestElement;
030: import org.apache.jmeter.testelement.property.CollectionProperty;
031: import org.apache.jmeter.testelement.property.JMeterProperty;
032: import org.apache.jmeter.testelement.property.NullProperty;
033: import org.apache.jorphan.collections.HashTree;
034: import org.apache.jorphan.collections.ListedHashTree;
035:
036: /**
037: * The goal of ModuleController is to add modularity to JMeter. The general idea
038: * is that web applications consist of small units of functionality (i.e. Logon,
039: * Create Account, Logoff...) which consist of requests that implement the
040: * functionality. These small units of functionality can be stored in
041: * SimpleControllers as modules that can be linked together quickly to form
042: * tests. ModuleController facilitates this by acting as a pointer to any
043: * controller that sits under the WorkBench. The controller and it's subelements
044: * will be substituted in place of the ModuleController at runtime. Config
045: * elements can be attached to the ModuleController to alter the functionality
046: * (which user logs in, which account is created, etc.) of the module.
047: *
048: * @author Thad Smith
049: */
050: public class ModuleController extends GenericController implements
051: ReplaceableController {
052:
053: private static final String NODE_PATH = "ModuleController.node_path";// $NON-NLS-1$
054:
055: private JMeterTreeNode selectedNode = null;
056:
057: /**
058: * No-arg constructor
059: *
060: * @see java.lang.Object#Object()
061: */
062: public ModuleController() {
063: super ();
064: }
065:
066: public Object clone() {
067: ModuleController clone = (ModuleController) super .clone();
068: if (selectedNode == null) {
069: this .restoreSelected();
070: }
071: clone.selectedNode = selectedNode;
072: return clone;
073: }
074:
075: /**
076: * Sets the (@link JMeterTreeNode) which represents the controller which
077: * this object is pointing to. Used for building the test case upon
078: * execution.
079: *
080: * @param tn
081: * JMeterTreeNode
082: * @see org.apache.jmeter.gui.tree.JMeterTreeNode
083: */
084: public void setSelectedNode(JMeterTreeNode tn) {
085: selectedNode = tn;
086: setNodePath();
087: }
088:
089: /**
090: * Gets the (@link JMeterTreeNode) for the Controller
091: *
092: * @return JMeterTreeNode
093: */
094: public JMeterTreeNode getSelectedNode() {
095: if (selectedNode == null)
096: restoreSelected();
097: return selectedNode;
098: }
099:
100: private void setNodePath() {
101: List nodePath = new ArrayList();
102: if (selectedNode != null) {
103: TreeNode[] path = selectedNode.getPath();
104: for (int i = 0; i < path.length; i++) {
105: nodePath.add(((JMeterTreeNode) path[i]).getName());
106: }
107: // nodePath.add(selectedNode.getName());
108: }
109: setProperty(new CollectionProperty(NODE_PATH, nodePath));
110: }
111:
112: public List getNodePath() {
113: JMeterProperty prop = getProperty(NODE_PATH);
114: if (!(prop instanceof NullProperty)) {
115: return (List) ((CollectionProperty) prop).getObjectValue();
116: }
117: return null;
118: }
119:
120: private void restoreSelected() {
121: GuiPackage gp = GuiPackage.getInstance();
122: if (gp != null) {
123: JMeterTreeNode root = (JMeterTreeNode) gp.getTreeModel()
124: .getRoot();
125: resolveReplacementSubTree(root);
126: }
127: }
128:
129: /**
130: * Compute the replacement tree.
131: * @param context
132: */
133: public void resolveReplacementSubTree(Object context) {
134: JMeterTreeNode root = (JMeterTreeNode) context;
135: if (selectedNode == null) {
136: List nodePathList = getNodePath();
137: if (nodePathList != null && nodePathList.size() > 0) {
138: traverse(root, nodePathList, 1);
139: }
140: }
141: }
142:
143: private void traverse(JMeterTreeNode node, List nodePath, int level) {
144: if (node != null && nodePath.size() > level) {
145: for (int i = 0; i < node.getChildCount(); i++) {
146: JMeterTreeNode cur = (JMeterTreeNode) node
147: .getChildAt(i);
148: if (cur.getName()
149: .equals(nodePath.get(level).toString())) {
150: if (nodePath.size() == (level + 1))
151: selectedNode = cur;
152: traverse(cur, nodePath, level + 1);
153: }
154: }
155: }
156: }
157:
158: /**
159: * Copies the controller's subelements into the execution tree
160: *
161: */
162: public HashTree getReplacementSubTree() {
163: HashTree tree = new ListedHashTree();
164: if (selectedNode != null) {
165: if (!selectedNode.isEnabled()) {
166: selectedNode = cloneTreeNode(selectedNode);
167: selectedNode.setEnabled(true);
168: }
169: tree.add(selectedNode);
170: createSubTree(tree, selectedNode);
171: }
172: return tree;
173: }
174:
175: private void createSubTree(HashTree tree, JMeterTreeNode node) {
176: Enumeration e = node.children();
177: while (e.hasMoreElements()) {
178: JMeterTreeNode subNode = (JMeterTreeNode) e.nextElement();
179: tree.add(subNode);
180: createSubTree(tree.getTree(subNode), subNode);
181: }
182: }
183:
184: private static JMeterTreeNode cloneTreeNode(JMeterTreeNode node) {
185: JMeterTreeNode treeNode = (JMeterTreeNode) node.clone();
186: treeNode.setUserObject(((TestElement) node.getUserObject())
187: .clone());
188: cloneChildren(treeNode, node);
189: return treeNode;
190: }
191:
192: private static void cloneChildren(JMeterTreeNode to,
193: JMeterTreeNode from) {
194: Enumeration enumr = from.children();
195: while (enumr.hasMoreElements()) {
196: JMeterTreeNode child = (JMeterTreeNode) enumr.nextElement();
197: JMeterTreeNode childClone = (JMeterTreeNode) child.clone();
198: childClone.setUserObject(((TestElement) child
199: .getUserObject()).clone());
200: to.add(childClone);
201: cloneChildren((JMeterTreeNode) to.getLastChild(), child);
202: }
203: }
204:
205: }
|