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.io.FileInputStream;
022: import java.io.FileNotFoundException;
023: import java.io.InputStream;
024: import java.util.Iterator;
025: import java.util.LinkedList;
026:
027: import org.apache.jmeter.save.SaveService;
028: import org.apache.jmeter.testelement.TestElement;
029: import org.apache.jmeter.util.JMeterUtils;
030: import org.apache.jorphan.collections.HashTree;
031: import org.apache.jorphan.logging.LoggingManager;
032: import org.apache.jorphan.util.JOrphanUtils;
033: import org.apache.log.Logger;
034:
035: public class IncludeController extends GenericController implements
036: ReplaceableController {
037: private static final Logger log = LoggingManager
038: .getLoggerForClass();
039:
040: private static final String INCLUDE_PATH = "IncludeController.includepath"; //$NON-NLS-1$
041:
042: private static final String prefix = JMeterUtils.getPropDefault(
043: "includecontroller.prefix", //$NON-NLS-1$
044: ""); //$NON-NLS-1$
045:
046: private HashTree SUBTREE = null;
047: private TestElement SUB = null;
048:
049: /**
050: * No-arg constructor
051: *
052: * @see java.lang.Object#Object()
053: */
054: public IncludeController() {
055: super ();
056: }
057:
058: public Object clone() {
059: // TODO - fix so that this is only called once per test, instead of at every clone
060: // Perhaps save previous filename, and only load if it has changed?
061: this .resolveReplacementSubTree(null);
062: IncludeController clone = (IncludeController) super .clone();
063: clone.setIncludePath(this .getIncludePath());
064: if (this .SUBTREE != null) {
065: if (this .SUBTREE.keySet().size() == 1) {
066: Iterator itr = this .SUBTREE.keySet().iterator();
067: while (itr.hasNext()) {
068: this .SUB = (TestElement) itr.next();
069: }
070: }
071: clone.SUBTREE = (HashTree) this .SUBTREE.clone();
072: clone.SUB = (TestElement) this .SUB.clone();
073: }
074: return clone;
075: }
076:
077: /**
078: * In the event an user wants to include an external JMX test plan
079: * the GUI would call this.
080: * @param jmxfile
081: */
082: public void setIncludePath(String jmxfile) {
083: this .setProperty(INCLUDE_PATH, jmxfile);
084: }
085:
086: /**
087: * return the JMX file path.
088: * @return the JMX file path
089: */
090: public String getIncludePath() {
091: return this .getPropertyAsString(INCLUDE_PATH);
092: }
093:
094: /**
095: * The way ReplaceableController works is clone is called first,
096: * followed by replace(HashTree) and finally getReplacement().
097: */
098: public HashTree getReplacementSubTree() {
099: return SUBTREE;
100: }
101:
102: public void resolveReplacementSubTree(Object context) {
103: this .SUBTREE = this .loadIncludedElements();
104: }
105:
106: /**
107: * load the included elements using SaveService
108: */
109: protected HashTree loadIncludedElements() {
110: // only try to load the JMX test plan if there is one
111: final String includePath = getIncludePath();
112: InputStream reader = null;
113: HashTree tree = null;
114: if (includePath != null && includePath.length() > 0) {
115: try {
116: String file = prefix + includePath;
117: log
118: .info("loadIncludedElements -- try to load included module: "
119: + file);
120: reader = new FileInputStream(file);
121: tree = SaveService.loadTree(reader);
122: removeDisabledItems(tree);
123: return tree;
124: } catch (NoClassDefFoundError ex) // Allow for missing optional jars
125: {
126: String msg = ex.getMessage();
127: if (msg == null) {
128: msg = "Missing jar file - see log for details";
129: }
130: log.warn("Missing jar file", ex);
131: JMeterUtils.reportErrorToUser(msg);
132: } catch (FileNotFoundException ex) {
133: String msg = ex.getMessage();
134: JMeterUtils.reportErrorToUser(msg);
135: log.warn(msg);
136: } catch (Exception ex) {
137: String msg = ex.getMessage();
138: if (msg == null) {
139: msg = "Unexpected error - see log for details";
140: }
141: JMeterUtils.reportErrorToUser(msg);
142: log.warn("Unexpected error", ex);
143: } finally {
144: JOrphanUtils.closeQuietly(reader);
145: }
146: }
147: return tree;
148: }
149:
150: private void removeDisabledItems(HashTree tree) {
151: Iterator iter = new LinkedList(tree.list()).iterator();
152: while (iter.hasNext()) {
153: TestElement item = (TestElement) iter.next();
154: if (!item.isEnabled()) {
155: //log.info("Removing "+item.toString());
156: tree.remove(item);
157: } else {
158: //log.info("Keeping "+item.toString());
159: removeDisabledItems(tree.getTree(item));// Recursive call
160: }
161: }
162: }
163:
164: }
|