1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package org.apache.jmeter.engine.util; 20 21 import java.util.Collection; 22 import java.util.HashMap; 23 import java.util.Iterator; 24 import java.util.LinkedList; 25 import java.util.List; 26 import java.util.Map; 27 28 import org.apache.jmeter.functions.Function; 29 import org.apache.jmeter.functions.InvalidVariableException; 30 import org.apache.jmeter.samplers.SampleResult; 31 import org.apache.jmeter.samplers.Sampler; 32 import org.apache.jmeter.threads.JMeterContext; 33 import org.apache.jmeter.threads.JMeterContextService; 34 import org.apache.jmeter.util.JMeterUtils; 35 import org.apache.jorphan.logging.LoggingManager; 36 import org.apache.jorphan.reflect.ClassFinder; 37 import org.apache.log.Logger; 38 39 /** 40 * CompoundFunction. 41 * 42 */ 43 public class CompoundVariable implements Function { 44 private static final Logger log = LoggingManager.getLoggerForClass(); 45 46 private String rawParameters; 47 48 private static final FunctionParser functionParser = new FunctionParser(); 49 50 private static final Map functions = new HashMap(); 51 52 private boolean hasFunction, isDynamic; 53 54 private String permanentResults = ""; // $NON-NLS-1$ 55 56 private LinkedList compiledComponents = new LinkedList(); 57 58 static { 59 try { 60 final String contain = // Classnames must contain this string [.functions.] 61 JMeterUtils.getProperty("classfinder.functions.contain"); // $NON-NLS-1$ 62 final String notContain = // Classnames must not contain this string [.gui.] 63 JMeterUtils.getProperty("classfinder.functions.notContain"); // $NON-NLS-1$ 64 if (contain!=null){ 65 log.info("Note: Function class names must contain the string: '"+contain+"'"); 66 } 67 if (notContain!=null){ 68 log.info("Note: Function class names must not contain the string: '"+notContain+"'"); 69 } 70 List classes = ClassFinder.findClassesThatExtend(JMeterUtils.getSearchPaths(), 71 new Class[] { Function.class }, true, contain, notContain); 72 Iterator iter = classes.iterator(); 73 while (iter.hasNext()) { 74 Function tempFunc = (Function) Class.forName((String) iter.next()).newInstance(); 75 String referenceKey = tempFunc.getReferenceKey(); 76 functions.put(referenceKey, tempFunc.getClass()); 77 // Add alias for original StringFromFile name (had only one underscore) 78 if (referenceKey.equals("__StringFromFile")){//$NON-NLS-1$ 79 functions.put("_StringFromFile", tempFunc.getClass());//$NON-NLS-1$ 80 } 81 } 82 final int functionCount = functions.size(); 83 if (functionCount == 0){ 84 log.warn("Did not find any functions"); 85 } else { 86 log.debug("Function count: "+functionCount); 87 } 88 } catch (Exception err) { 89 log.error("", err); 90 } 91 } 92 93 public CompoundVariable() { 94 super(); 95 isDynamic = true; 96 hasFunction = false; 97 } 98 99 public CompoundVariable(String parameters) { 100 this(); 101 try { 102 setParameters(parameters); 103 } catch (InvalidVariableException e) { 104 } 105 } 106 107 public String execute() { 108 if (isDynamic) { 109 JMeterContext context = JMeterContextService.getContext(); 110 SampleResult previousResult = context.getPreviousResult(); 111 Sampler currentSampler = context.getCurrentSampler(); 112 return execute(previousResult, currentSampler); 113 } 114 return permanentResults; // $NON-NLS-1$ 115 } 116 117 /** 118 * Allows the retrieval of the original String prior to it being compiled. 119 * 120 * @return String 121 */ 122 public String getRawParameters() { 123 return rawParameters; 124 } 125 126 /* 127 * (non-Javadoc) 128 * 129 * @see Function#execute(SampleResult, Sampler) 130 */ 131 public String execute(SampleResult previousResult, Sampler currentSampler) { 132 if (compiledComponents == null || compiledComponents.size() == 0) { 133 return ""; // $NON-NLS-1$ 134 } 135 boolean testDynamic = false; 136 StringBuffer results = new StringBuffer(); 137 Iterator iter = compiledComponents.iterator(); 138 while (iter.hasNext()) { 139 Object item = iter.next(); 140 if (item instanceof Function) { 141 testDynamic = true; 142 try { 143 results.append(((Function) item).execute(previousResult, currentSampler)); 144 } catch (InvalidVariableException e) { 145 } 146 } else if (item instanceof SimpleVariable) { 147 testDynamic = true; 148 results.append(((SimpleVariable) item).toString()); 149 } else { 150 results.append(item); 151 } 152 } 153 if (!testDynamic) { 154 isDynamic = false; 155 permanentResults = results.toString(); 156 } 157 return results.toString(); 158 } 159 160 public CompoundVariable getFunction() { 161 CompoundVariable func = new CompoundVariable(); 162 func.compiledComponents = (LinkedList) compiledComponents.clone(); 163 func.rawParameters = rawParameters; 164 return func; 165 } 166 167 public List getArgumentDesc() { 168 return new LinkedList(); 169 } 170 171 public void clear() { 172 // TODO should this also clear isDynamic, rawParameters, permanentResults? 173 hasFunction = false; 174 compiledComponents.clear(); 175 } 176 177 public void setParameters(String parameters) throws InvalidVariableException { 178 this.rawParameters = parameters; 179 if (parameters == null || parameters.length() == 0) { 180 return; 181 } 182 183 compiledComponents = functionParser.compileString(parameters); 184 if (compiledComponents.size() > 1 || !(compiledComponents.get(0) instanceof String)) { 185 hasFunction = true; 186 } 187 } 188 189 static Object getNamedFunction(String functionName) throws InvalidVariableException { 190 if (functions.containsKey(functionName)) { 191 try { 192 return ((Class) functions.get(functionName)).newInstance(); 193 } catch (Exception e) { 194 log.error("", e); // $NON-NLS-1$ 195 throw new InvalidVariableException(); 196 } 197 } 198 return new SimpleVariable(functionName); 199 } 200 201 public boolean hasFunction() { 202 return hasFunction; 203 } 204 205 // Dummy methods needed by Function interface 206 207 /** 208 * @see Function#getReferenceKey() 209 */ 210 public String getReferenceKey() { 211 return ""; // $NON-NLS-1$ 212 } 213 214 public void setParameters(Collection parameters) throws InvalidVariableException { 215 } 216 }