Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/JMeter.java =================================================================== --- jakarta-jmeter-2.3/src/core/org/apache/jmeter/JMeter.java (revision 1) +++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/JMeter.java (working copy) @@ -28,6 +28,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Enumeration; +import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -55,6 +56,7 @@ import org.apache.jmeter.gui.action.ActionRouter; import org.apache.jmeter.gui.action.Load; import org.apache.jmeter.gui.tree.JMeterTreeListener; +import org.apache.jmeter.gui.tree.JMeterTreeNode; import org.apache.jmeter.gui.tree.JMeterTreeModel; import org.apache.jmeter.plugin.JMeterPlugin; import org.apache.jmeter.plugin.PluginManager; @@ -76,6 +78,7 @@ import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.gui.ComponentUtil; import org.apache.jorphan.logging.LoggingManager; +import org.apache.jorphan.collections.SearchByClass; import org.apache.jorphan.reflect.ClassTools; import org.apache.jorphan.util.JMeterException; import org.apache.jorphan.util.JOrphanUtils; @@ -656,6 +659,19 @@ HashTree tree = SaveService.loadTree(reader); + JMeterTreeModel treeModel = new JMeterTreeModel(); + JMeterTreeNode root = (JMeterTreeNode) treeModel.getRoot(); + treeModel.addSubTree(tree, root); + + // Hack to resolve ModuleControllers in non GUI mode + SearchByClass replaceableControllers = new SearchByClass(ReplaceableController.class); + tree.traverse(replaceableControllers); + Collection replaceableControllersRes = replaceableControllers.getSearchResults(); + for (Iterator iter = replaceableControllersRes.iterator(); iter.hasNext();) { + ReplaceableController replaceableController = (ReplaceableController) iter.next(); + replaceableController.resolveReplacementSubTree(root); + } + // Remove the disabled items // For GUI runs this is done in Start.java convertSubTree(tree); @@ -705,46 +721,70 @@ } } - /** - * Code copied from AbstractAction.java and modified to suit TestElements - * - * @param tree - */ - private void convertSubTree(HashTree tree) { - Iterator iter = new LinkedList(tree.list()).iterator(); - while (iter.hasNext()) { - TestElement item = (TestElement) iter.next(); - if (item.isEnabled()) { - // This is done for GUI runs in JMeterTreeModel.addSubTree() - if (item instanceof TestPlan) { - TestPlan tp = (TestPlan) item; - tp.setFunctionalMode(tp.isFunctionalMode()); - tp.setSerialized(tp.isSerialized()); - } - // TODO: this is a bit of a hack, but seems to work for the Include Controller - if (item instanceof ReplaceableController) { - // HACK: force the controller to load its tree - ReplaceableController rc = (ReplaceableController) item.clone(); - HashTree subTree = tree.getTree(item); - if (subTree != null) { - HashTree replacementTree = rc.getReplacementSubTree(); - if (replacementTree != null) { - convertSubTree(replacementTree); - tree.replace(item,rc); - tree.set(rc,replacementTree); - } - } else { - convertSubTree(tree.getTree(item)); - } - } else { - convertSubTree(tree.getTree(item)); - } // ReplaceableController - } else {// disabled - tree.remove(item); - } - } - } + /** + * Refactored from AbstractAction.java + * + * @param tree + */ + public static void convertSubTree(HashTree tree) { + Iterator iter = new LinkedList(tree.list()).iterator(); + while (iter.hasNext()) { + Object o = iter.next(); + if (o instanceof TestElement) { + TestElement item = (TestElement) o; + if (item.isEnabled()) { + if (item instanceof ReplaceableController) { + // HACK: force the controller to load its tree + ReplaceableController rc = (ReplaceableController) item + .clone(); + HashTree subTree = tree.getTree(item); + if (subTree != null) { + HashTree replacementTree = rc + .getReplacementSubTree(); + if (replacementTree != null) { + convertSubTree(replacementTree); + tree.replace(item, rc); + tree.set(rc, replacementTree); + } + } else { + convertSubTree(tree.getTree(item)); + } + } else { + convertSubTree(tree.getTree(item)); + } + } else + tree.remove(item); + } else { + JMeterTreeNode item = (JMeterTreeNode) o; + if (item.isEnabled()) { + // Replacement only needs to occur when starting the engine + // @see StandardJMeterEngine.run() + if (item.getUserObject() instanceof ReplaceableController) { + ReplaceableController rc = (ReplaceableController) item + .getTestElement(); + HashTree subTree = tree.getTree(item); + if (subTree != null) { + HashTree replacementTree = rc + .getReplacementSubTree(); + if (replacementTree != null) { + convertSubTree(replacementTree); + tree.replace(item, rc); + tree.set(rc, replacementTree); + } + } + } else { + convertSubTree(tree.getTree(item)); + TestElement testElement = item.getTestElement(); + tree.replace(item, testElement); + } + } else { + tree.remove(item); + } + } + } + } + private JMeterEngine doRemoteInit(String hostName, HashTree testTree) { JMeterEngine engine = null; try { Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/control/ReplaceableController.java =================================================================== --- jakarta-jmeter-2.3/src/core/org/apache/jmeter/control/ReplaceableController.java (revision 1) +++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/control/ReplaceableController.java (working copy) @@ -42,4 +42,11 @@ * @see org.apache.jmeter.gui.action.AbstractAction#convertSubTree */ public HashTree getReplacementSubTree(); + + /** + * Compute the replacement tree. + * + * @param context + */ + public void resolveReplacementSubTree(Object context); } Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/AbstractAction.java =================================================================== --- jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/AbstractAction.java (revision 1) +++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/AbstractAction.java (working copy) @@ -49,35 +49,7 @@ abstract public Set getActionNames(); protected void convertSubTree(HashTree tree) { - Iterator iter = new LinkedList(tree.list()).iterator(); - while (iter.hasNext()) { - Object o = iter.next(); - if(o instanceof TestElement) - continue; //hey, no need to convert - JMeterTreeNode item = (JMeterTreeNode) o; - if (item.isEnabled()) { - if (item.getUserObject() instanceof ReplaceableController) { - ReplaceableController rc = (ReplaceableController) item.getTestElement(); - HashTree subTree = tree.getTree(item); - - if (subTree != null) { - HashTree replacementTree = rc.getReplacementSubTree(); - if (replacementTree != null) { - convertSubTree(replacementTree); - tree.replace(item,rc); - tree.set(rc,replacementTree); - } - } - } else { - convertSubTree(tree.getTree(item)); - TestElement testElement = item.getTestElement(); - tree.replace(item, testElement); - } - } else { - tree.remove(item); - } - - } + org.apache.jmeter.JMeter.convertSubTree(tree); } /** Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/RemoteStart.java =================================================================== --- jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/RemoteStart.java (revision 1) +++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/RemoteStart.java (working copy) @@ -184,7 +184,7 @@ private void initEngine(JMeterEngine engine, String host) { GuiPackage gui = GuiPackage.getInstance(); HashTree testTree = gui.getTreeModel().getTestPlan(); - convertSubTree(testTree); + org.apache.jmeter.JMeter.convertSubTree(testTree); testTree.add(testTree.getArray()[0], gui.getMainFrame()); engine.configure(testTree); } Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/Start.java =================================================================== --- jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/Start.java (revision 1) +++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/action/Start.java (working copy) @@ -89,7 +89,7 @@ GuiPackage gui = GuiPackage.getInstance(); engine = new StandardJMeterEngine(); HashTree testTree = gui.getTreeModel().getTestPlan(); - convertSubTree(testTree); + org.apache.jmeter.JMeter.convertSubTree(testTree); DisabledComponentRemover remover = new DisabledComponentRemover(testTree); testTree.traverse(remover); testTree.add(testTree.getArray()[0], gui.getMainFrame()); Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java =================================================================== --- jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java (revision 1) +++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java (working copy) @@ -105,12 +105,17 @@ } component.setProperty(TestElement.GUI_CLASS, NameUpdater.getCurrentName(component .getPropertyAsString(TestElement.GUI_CLASS))); - GuiPackage.getInstance().updateCurrentNode(); - JMeterGUIComponent guicomp = GuiPackage.getInstance().getGui(component); - guicomp.configure(component); - guicomp.modifyTestElement(component); - GuiPackage.getInstance().getCurrentGui(); // put the gui object back - // to the way it was. + + GuiPackage guiPackage = GuiPackage.getInstance(); + if (guiPackage != null) { + // The node can be added in non GUI mode at startup + guiPackage.updateCurrentNode(); + JMeterGUIComponent guicomp = guiPackage.getGui(component); + guicomp.configure(component); + guicomp.modifyTestElement(component); + guiPackage.getCurrentGui(); // put the gui object back + // to the way it was. + } JMeterTreeNode newNode = new JMeterTreeNode(component, this); // This check the state of the TestElement and if returns false it Index: jakarta-jmeter-2.3/src/components/org/apache/jmeter/control/IncludeController.java =================================================================== --- jakarta-jmeter-2.3/src/components/org/apache/jmeter/control/IncludeController.java (revision 1) +++ jakarta-jmeter-2.3/src/components/org/apache/jmeter/control/IncludeController.java (working copy) @@ -63,7 +63,7 @@ public Object clone() { // TODO - fix so that this is only called once per test, instead of at every clone // Perhaps save previous filename, and only load if it has changed? - this.SUBTREE = this.loadIncludedElements(); + this.resolveReplacementSubTree(null); IncludeController clone = (IncludeController) super.clone(); clone.setIncludePath(this.getIncludePath()); if (this.SUBTREE != null) { @@ -104,6 +104,14 @@ return SUBTREE; } + /** + * @XXX: Add documentation + * @param context + */ + public void resolveReplacementSubTree(Object context) { + this.SUBTREE = this.loadIncludedElements(); + } + /** * load the included elements using SaveService * @param node Index: jakarta-jmeter-2.3/src/components/org/apache/jmeter/control/ModuleController.java =================================================================== --- jakarta-jmeter-2.3/src/components/org/apache/jmeter/control/ModuleController.java (revision 1) +++ jakarta-jmeter-2.3/src/components/org/apache/jmeter/control/ModuleController.java (working copy) @@ -116,19 +116,28 @@ return null; } - private void restoreSelected() { - if (selectedNode == null) { - List nodePath = getNodePath(); - if (nodePath != null && nodePath.size() > 0) { - GuiPackage gp = GuiPackage.getInstance(); - if (gp != null) { - JMeterTreeNode root = (JMeterTreeNode) gp.getTreeModel().getRoot(); - traverse(root, nodePath, 1); - } - } - } - } + private void restoreSelected() { + GuiPackage gp = GuiPackage.getInstance(); + if (gp != null) { + JMeterTreeNode root = (JMeterTreeNode) gp.getTreeModel().getRoot(); + resolveReplacementSubTree(root); + } + } + /** + * Compute the replacement tree. + * @param context + */ + public void resolveReplacementSubTree(Object context) { + JMeterTreeNode root = (JMeterTreeNode) context; + if (selectedNode == null) { + List nodePathList = getNodePath(); + if (nodePathList != null && nodePathList.size() > 0) { + traverse(root, nodePathList, 1); + } + } + } + private void traverse(JMeterTreeNode node, List nodePath, int level) { if (node != null && nodePath.size() > level) { for (int i = 0; i < node.getChildCount(); i++) {