1 18 19 package org.apache.jmeter.protocol.http.parser; 20 21 import java.io.ByteArrayInputStream ; 22 import java.io.UnsupportedEncodingException ; 23 import java.net.MalformedURLException ; 24 import java.net.URL ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 28 import org.apache.jmeter.config.Argument; 29 import org.apache.jmeter.junit.JMeterTestCase; 30 import org.apache.jmeter.protocol.http.sampler.HTTPSampler; 31 import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase; 32 import org.apache.jmeter.testelement.property.PropertyIterator; 33 import org.apache.jorphan.logging.LoggingManager; 34 import org.apache.jorphan.util.JOrphanUtils; 35 import org.apache.log.Logger; 36 import org.apache.oro.text.PatternCacheLRU; 37 import org.apache.oro.text.regex.MalformedPatternException; 38 import org.apache.oro.text.regex.Perl5Compiler; 39 import org.apache.oro.text.regex.Perl5Matcher; 40 import org.w3c.dom.Document ; 41 import org.w3c.dom.NamedNodeMap ; 42 import org.w3c.dom.Node ; 43 import org.w3c.dom.NodeList ; 44 import org.w3c.tidy.Tidy; 45 import org.xml.sax.SAXException ; 46 47 52 public final class HtmlParsingUtils 53 { 54 transient private static Logger log = LoggingManager.getLoggerForClass(); 55 56 private static String utfEncodingName; 57 63 64 private static PatternCacheLRU patternCache = 65 new PatternCacheLRU(1000, new Perl5Compiler()); 66 67 private static ThreadLocal localMatcher = new ThreadLocal () 68 { 69 protected Object initialValue() 70 { 71 return new Perl5Matcher(); 72 } 73 }; 74 75 78 private HtmlParsingUtils() 79 { 80 } 81 82 public static synchronized boolean isAnchorMatched( 83 HTTPSamplerBase newLink, 84 HTTPSamplerBase config) 85 throws MalformedPatternException 86 { 87 boolean ok = true; 88 Perl5Matcher matcher = (Perl5Matcher) localMatcher.get(); 89 PropertyIterator iter = config.getArguments().iterator(); 90 91 String query = null; 92 try 93 { 94 query = JOrphanUtils.decode(newLink.getQueryString(),"UTF-8"); 95 } 96 catch (UnsupportedEncodingException e) 97 { 98 log.error("UTF-8 encoding not supported!"); 100 throw new Error ("Should not happen: "+e.toString()); 101 } 102 103 if (query == null && config.getArguments().getArgumentCount() > 0) 104 { 105 return false; 106 } 107 108 while (iter.hasNext()) 109 { 110 Argument item = (Argument) iter.next().getObjectValue(); 111 if (query.indexOf(item.getName() + "=") == -1) 112 { 113 if (!(ok = 114 ok 115 && matcher.contains( 116 query, 117 patternCache.getPattern( 118 item.getName(), 119 Perl5Compiler.READ_ONLY_MASK)))) 120 { 121 return false; 122 } 123 } 124 } 125 126 if (config.getDomain() != null 127 && config.getDomain().length() > 0 128 && !newLink.getDomain().equals(config.getDomain())) 129 { 130 if (!(ok = 131 ok 132 && matcher.matches( 133 newLink.getDomain(), 134 patternCache.getPattern( 135 config.getDomain(), 136 Perl5Compiler.READ_ONLY_MASK)))) 137 { 138 return false; 139 } 140 } 141 142 if (!newLink.getPath().equals(config.getPath()) 143 && !matcher.matches( 144 newLink.getPath(), 145 patternCache.getPattern( 146 "[/]*" + config.getPath(), 147 Perl5Compiler.READ_ONLY_MASK))) 148 { 149 return false; 150 } 151 152 if (!(ok = 153 ok 154 && matcher.matches( 155 newLink.getProtocol(), 156 patternCache.getPattern( 157 config.getProtocol(), 158 Perl5Compiler.READ_ONLY_MASK)))) 159 { 160 return false; 161 } 162 163 return ok; 164 } 165 166 public static synchronized boolean isArgumentMatched( 167 Argument arg, 168 Argument patternArg) 169 throws MalformedPatternException 170 { 171 Perl5Matcher matcher = (Perl5Matcher) localMatcher.get(); 172 return ( 173 arg.getName().equals(patternArg.getName()) 174 || matcher.matches( 175 arg.getName(), 176 patternCache.getPattern( 177 patternArg.getName(), 178 Perl5Compiler.READ_ONLY_MASK))) 179 && (arg.getValue().equals(patternArg.getValue()) 180 || matcher.matches( 181 (String ) arg.getValue(), 182 patternCache.getPattern( 183 (String ) patternArg.getValue(), 184 Perl5Compiler.READ_ONLY_MASK))); 185 } 186 187 192 public static Tidy getParser() 193 { 194 log.debug("Start : getParser1"); 195 Tidy tidy = new Tidy(); 196 tidy.setCharEncoding(org.w3c.tidy.Configuration.UTF8); 197 tidy.setQuiet(true); 198 tidy.setShowWarnings(false); 199 200 if (log.isDebugEnabled()) 201 { 202 log.debug("getParser1 : tidy parser created - " + tidy); 203 } 204 205 log.debug("End : getParser1"); 206 207 return tidy; 208 } 209 210 216 public static Node getDOM(String text) throws SAXException 217 { 218 log.debug("Start : getDOM1"); 219 220 try 221 { 222 Node node = 223 getParser().parseDOM( 224 new ByteArrayInputStream ( 225 text.getBytes("UTF-8")), 226 null); 227 228 if (log.isDebugEnabled()) 229 { 230 log.debug("node : " + node); 231 } 232 233 log.debug("End : getDOM1"); 234 235 return node; 236 } 237 catch (UnsupportedEncodingException e) 238 { 239 log.error("getDOM1 : Unsupported encoding exception - " + e); 240 log.debug("End : getDOM1"); 241 throw new RuntimeException ("UTF-8 encoding failed"); 242 } 243 } 244 245 public static Document createEmptyDoc() 246 { 247 return Tidy.createEmptyDocument(); 248 } 249 250 255 public static HTTPSampler createUrlFromAnchor( 256 String parsedUrlString, 257 URL context) 258 throws MalformedURLException 259 { 260 if (log.isDebugEnabled()) 261 { 262 log.debug("Creating URL from Anchor: "+parsedUrlString 263 +", base: "+context); 264 } 265 URL url= new URL (context, parsedUrlString); 266 HTTPSampler sampler = new HTTPSampler(); 267 sampler.setDomain(url.getHost()); 268 sampler.setProtocol(url.getProtocol()); 269 sampler.setPort(url.getPort()); 270 sampler.setPath(url.getPath()); 271 sampler.parseArguments(url.getQuery()); 272 273 return sampler; 274 } 275 276 public static List createURLFromForm( 277 Node doc, 278 URL context) 279 { 280 String selectName = null; 281 LinkedList urlConfigs = new LinkedList (); 282 recurseForm(doc, urlConfigs, context, selectName, false); 283 293 return urlConfigs; 294 } 295 296 private static boolean recurseForm( 297 Node tempNode, 298 LinkedList urlConfigs, 299 URL context, 300 String selectName, 301 boolean inForm) 302 { 303 NamedNodeMap nodeAtts = tempNode.getAttributes(); 304 String tag = tempNode.getNodeName(); 305 try 306 { 307 if (inForm) 308 { 309 HTTPSampler url = (HTTPSampler) urlConfigs.getLast(); 310 if (tag.equalsIgnoreCase("form")) 311 { 312 try 313 { 314 urlConfigs.add(createFormUrlConfig(tempNode, context)); 315 } 316 catch (MalformedURLException e) 317 { 318 inForm = false; 319 } 320 } 321 else if (tag.equalsIgnoreCase("input")) 322 { 323 url.addArgument( 324 getAttributeValue(nodeAtts, "name"), 325 getAttributeValue(nodeAtts, "value")); 326 } 327 else if (tag.equalsIgnoreCase("textarea")) 328 { 329 try 330 { 331 url.addArgument( 332 getAttributeValue(nodeAtts, "name"), 333 tempNode.getFirstChild().getNodeValue()); 334 } 335 catch (NullPointerException e) 336 { 337 url.addArgument( 338 getAttributeValue(nodeAtts, "name"), 339 ""); 340 } 341 } 342 else if (tag.equalsIgnoreCase("select")) 343 { 344 selectName = getAttributeValue(nodeAtts, "name"); 345 } 346 else if (tag.equalsIgnoreCase("option")) 347 { 348 String value = getAttributeValue(nodeAtts, "value"); 349 if (value == null) 350 { 351 try 352 { 353 value = tempNode.getFirstChild().getNodeValue(); 354 } 355 catch (NullPointerException e) 356 { 357 value = ""; 358 } 359 } 360 url.addArgument(selectName, value); 361 } 362 } 363 else if (tag.equalsIgnoreCase("form")) 364 { 365 try 366 { 367 urlConfigs.add(createFormUrlConfig(tempNode, context)); 368 inForm = true; 369 } 370 catch (MalformedURLException e) 371 { 372 inForm = false; 373 } 374 385 } 386 } 387 catch (Exception ex) 388 { 389 log.warn("Some bad HTML " + printNode(tempNode), ex); 390 } 391 NodeList childNodes = tempNode.getChildNodes(); 392 for (int x = 0; x < childNodes.getLength(); x++) 393 { 394 inForm = 395 recurseForm( 396 childNodes.item(x), 397 urlConfigs, 398 context, 399 selectName, 400 inForm); 401 } 402 return inForm; 403 } 404 405 private static String getAttributeValue(NamedNodeMap att, String attName) 406 { 407 try 408 { 409 return att.getNamedItem(attName).getNodeValue(); 410 } 411 catch (Exception ex) 412 { 413 return ""; 414 } 415 } 416 417 private static String printNode(Node node) 418 { 419 StringBuffer buf = new StringBuffer (); 420 buf.append("<"); 421 buf.append(node.getNodeName()); 422 NamedNodeMap atts = node.getAttributes(); 423 for (int x = 0; x < atts.getLength(); x++) 424 { 425 buf.append(" "); 426 buf.append(atts.item(x).getNodeName()); 427 buf.append("=\""); 428 buf.append(atts.item(x).getNodeValue()); 429 buf.append("\""); 430 } 431 432 buf.append(">"); 433 434 return buf.toString(); 435 } 436 private static HTTPSampler createFormUrlConfig( 437 Node tempNode, 438 URL context) 439 throws MalformedURLException 440 { 441 NamedNodeMap atts = tempNode.getAttributes(); 442 if (atts.getNamedItem("action") == null) 443 { 444 throw new MalformedURLException (); 445 } 446 String action = atts.getNamedItem("action").getNodeValue(); 447 HTTPSampler url = createUrlFromAnchor(action, context); 448 return url; 449 } 450 451 453 455 public static class Test extends JMeterTestCase 456 { 457 458 public Test(String name) 459 { 460 super(name); 461 } 462 463 protected void setUp() 464 { 465 } 466 467 public void testGetParser() throws Exception 468 { 469 getParser(); 470 } 471 public void testGetDom() throws Exception 472 { 473 getDOM("<HTML></HTML>"); 474 getDOM(""); 475 } 476 public void testIsArgumentMatched() throws Exception 477 { 478 Argument arg = new Argument(); 479 Argument argp = new Argument(); 480 assertTrue(isArgumentMatched(arg,argp)); 481 482 arg = new Argument("test","abcd"); 483 argp = new Argument("test","a.*d"); 484 assertTrue(isArgumentMatched(arg,argp)); 485 486 arg = new Argument("test","abcd"); 487 argp = new Argument("test","a.*e"); 488 assertFalse(isArgumentMatched(arg,argp)); 489 } 490 } 491 } 492 | Popular Tags |