1 17 package org.apache.jmeter.protocol.http.sampler; 18 19 import java.io.ByteArrayOutputStream ; 20 import java.io.PrintStream ; 21 import java.net.MalformedURLException ; 22 import java.net.URL ; 23 import java.util.Iterator ; 24 25 import org.apache.jmeter.config.Argument; 26 import org.apache.jmeter.config.Arguments; 27 import org.apache.jmeter.engine.event.LoopIterationEvent; 28 import org.apache.jmeter.protocol.http.control.AuthManager; 29 import org.apache.jmeter.protocol.http.control.CookieManager; 30 import org.apache.jmeter.protocol.http.control.HeaderManager; 31 import org.apache.jmeter.protocol.http.parser.HTMLParseException; 32 import org.apache.jmeter.protocol.http.parser.HTMLParser; 33 import org.apache.jmeter.protocol.http.util.HTTPArgument; 34 import org.apache.jmeter.samplers.AbstractSampler; 35 import org.apache.jmeter.samplers.Entry; 36 import org.apache.jmeter.samplers.SampleResult; 37 import org.apache.jmeter.testelement.TestElement; 38 import org.apache.jmeter.testelement.TestListener; 39 import org.apache.jmeter.testelement.property.BooleanProperty; 40 import org.apache.jmeter.testelement.property.IntegerProperty; 41 import org.apache.jmeter.testelement.property.JMeterProperty; 42 import org.apache.jmeter.testelement.property.PropertyIterator; 43 import org.apache.jmeter.testelement.property.StringProperty; 44 import org.apache.jmeter.testelement.property.TestElementProperty; 45 import org.apache.jorphan.logging.LoggingManager; 46 import org.apache.jorphan.util.JOrphanUtils; 47 import org.apache.log.Logger; 48 import org.apache.oro.text.regex.MalformedPatternException; 49 import org.apache.oro.text.regex.Pattern; 50 import org.apache.oro.text.regex.Perl5Compiler; 51 import org.apache.oro.text.regex.Perl5Matcher; 52 import org.apache.oro.text.regex.StringSubstitution; 53 import org.apache.oro.text.regex.Substitution; 54 import org.apache.oro.text.regex.Util; 55 56 61 public abstract class HTTPSamplerBase extends AbstractSampler implements TestListener 62 { 63 private static final Logger log = LoggingManager.getLoggerForClass(); 64 65 public static final int DEFAULT_HTTPS_PORT = 443; 66 public static final int DEFAULT_HTTP_PORT = 80; 67 68 public final static String ARGUMENTS= "HTTPsampler.Arguments"; 69 public final static String AUTH_MANAGER= "HTTPSampler.auth_manager"; 70 public final static String COOKIE_MANAGER= "HTTPSampler.cookie_manager"; 71 public final static String HEADER_MANAGER= "HTTPSampler.header_manager"; 72 public final static String MIMETYPE= "HTTPSampler.mimetype"; 73 public final static String DOMAIN= "HTTPSampler.domain"; 74 public final static String PORT= "HTTPSampler.port"; 75 public final static String METHOD= "HTTPSampler.method"; 76 77 public final static String PATH= "HTTPSampler.path"; 78 public final static String FOLLOW_REDIRECTS= "HTTPSampler.follow_redirects"; 79 public final static String AUTO_REDIRECTS = "HTTPSampler.auto_redirects"; 80 public final static String PROTOCOL= "HTTPSampler.protocol"; 81 public final static String DEFAULT_PROTOCOL= "http"; 82 public final static String URL= "HTTPSampler.URL"; 83 public final static String POST= "POST"; 84 public final static String GET= "GET"; 85 public final static String USE_KEEPALIVE= "HTTPSampler.use_keepalive"; 86 public final static String FILE_NAME= "HTTPSampler.FILE_NAME"; 87 public final static String FILE_FIELD= "HTTPSampler.FILE_FIELD"; 88 public final static String FILE_DATA= "HTTPSampler.FILE_DATA"; 89 public final static String FILE_MIMETYPE= "HTTPSampler.FILE_MIMETYPE"; 90 public final static String CONTENT_TYPE= "HTTPSampler.CONTENT_TYPE"; 91 public final static String NORMAL_FORM= "normal_form"; 92 public final static String MULTIPART_FORM= "multipart_form"; 93 public final static String IMAGE_PARSER= "HTTPSampler.image_parser"; 95 public final static String MONITOR = "HTTPSampler.monitor"; 96 97 98 public static final int UNSPECIFIED_PORT= 0; 99 boolean dynamicPath = false; 100 protected final static String NON_HTTP_RESPONSE_CODE= 101 "Non HTTP response code"; 102 protected final static String NON_HTTP_RESPONSE_MESSAGE= 103 "Non HTTP response message"; 104 105 private static Pattern pattern; 106 107 static { 108 try 109 { 110 pattern= new Perl5Compiler().compile( 111 " ", 112 Perl5Compiler.READ_ONLY_MASK 113 & Perl5Compiler.SINGLELINE_MASK); 114 } 115 catch (MalformedPatternException e) 116 { 117 log.error("Cant compile pattern.", e); 118 throw new Error (e.toString()); } 120 } 121 122 public HTTPSamplerBase() 123 { 124 } 125 126 public void setFileField(String value) 127 { 128 setProperty(FILE_FIELD, value); 129 } 130 public String getFileField() 131 { 132 return getPropertyAsString(FILE_FIELD); 133 } 134 public void setFilename(String value) 135 { 136 setProperty(FILE_NAME, value); 137 } 138 public String getFilename() 139 { 140 return getPropertyAsString(FILE_NAME); 141 } 142 public void setProtocol(String value) 143 { 144 setProperty(PROTOCOL, value.toLowerCase()); 145 } 146 public String getProtocol() 147 { 148 String protocol= getPropertyAsString(PROTOCOL); 149 if (protocol == null || protocol.equals("")) 150 { 151 return DEFAULT_PROTOCOL; 152 } 153 else 154 { 155 return protocol; 156 } 157 } 158 159 166 public void setPath(String path) 167 { 168 if (GET.equals(getMethod())) 169 { 170 int index= path.indexOf("?"); 171 if (index > -1) 172 { 173 setProperty(PATH, path.substring(0, index)); 174 parseArguments(path.substring(index + 1)); 175 } 176 else 177 { 178 setProperty(PATH, path); 179 } 180 } 181 else 182 { 183 setProperty(PATH, path); 184 } 185 } 186 187 public String getPath() 188 { 189 String p = getPropertyAsString(PATH); 190 if(dynamicPath) 191 { 192 return encodeSpaces(p); 193 } 194 return p; 195 } 196 197 public void setFollowRedirects(boolean value) 198 { 199 setProperty(new BooleanProperty(FOLLOW_REDIRECTS, value)); 200 } 201 202 public boolean getFollowRedirects() 203 { 204 return getPropertyAsBoolean(FOLLOW_REDIRECTS); 205 } 206 207 public void setMethod(String value) 208 { 209 setProperty(METHOD, value); 210 } 211 212 public String getMethod() 213 { 214 return getPropertyAsString(METHOD); 215 } 216 217 public void setUseKeepAlive(boolean value) 218 { 219 setProperty(new BooleanProperty(USE_KEEPALIVE, value)); 220 } 221 222 public boolean getUseKeepAlive() 223 { 224 return getPropertyAsBoolean(USE_KEEPALIVE); 225 } 226 227 public void setMonitor(String value){ 228 this.setProperty(MONITOR,value); 229 } 230 231 public String getMonitor(){ 232 return this.getPropertyAsString(MONITOR); 233 } 234 235 public boolean isMonitor(){ 236 return this.getPropertyAsBoolean(MONITOR); 237 } 238 239 public void addEncodedArgument(String name, String value, String metaData) 240 { 241 log.debug( 242 "adding argument: name: " 243 + name 244 + " value: " 245 + value 246 + " metaData: " 247 + metaData); 248 249 HTTPArgument arg= new HTTPArgument(name, value, metaData, true); 250 251 if (arg.getName().equals(arg.getEncodedName()) 252 && arg.getValue().equals(arg.getEncodedValue())) 253 { 254 arg.setAlwaysEncoded(false); 255 } 256 this.getArguments().addArgument(arg); 257 } 258 259 public void addArgument(String name, String value) 260 { 261 this.getArguments().addArgument(new HTTPArgument(name, value)); 262 } 263 264 public void addArgument(String name, String value, String metadata) 265 { 266 this.getArguments().addArgument(new HTTPArgument(name, value, metadata)); 267 } 268 269 public void addTestElement(TestElement el) 270 { 271 if (el instanceof CookieManager) 272 { 273 setCookieManager((CookieManager)el); 274 } 275 else if (el instanceof HeaderManager) 276 { 277 setHeaderManager((HeaderManager)el); 278 } 279 else if (el instanceof AuthManager) 280 { 281 setAuthManager((AuthManager)el); 282 } 283 else 284 { 285 super.addTestElement(el); 286 } 287 } 288 289 public void setPort(int value) 290 { 291 setProperty(new IntegerProperty(PORT, value)); 292 } 293 294 public int getPort() 295 { 296 int port= getPropertyAsInt(PORT); 297 if (port == UNSPECIFIED_PORT) 298 { 299 if ("https".equalsIgnoreCase(getProtocol())) 300 { 301 return DEFAULT_HTTPS_PORT; 302 } 303 return DEFAULT_HTTP_PORT; 304 } 305 return port; 306 } 307 308 public void setDomain(String value) 309 { 310 setProperty(DOMAIN, value); 311 } 312 313 public String getDomain() 314 { 315 return getPropertyAsString(DOMAIN); 316 } 317 318 public void setArguments(Arguments value) 319 { 320 setProperty(new TestElementProperty(ARGUMENTS, value)); 321 } 322 323 public Arguments getArguments() 324 { 325 return (Arguments)getProperty(ARGUMENTS).getObjectValue(); 326 } 327 328 public void setAuthManager(AuthManager value) 329 { 330 setProperty(new TestElementProperty(AUTH_MANAGER, value)); 331 } 332 333 public AuthManager getAuthManager() 334 { 335 return (AuthManager)getProperty(AUTH_MANAGER).getObjectValue(); 336 } 337 338 public void setHeaderManager(HeaderManager value) 339 { 340 setProperty(new TestElementProperty(HEADER_MANAGER, value)); 341 } 342 343 public HeaderManager getHeaderManager() 344 { 345 return (HeaderManager)getProperty(HEADER_MANAGER).getObjectValue(); 346 } 347 348 public void setCookieManager(CookieManager value) 349 { 350 setProperty(new TestElementProperty(COOKIE_MANAGER, value)); 351 } 352 353 public CookieManager getCookieManager() 354 { 355 return (CookieManager)getProperty(COOKIE_MANAGER).getObjectValue(); 356 } 357 358 public void setMimetype(String value) 359 { 360 setProperty(MIMETYPE, value); 361 } 362 363 public String getMimetype() 364 { 365 return getPropertyAsString(MIMETYPE); 366 } 367 368 public boolean isImageParser() 369 { 370 return getPropertyAsBoolean(IMAGE_PARSER); 371 } 372 373 public void setImageParser(boolean parseImages) 374 { 375 setProperty(new BooleanProperty(IMAGE_PARSER, parseImages)); 376 } 377 378 387 protected HTTPSampleResult errorResult(Throwable e, String data, long time) 388 { 389 HTTPSampleResult res= new HTTPSampleResult(time); 390 res.setSampleLabel("Error"); 391 res.setSamplerData(data); 392 res.setDataType(HTTPSampleResult.TEXT); 393 ByteArrayOutputStream text= new ByteArrayOutputStream (200); 394 e.printStackTrace(new PrintStream (text)); 395 res.setResponseData(text.toByteArray()); 396 res.setResponseCode(NON_HTTP_RESPONSE_CODE); 397 res.setResponseMessage(NON_HTTP_RESPONSE_MESSAGE); 398 res.setSuccessful(false); 399 try { 400 res.setURL(getUrl()); 401 } catch (MalformedURLException ex){ 402 } 403 res.setMonitor(this.isMonitor()); 404 return res; 405 } 406 407 413 public URL getUrl() throws MalformedURLException 414 { 415 String pathAndQuery= null; 416 if (this.getMethod().equals(GET) 417 && getQueryString().length() > 0) 418 { 419 if (this.getPath().indexOf("?") > -1) 420 { 421 pathAndQuery= this.getPath() + "&" + getQueryString(); 422 } 423 else 424 { 425 pathAndQuery= this.getPath() + "?" + getQueryString(); 426 } 427 } 428 else 429 { 430 pathAndQuery= this.getPath(); 431 } 432 if (!pathAndQuery.startsWith("/")) 433 { 434 pathAndQuery= "/" + pathAndQuery; 435 } 436 if (getPort() == UNSPECIFIED_PORT || getPort() == DEFAULT_HTTP_PORT) 437 { 438 return new URL (getProtocol(), getDomain(), pathAndQuery); 439 } 440 else 441 { 442 return new URL ( 443 getProtocol(), 444 getPropertyAsString(DOMAIN), 445 getPort(), 446 pathAndQuery); 447 } 448 } 449 450 455 public String getQueryString() 456 { 457 StringBuffer buf= new StringBuffer (); 458 PropertyIterator iter= getArguments().iterator(); 459 boolean first= true; 460 while (iter.hasNext()) 461 { 462 HTTPArgument item= null; 463 try 464 { 465 item= (HTTPArgument)iter.next().getObjectValue(); 466 } 467 catch (ClassCastException e) 468 { 469 item= new HTTPArgument((Argument)iter.next().getObjectValue()); 470 } 471 if (!first) 472 { 473 buf.append("&"); 474 } 475 else 476 { 477 first= false; 478 } 479 buf.append(item.getEncodedName()); 480 if (item.getMetaData() == null) 481 { 482 buf.append("="); 483 } 484 else 485 { 486 buf.append(item.getMetaData()); 487 } 488 buf.append(item.getEncodedValue()); 489 } 490 return buf.toString(); 491 } 492 493 494 506 public void parseArguments(String queryString) 507 { 508 String [] args= JOrphanUtils.split(queryString, "&"); 509 for (int i= 0; i < args.length; i++) 510 { 511 int endOfNameIndex= 0; 517 String metaData= ""; if (args[i].indexOf("=") != -1) 519 { 520 endOfNameIndex= args[i].indexOf("="); 522 metaData= "="; 523 } 524 else 525 { 526 metaData= ""; 527 if (args[i].length() > 0) 528 { 529 endOfNameIndex= args[i].length(); } 531 else 532 { 533 endOfNameIndex= 0; } 535 } 536 String name= ""; if (args[i].length() > 0) 539 { 540 name= args[i].substring(0, endOfNameIndex); 542 } 543 String value= ""; 545 if ((endOfNameIndex + 1) < args[i].length()) 546 { 547 value= args[i].substring(endOfNameIndex + 1, args[i].length()); 548 } 549 if (name.length() > 0) 550 { 551 addEncodedArgument(name, value, metaData); 552 } 553 } 554 } 555 556 public String toString() 557 { 558 try 559 { 560 return this.getUrl().toString() 561 + ((POST.equals(getMethod())) 562 ? "\nQuery Data: " + getQueryString() 563 : ""); 564 } 565 catch (MalformedURLException e) 566 { 567 return ""; 568 } 569 } 570 571 577 public SampleResult sample(Entry e) { 578 return sample(); 579 } 580 581 586 public SampleResult sample() 587 { 588 try 589 { 590 SampleResult res= sample(getUrl(), getMethod(), false, 0); 591 res.setSampleLabel(getName()); 592 return res; 593 } 594 catch (MalformedURLException e) 595 { 596 return errorResult(e, getName(), 0); 597 } 598 } 599 600 protected abstract HTTPSampleResult sample(URL u, String s, boolean b, int i); 601 602 private static ThreadLocal localMatcher = new ThreadLocal () 603 { 604 protected synchronized Object initialValue() 605 { 606 return new Perl5Matcher(); 607 } 608 }; 609 private static Substitution spaceSub = new StringSubstitution("%20"); 610 611 630 protected HTTPSampleResult downloadPageResources( 631 HTTPSampleResult res, 632 boolean createContainerResult, 633 int frameDepth) 634 { 635 Iterator urls= null; 636 try 637 { 638 if (res.getContentType().toLowerCase().indexOf("text/html") != -1) 639 { 640 urls= 641 HTMLParser.getParser().getEmbeddedResourceURLs( 642 res.getResponseData(), 643 res.getURL()); 644 } 645 } 646 catch (HTMLParseException e) 647 { 648 res.addSubResult(errorResult(e, null, 0)); 650 res.setSuccessful(false); 651 } 652 653 if (urls != null && urls.hasNext()) 655 { 656 if (createContainerResult) 657 { 658 res= new HTTPSampleResult(res); 659 } 660 661 while (urls.hasNext()) 662 { 663 Object binURL= urls.next(); 664 try 665 { 666 HTTPSampleResult binRes= 667 sample( 668 (URL )binURL, 669 GET, 670 false, 671 frameDepth + 1); 672 res.addSubResult(binRes); 673 res.setSuccessful( 674 res.isSuccessful() && binRes.isSuccessful()); 675 } 676 catch (ClassCastException e) 677 { 678 res.addSubResult( 679 errorResult( 680 new Exception (binURL + " is not a correct URI"), 681 null, 682 0)); 683 res.setSuccessful(false); 684 continue; 685 } 686 } 687 } 688 return res; 689 } 690 691 protected String encodeSpaces(String path) { 692 path= 698 Util.substitute( 699 (Perl5Matcher)localMatcher.get(), 700 pattern, 701 spaceSub, 702 path, 703 Util.SUBSTITUTE_ALL); 704 return path; 705 } 706 707 protected static final int MAX_REDIRECTS = 5; 708 protected static final int MAX_FRAME_DEPTH = 5; 709 712 public void testEnded() 713 { 714 dynamicPath = false; 715 } 716 719 public void testEnded(String host) 720 { 721 testEnded(); 722 } 723 726 public void testIterationStart(LoopIterationEvent event) 727 { 728 } 729 732 public void testStarted() 733 { 734 JMeterProperty pathP = getProperty(PATH); 735 log.debug("path property is a " + pathP.getClass().getName()); 736 log.debug("path beginning value = " + pathP.getStringValue()); 737 if(pathP instanceof StringProperty && !"".equals(pathP.getStringValue())) 738 { 739 log.debug("Encoding spaces in path"); 740 pathP.setObjectValue(encodeSpaces(pathP.getStringValue())); 741 } 742 else 743 { 744 log.debug("setting dynamic path to true"); 745 dynamicPath = true; 746 } 747 log.debug("path ending value = " + pathP.getStringValue()); 748 } 749 752 public void testStarted(String host) 753 { 754 testStarted(); 755 } 756 759 public Object clone() 760 { 761 HTTPSamplerBase base = (HTTPSamplerBase)super.clone(); 762 base.dynamicPath = dynamicPath; 763 return base; 764 } 765 } 766 | Popular Tags |