sebb 2003/11/26 18:55:05 Modified: src/protocol/http/org/apache/jmeter/protocol/http/parser HTMLParser.java Log: Use reflection to get Parserinstance, and cache the result; update tests Revision Changes Path 1.5 +225 -66 jakarta-jmeter/src/protocol/http/org/apache/jmeter/protocol/http/parser/HTMLParser.java Index: HTMLParser.java =================================================================== RCS file: /home/cvs/jakarta-jmeter/src/protocol/http/org/apache/jmeter/protocol/http/parser/HTMLParser.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- HTMLParser.java 26 Nov 2003 22:50:14 -0000 1.4 +++ HTMLParser.java 27 Nov 2003 02:55:05 -0000 1.5 @@ -59,11 +59,16 @@ import java.io.File; import java.io.FileInputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URL; import java.util.Arrays; import java.util.Collection; +import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.Properties; +import java.util.Vector; import junit.framework.TestCase; @@ -76,11 +81,28 @@ */ public abstract class HTMLParser { - /** Used to store the Logger (used for debug and error messages). */ + /** Used to store the Logger (used for debug and error messages). */ transient private static Logger log = LoggingManager.getLoggerForClass(); - /** Singleton */ - static HTMLParser parser; +// /** Singleton */ +// private static HTMLParser parser; + + private static final String PARSER_METHOD = "getParserInstance"; + private static final String PARSER_REUSABLE = "isParserReusable"; + + /* + * Cache of methods. + * These need to be invoked each time, in case the parser cannot be re-used + */ + private static Hashtable methods = new Hashtable(3); + + // Cache of parsers - used if parsers are re-usable + private static Hashtable parsers = new Hashtable(3); + + private final static String PARSER_CLASSNAME = "htmlParser.className"; + + private final static String DEFAULT_PARSER = + "org.apache.jmeter.protocol.http.parser.HtmlParserHTMLParser"; /** * Protected constructor to prevent instantiation except @@ -89,48 +111,139 @@ protected HTMLParser() { } - /** - * Create the single instance. - */ - private static void initialize() - { - String htmlParserClassName= - JMeterUtils.getPropDefault( - "htmlParser.className", - "org.apache.jmeter.protocol.http.parser.HtmlParserHTMLParser"); - - try +// /** +// * Create the single instance. +// */ +// private static void initialize() +// { +// String htmlParserClassName= +// JMeterUtils.getPropDefault(PARSER_CLASSNAME,DEFAULT_PARSER); +// +// try +// { +// parser= +// (HTMLParser)Class.forName(htmlParserClassName).newInstance(); +// } +// catch (InstantiationException e) +// { +// throw new Error(e); +// } +// catch (IllegalAccessException e) +// { +// throw new Error(e); +// } +// catch (ClassNotFoundException e) +// { +// throw new Error(e); +// } +// log.info("Using "+htmlParserClassName); +// } + + public static final HTMLParser getParser(){ + boolean reusable=false; + String htmlParserClassName= + JMeterUtils.getPropDefault(PARSER_CLASSNAME,DEFAULT_PARSER); + + HTMLParser pars=(HTMLParser) parsers.get(htmlParserClassName); + if (pars != null){ + log.info("Fetched "+htmlParserClassName); + return pars; + } + Method meth =(Method) methods.get(htmlParserClassName); + if (meth != null) { + try + { + pars = (HTMLParser) meth.invoke(null,null); + } + catch (NullPointerException e) // method did not return anything + { + throw new Error(PARSER_METHOD+"() returned null",e); + } + catch (IllegalArgumentException e) + { + throw new Error("Should not happen",e); + } + catch (IllegalAccessException e) + { + throw new Error("Should not happen",e); + } + catch (InvocationTargetException e) + { + throw new Error("Should not happen",e); + }; + log.info("Using "+htmlParserClassName); + return pars; + } + + try + { + Class clazz = Class.forName(htmlParserClassName); + meth = clazz.getMethod(PARSER_METHOD,null); + pars= (HTMLParser) meth.invoke(null,null); + try{ + reusable=((Boolean) + clazz.getMethod(PARSER_REUSABLE,null) + .invoke(null,null)) + .booleanValue(); + } + catch (Exception e){ + // ignored + } + } + catch (NullPointerException e) // method did not return anything + { + throw new Error(PARSER_METHOD+"() returned null",e); + } + catch (IllegalAccessException e) + { + throw new Error(e); + } + catch (ClassNotFoundException e) + { + throw new Error(e); + } + catch (SecurityException e) { - parser= - (HTMLParser)Class.forName(htmlParserClassName).newInstance(); + throw new Error(e); } - catch (InstantiationException e) + catch (NoSuchMethodException e) { - throw new Error(e); + throw new Error(e); } - catch (IllegalAccessException e) + catch (IllegalArgumentException e) { - throw new Error(e); + throw new Error(e); } - catch (ClassNotFoundException e) + catch (InvocationTargetException e) { - throw new Error(e); + throw new Error(e); } - log.info("Using "+htmlParserClassName); + log.info("Created "+htmlParserClassName+ " reusable="+reusable); + if (reusable){ + parsers.put(htmlParserClassName,pars); + } + methods.put(htmlParserClassName,meth); + return pars; } +// /** +// * Obtain the (singleton) HtmlParser. +// * +// * @return The single HtmlParser instance. +// */ +// public static final synchronized HTMLParser xgetParser() +// { +// if (parser == null) { +// initialize(); +// } +// return parser; +// } - /** - * Obtain the (singleton) HtmlParser. - * - * @return The single HtmlParser instance. - */ - public static final synchronized HTMLParser getParser() - { - if (parser == null) { - initialize(); - } - return parser; - } + /** + * Obtain the (singleton) HtmlParser. + * + * @return The single HtmlParser instance. + */ + //public static abstract HTMLParser xgetParserInstance(); /** * Get the URLs for all the resources that a browser would automatically @@ -155,6 +268,7 @@ // the elements in the set later on. As a side-effect, this will keep // them roughly in order, which should be a better model of browser // behaviour. + // N.B. LinkedHashSet is Java 1.4 return getEmbeddedResourceURLs(html, baseUrl,new LinkedHashSet()); } @@ -180,43 +294,88 @@ public static class HTMLParserTest extends TestCase { + private static final String TESTFILE1= "testfiles/HTMLParserTestCase.html"; + private static final String URL1 = "http://myhost/mydir/myfile.html"; + private static final String[] EXPECTED_RESULT1 = new String[] { + "http://myhost/mydir/images/image-a.gif", + "http://myhost/mydir/images/image-b.gif", + "http://myhost/mydir/images/image-c.gif", + "http://myhost/mydir/images/image-d.gif", + "http://myhost/mydir/images/image-e.gif", + "http://myhost/mydir/images/image-f.gif", + "http://myhost/mydir/images/image-a2.gif", + "http://myhost/mydir/images/image-b2.gif", + "http://myhost/mydir/images/image-c2.gif", + "http://myhost/mydir/images/image-d2.gif", + "http://myhost/mydir/images/image-e2.gif", + "http://myhost/mydir/images/image-f2.gif", + }; + + private static final String[] EXPECTED_RESULT1A = new String[] { + "http://myhost/mydir/images/image-a.gif", + "http://myhost/mydir/images/image-b.gif", + "http://myhost/mydir/images/image-b.gif", + "http://myhost/mydir/images/image-c.gif", + "http://myhost/mydir/images/image-d.gif", + "http://myhost/mydir/images/image-e.gif", + "http://myhost/mydir/images/image-f.gif", + "http://myhost/mydir/images/image-a2.gif", + "http://myhost/mydir/images/image-b2.gif", + "http://myhost/mydir/images/image-c2.gif", + "http://myhost/mydir/images/image-d2.gif", + "http://myhost/mydir/images/image-d2.gif", + "http://myhost/mydir/images/image-e2.gif", + "http://myhost/mydir/images/image-f2.gif", + }; public HTMLParserTest() { super(); } - public static void testParser(HTMLParser parser) throws Exception + // Test if can instantiate parser using property name + public static void testParser(String s) throws Exception { - final String[] EXPECTED_RESULT= new String[] { - "http://myhost/mydir/images/image-a.gif", - "http://myhost/mydir/images/image-b.gif", - "http://myhost/mydir/images/image-c.gif", - "http://myhost/mydir/images/image-d.gif", - "http://myhost/mydir/images/image-e.gif", - "http://myhost/mydir/images/image-f.gif", - "http://myhost/mydir/images/image-a2.gif", - "http://myhost/mydir/images/image-b2.gif", - "http://myhost/mydir/images/image-c2.gif", - "http://myhost/mydir/images/image-d2.gif", - "http://myhost/mydir/images/image-e2.gif", - "http://myhost/mydir/images/image-f2.gif", - }; - File f= new File("testfiles/HTMLParserTestCase.html"); - byte[] buffer= new byte[(int)f.length()]; - int len= new FileInputStream(f).read(buffer); - assertEquals(len, buffer.length); - Iterator result= - parser.getEmbeddedResourceURLs( - buffer, - new URL("http://myhost/mydir/myfile.html")); - Iterator expected= Arrays.asList(EXPECTED_RESULT).iterator(); - while (expected.hasNext()) { - assertTrue(result.hasNext()); - assertEquals(expected.next(), result.next().toString()); - } - assertFalse(result.hasNext()); + Properties p = JMeterUtils.getJMeterProperties(); + if (p == null){ + p=JMeterUtils.getProperties("jmeter.properties"); + } + p.setProperty(PARSER_CLASSNAME,s); + testParser(getParser()); + testParser(getParser());// check re-usability } + + //TODO - this test won't work for non-reusable parsers + public static void testParser(HTMLParser p) throws Exception + { + filetest(p,TESTFILE1,URL1,EXPECTED_RESULT1,null); + filetest(p,TESTFILE1,URL1,EXPECTED_RESULT1,null);// See if reusable + filetest(p,TESTFILE1,URL1,EXPECTED_RESULT1A,new Vector()); + filetest(p,TESTFILE1,URL1,EXPECTED_RESULT1A,new Vector()); + } + + private static void filetest(HTMLParser p,String file, String url, String[] expected_result, + Collection c) throws Exception + { + log.info("file "+file); + log.info("parser "+p.getClass().getName()); + File f= new File(file); + byte[] buffer= new byte[(int)f.length()]; + int len= new FileInputStream(f).read(buffer); + assertEquals(len, buffer.length); + Iterator result; + if (c == null) { + result = p.getEmbeddedResourceURLs(buffer,new URL(url)); + } else { + result = p.getEmbeddedResourceURLs(buffer,new URL(url),c); + } + Iterator expected= Arrays.asList(expected_result).iterator(); + while (expected.hasNext()) { + assertTrue(result.hasNext()); + assertEquals(expected.next(), result.next().toString()); + } + assertFalse(result.hasNext()); + } public void testDefaultParser() throws Exception { testParser(getParser()); } } -} +} \ No newline at end of file
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]