1 18 19 package org.apache.jmeter.functions; 20 21 import java.io.Serializable ; 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Iterator ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 import java.util.Random ; 28 29 import org.apache.jmeter.engine.util.CompoundVariable; 30 import org.apache.jmeter.junit.JMeterTestCase; 31 import org.apache.jmeter.samplers.SampleResult; 32 import org.apache.jmeter.samplers.Sampler; 33 import org.apache.jmeter.threads.JMeterContext; 34 import org.apache.jmeter.threads.JMeterContextService; 35 import org.apache.jmeter.threads.JMeterVariables; 36 import org.apache.jmeter.util.JMeterUtils; 37 import org.apache.jorphan.logging.LoggingManager; 38 import org.apache.log.Logger; 39 import org.apache.oro.text.PatternCacheLRU; 40 import org.apache.oro.text.regex.MatchResult; 41 import org.apache.oro.text.regex.Pattern; 42 import org.apache.oro.text.regex.PatternMatcher; 43 import org.apache.oro.text.regex.PatternMatcherInput; 44 import org.apache.oro.text.regex.Perl5Compiler; 45 import org.apache.oro.text.regex.Perl5Matcher; 46 import org.apache.oro.text.regex.Util; 47 48 public class RegexFunction extends AbstractFunction implements Serializable 49 { 50 transient private static Logger log = LoggingManager.getLoggerForClass(); 51 public static final String ALL = "ALL"; 52 public static final String RAND = "RAND"; 53 public static final String KEY = "__regexFunction"; 54 55 private Object [] values; 57 private static Random rand = new Random(); 58 private static final List desc = new LinkedList (); 59 60 private static PatternCacheLRU patternCache = 61 new PatternCacheLRU(1000, new Perl5Compiler()); 62 private Pattern templatePattern; 64 private static ThreadLocal localMatcher = new ThreadLocal () 65 { 66 protected Object initialValue() 67 { 68 return new Perl5Matcher(); 69 } 70 }; 71 72 private static final int MIN_PARAMETER_COUNT = 2; 74 private static final int MAX_PARAMETER_COUNT = 6; 75 static { 76 desc.add(JMeterUtils.getResString("regexfunc_param_1")); desc.add(JMeterUtils.getResString("regexfunc_param_2")); desc.add(JMeterUtils.getResString("regexfunc_param_3")); desc.add(JMeterUtils.getResString("regexfunc_param_4")); desc.add(JMeterUtils.getResString("regexfunc_param_5")); desc.add(JMeterUtils.getResString("function_name_param")); 82 } 83 84 public RegexFunction() 85 { 86 templatePattern = patternCache.getPattern("\\$(\\d+)\\$", Perl5Compiler.READ_ONLY_MASK); 87 } 88 89 public synchronized String execute(SampleResult previousResult, Sampler currentSampler) 90 throws InvalidVariableException 91 { 92 String valueIndex="", defaultValue="", between=""; 93 String name=""; 94 Pattern searchPattern; 95 Object [] tmplt; 96 try 97 { 98 searchPattern = 99 patternCache.getPattern(((CompoundVariable) values[0]).execute(), Perl5Compiler.READ_ONLY_MASK); 100 tmplt = generateTemplate(((CompoundVariable) values[1]).execute()); 101 102 if (values.length > 2) 103 { 104 valueIndex = ((CompoundVariable) values[2]).execute(); 105 } 106 if (valueIndex.equals("")) 107 { 108 valueIndex = "1"; 109 } 110 111 if (values.length > 3) 112 { 113 between = ((CompoundVariable) values[3]).execute(); 114 } 115 116 if (values.length > 4) 117 { 118 String dv = ((CompoundVariable) values[4]).execute(); 119 if (!dv.equals("")) 120 { 121 defaultValue = dv; 122 } 123 } 124 125 if (values.length > 5) 126 { 127 name = ((CompoundVariable) values[values.length - 1]).execute(); 128 } 129 } 130 catch (Exception e) 131 { 132 throw new InvalidVariableException(e.toString()); 133 } 134 135 JMeterVariables vars = getVariables(); vars.put(name, defaultValue); 137 if (previousResult == null || previousResult.getResponseData() == null) 138 { 139 return defaultValue; 140 } 141 142 List collectAllMatches = new ArrayList (); 143 try 144 { 145 PatternMatcher matcher = (PatternMatcher) localMatcher.get(); 146 String responseText = new String (previousResult.getResponseData()); 147 PatternMatcherInput input = new PatternMatcherInput(responseText); 148 while (matcher.contains(input, searchPattern)) 149 { 150 MatchResult match = matcher.getMatch(); 151 collectAllMatches.add(match); 152 } 153 } 154 catch (NumberFormatException e) 155 { 156 log.error("", e); 157 return defaultValue; 158 } 159 catch (Exception e) 160 { 161 return defaultValue; 162 } 163 finally 164 { 165 vars.put(name+"_matchNr", ""+collectAllMatches.size()); 166 } 167 168 if (collectAllMatches.size() == 0) 169 { 170 return defaultValue; 171 } 172 173 if (valueIndex.equals(ALL)) 174 { 175 StringBuffer value = new StringBuffer (); 176 Iterator it = collectAllMatches.iterator(); 177 boolean first = true; 178 while (it.hasNext()) 179 { 180 if (!first) 181 { 182 value.append(between); 183 } 184 else 185 { 186 first = false; 187 } 188 value.append(generateResult((MatchResult) it.next(),name, tmplt, vars)); 189 } 190 return value.toString(); 191 } 192 else if (valueIndex.equals(RAND)) 193 { 194 MatchResult result = 195 (MatchResult) collectAllMatches.get( 196 rand.nextInt(collectAllMatches.size())); 197 return generateResult(result,name, tmplt, vars); 198 } 199 else 200 { 201 try 202 { 203 int index = Integer.parseInt(valueIndex) - 1; 204 MatchResult result = (MatchResult) collectAllMatches.get(index); 205 return generateResult(result,name, tmplt, vars); 206 } 207 catch (NumberFormatException e) 208 { 209 float ratio = Float.parseFloat(valueIndex); 210 MatchResult result = 211 (MatchResult) collectAllMatches.get( 212 (int) (collectAllMatches.size() * ratio + .5) - 1); 213 return generateResult(result,name, tmplt, vars); 214 } 215 catch (IndexOutOfBoundsException e) 216 { 217 return defaultValue; 218 } 219 } 220 221 } 222 223 private void saveGroups(MatchResult result, String namep, JMeterVariables vars) 224 { 225 if (result != null) 226 { 227 for (int x = 0; x < result.groups(); x++) 228 { 229 vars.put(namep + "_g" + x, result.group(x)); 230 } 231 } 232 } 233 234 public List getArgumentDesc() 235 { 236 return desc; 237 } 238 239 private String generateResult(MatchResult match, String namep, Object [] template 240 ,JMeterVariables vars) 241 { 242 saveGroups(match, namep, vars); 243 StringBuffer result = new StringBuffer (); 244 for (int a = 0; a < template.length; a++) 245 { 246 if (template[a] instanceof String ) 247 { 248 result.append(template[a]); 249 } 250 else 251 { 252 result.append(match.group(((Integer ) template[a]).intValue())); 253 } 254 } 255 vars.put(namep, result.toString()); 256 return result.toString(); 257 } 258 259 public String getReferenceKey() 260 { 261 return KEY; 262 } 263 264 public synchronized void setParameters(Collection parameters) 265 throws InvalidVariableException 266 { 267 values = parameters.toArray(); 268 269 if ((values.length < MIN_PARAMETER_COUNT) 270 || (values.length > MAX_PARAMETER_COUNT)) 271 { 272 throw new InvalidVariableException( 273 "Parameter Count " + values.length 275 + " not between " + MIN_PARAMETER_COUNT 277 + " & " + MAX_PARAMETER_COUNT); 279 } 280 } 281 282 private Object [] generateTemplate(String rawTemplate) 283 { 284 List pieces = new ArrayList (); 285 List combined = new LinkedList (); 286 PatternMatcher matcher = new Perl5Matcher(); 287 Util.split(pieces, new Perl5Matcher(), templatePattern, rawTemplate); 288 PatternMatcherInput input = new PatternMatcherInput(rawTemplate); 289 Iterator iter = pieces.iterator(); 290 boolean startsWith = isFirstElementGroup(rawTemplate); 291 while (iter.hasNext()) 292 { 293 boolean matchExists = matcher.contains(input, templatePattern); 294 if (startsWith) 295 { 296 if (matchExists) 297 { 298 combined.add(new Integer (matcher.getMatch().group(1))); 299 } 300 combined.add(iter.next()); 301 } 302 else 303 { 304 combined.add(iter.next()); 305 if (matchExists) 306 { 307 combined.add(new Integer (matcher.getMatch().group(1))); 308 } 309 } 310 } 311 if (matcher.contains(input, templatePattern)) 312 { 313 combined.add(new Integer (matcher.getMatch().group(1))); 314 } 315 return combined.toArray(); 316 } 317 318 private boolean isFirstElementGroup(String rawData) 319 { 320 Pattern pattern = patternCache.getPattern("^\\$\\d+\\$", Perl5Compiler.READ_ONLY_MASK); 321 return new Perl5Matcher().contains(rawData, pattern); 322 } 323 324 325 public static class Test extends JMeterTestCase 326 { 327 RegexFunction variable; 328 SampleResult result; 329 Collection params; 330 private JMeterVariables vars; 331 private JMeterContext jmctx = null; 332 333 public Test(String name) 334 { 335 super(name); 336 } 337 338 public void setUp() 339 { 340 variable = new RegexFunction(); 341 result = new SampleResult(); 342 jmctx = JMeterContextService.getContext(); 343 String data = 344 "<company-xmlext-query-ret><row>" 345 + "<value field=\"RetCode\">" 346 + "LIS_OK</value><value" 347 + " field=\"RetCodeExtension\"></value>" 348 + "<value field=\"alias\"></value><value" 349 + " field=\"positioncount\"></value>" 350 + "<value field=\"invalidpincount\">0</value><value" 351 + " field=\"pinposition1\">1</value><value" 352 + " field=\"pinpositionvalue1\"></value><value" 353 + " field=\"pinposition2\">5</value><value" 354 + " field=\"pinpositionvalue2\"></value><value" 355 + " field=\"pinposition3\">6</value><value" 356 + " field=\"pinpositionvalue3\"></value>" 357 + "</row></company-xmlext-query-ret>"; 358 result.setResponseData(data.getBytes()); 359 vars = new JMeterVariables(); 360 jmctx.setVariables(vars); 361 jmctx.setPreviousResult(result); 362 } 363 364 public void testVariableExtraction() throws Exception 365 { 366 params = new LinkedList (); 367 params.add(new CompoundVariable("<value field=\"(pinposition\\d+)\">(\\d+)</value>")); 368 params.add(new CompoundVariable("$2$")); 369 params.add(new CompoundVariable("2")); 370 variable.setParameters(params); 371 String match = variable.execute(result, null); 372 assertEquals("5", match); 373 } 374 375 public void testVariableExtraction2() throws Exception 376 { 377 params = new LinkedList (); 378 params.add(new CompoundVariable( 379 "<value field=\"(pinposition\\d+)\">(\\d+)</value>")); 380 params.add(new CompoundVariable("$1$")); 381 params.add(new CompoundVariable("3")); 382 variable.setParameters(params); 383 String match = variable.execute(result, null); 384 assertEquals("pinposition3", match); 385 } 386 387 public void testVariableExtraction5() throws Exception 388 { 389 params = new LinkedList (); 390 params.add(new CompoundVariable( 391 "<value field=\"(pinposition\\d+)\">(\\d+)</value>")); 392 params.add(new CompoundVariable("$1$")); 393 params.add(new CompoundVariable("ALL")); 394 params.add(new CompoundVariable("_")); 395 variable.setParameters(params); 396 String match = variable.execute(result, null); 397 assertEquals("pinposition1_pinposition2_pinposition3", match); 398 } 399 400 public void testVariableExtraction6() throws Exception 401 { 402 params = new LinkedList (); 403 params.add(new CompoundVariable( 404 "<value field=\"(pinposition\\d+)\">(\\d+)</value>")); 405 params.add(new CompoundVariable("$2$")); 406 params.add(new CompoundVariable("4")); 407 params.add(new CompoundVariable("")); 408 params.add(new CompoundVariable("default")); 409 variable.setParameters(params); 410 String match = variable.execute(result, null); 411 assertEquals("default", match); 412 } 413 414 public void testComma() throws Exception 415 { 416 params = new LinkedList (); 417 params.add(new CompoundVariable( 418 "<value,? field=\"(pinposition\\d+)\">(\\d+)</value>")); 419 params.add(new CompoundVariable("$1$")); 420 params.add(new CompoundVariable("3")); 421 variable.setParameters(params); 422 String match = variable.execute(result, null); 423 assertEquals("pinposition3", match); 424 } 425 426 public void testVariableExtraction3() throws Exception 427 { 428 params = new LinkedList (); 429 params.add(new CompoundVariable( 430 "<value field=\"(pinposition\\d+)\">(\\d+)</value>")); 431 params.add(new CompoundVariable("_$1$")); 432 params.add(new CompoundVariable("2")); 433 variable.setParameters(params); 434 String match = variable.execute(result, null); 435 assertEquals("_pinposition2", match); 436 } 437 438 public void testVariableExtraction4() throws Exception 439 { 440 params = new LinkedList (); 441 params.add(new CompoundVariable( 442 "<value field=\"(pinposition\\d+)\">(\\d+)</value>")); 443 params.add(new CompoundVariable("$2$, ")); 444 params.add(new CompoundVariable(".333")); 445 variable.setParameters(params); 446 String match = variable.execute(result, null); 447 assertEquals("1, ", match); 448 } 449 450 public void testDefaultValue() throws Exception 451 { 452 params = new LinkedList (); 453 params.add(new CompoundVariable( 454 "<value,, field=\"(pinposition\\d+)\">(\\d+)</value>")); 455 params.add(new CompoundVariable("$2$, ")); 456 params.add(new CompoundVariable(".333")); 457 params.add(new CompoundVariable("")); 458 params.add(new CompoundVariable("No Value Found")); 459 variable.setParameters(params); 460 String match = variable.execute(result, null); 461 assertEquals("No Value Found", match); 462 } 463 } 464 } 465 | Popular Tags |