Source Code Cross Referenced for Configuration.java in  » Testing » webtest » com » canoo » webtest » engine » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » webtest » com.canoo.webtest.engine 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // Copyright © 2002-2007 Canoo Engineering AG, Switzerland.
002:        package com.canoo.webtest.engine;
003:
004:        import java.io.File;
005:        import java.io.IOException;
006:        import java.lang.reflect.Method;
007:        import java.net.URL;
008:        import java.util.HashMap;
009:        import java.util.HashSet;
010:        import java.util.Iterator;
011:        import java.util.LinkedList;
012:        import java.util.List;
013:        import java.util.Map;
014:        import java.util.Set;
015:
016:        import org.apache.commons.lang.StringUtils;
017:        import org.apache.commons.lang.WordUtils;
018:        import org.apache.log4j.Logger;
019:        import org.apache.tools.ant.BuildException;
020:        import org.apache.tools.ant.IntrospectionHelper;
021:        import org.apache.tools.ant.Project;
022:        import org.apache.tools.ant.Task;
023:
024:        import com.canoo.webtest.ant.WebtestTask;
025:        import com.canoo.webtest.interfaces.IPropertyHandler;
026:        import com.canoo.webtest.plugins.pdftest.htmlunit.PDFPage;
027:        import com.canoo.webtest.plugins.pdftest.htmlunit.pdfbox.PdfBoxPDFPage;
028:        import com.canoo.webtest.steps.HtmlParserMessage;
029:        import com.canoo.webtest.util.Checker;
030:        import com.canoo.webtest.util.MapUtil;
031:        import com.gargoylesoftware.htmlunit.BrowserVersion;
032:        import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider;
033:        import com.gargoylesoftware.htmlunit.DefaultPageCreator;
034:        import com.gargoylesoftware.htmlunit.Page;
035:        import com.gargoylesoftware.htmlunit.RefreshHandler;
036:        import com.gargoylesoftware.htmlunit.WebClient;
037:        import com.gargoylesoftware.htmlunit.WebRequestSettings;
038:        import com.gargoylesoftware.htmlunit.WebResponse;
039:        import com.gargoylesoftware.htmlunit.WebWindow;
040:
041:        /**
042:         * Captures configuration information.<p>
043:         *
044:         * @author unknown
045:         * @author Marc Guillemot
046:         * @author Paul King
047:         * @webtest.step category="General"
048:         * name="config"
049:         * description="This is a nested task of 
050:         * <stepref name='webtest' category='General'/> 
051:         * and is used to configure the target host system to use for a particular 
052:         * <stepref name='webtest' category='General'/> 
053:         * and several other features such as reporting of test results 
054:         * and printing of debug information."
055:         */
056:        public class Configuration extends Task {
057:            private static final Logger LOG = Logger
058:                    .getLogger(Configuration.class);
059:            public static final int PORT_HTTP = 80;
060:            public static final int PORT_HTTPS = 443;
061:            public static final int DEFAULT_PORT = PORT_HTTP;
062:            public static final String DEFAULT_HOST = "localhost";
063:            public static final String PROTOCOL_HTTP = "http";
064:            public static final String PROTOCOL_HTTPS = "https";
065:            public static final String PROTOCOL_FILE = "file";
066:            private static final String URL_SEPARATOR = "/";
067:
068:            /** The number of seconds before http connections timeout: (default={@value}) */
069:            protected static final int DEFAULT_TIMEOUT = 5 * 60; // protected visibility to generate javadoc
070:
071:            private boolean fSummary;
072:            private int fPort = DEFAULT_PORT;
073:            private int fTimeout = DEFAULT_TIMEOUT;
074:            private String fProtocol = PROTOCOL_HTTP;
075:            private boolean fSaveResponse;
076:            private boolean fEasyAjax = false;
077:
078:            private String fSavePrefix = "response";
079:            private String fAutoRefresh = "false";
080:            private String fResultFile = "WebTestReport.xml";
081:
082:            private boolean fShowHtmlParserOutput;
083:            private boolean fHaltOnError;
084:            private boolean fHaltOnFailure;
085:            private String fErrorProperty;
086:            private String fFailureProperty;
087:            private String fDefaultPropertyType;
088:            private File fSummaryFile;
089:
090:            private String fHost = DEFAULT_HOST;
091:            private String fBasePath;
092:            private File fResultPath;
093:            private File fWebtestResultDir;
094:
095:            private IPropertyHandler fPropertyHandler;
096:            private final List fHeaderList = new LinkedList();
097:            private final List fOptionList = new LinkedList();
098:            private Context fContext;
099:            private int resultFolderIndex = -1;
100:
101:            /**
102:             * The task properties that may take default values from the corresponding wt.config.* project properties
103:             * (when not configured explicitely on the task).
104:             */
105:            private final static String[] PROPERTIES = { "autorefresh",
106:                    "basepath", "defaultpropertytype", "errorproperty",
107:                    "failureproperty", "haltonerror", "haltonfailure", "host",
108:                    "port", "protocol", "resultpath", "saveprefix",
109:                    "saveresponse", "showhtmlparseroutput", "summary",
110:                    "timeout" };
111:
112:            /**
113:             * Configuration constructor used by instance creation as nested element in ant.<p>
114:             */
115:            public Configuration() {
116:                fHaltOnError = true;
117:                fHaltOnFailure = true;
118:            }
119:
120:            /**
121:             * Get's called from Ant once the project and target references have been set
122:             * but before the properties are configured
123:             */
124:            public void init() {
125:                // read values from wt.config.* properties
126:                configureDefaultFromProjectProperties();
127:            }
128:
129:            /**
130:             * Configuration constructor used to generate a default configuration when the user omit it.<p>
131:             */
132:            public Configuration(final WebtestTask testSpec) {
133:                // default properties
134:                fSummary = true;
135:                fSaveResponse = true;
136:                fErrorProperty = "webtest.error";
137:                fFailureProperty = "webtest.failure";
138:                fShowHtmlParserOutput = true;
139:                setProject(testSpec.getProject());
140:                setOwningTarget(testSpec.getOwningTarget());
141:                init(); // as ant does, here to configure from wt.config.* properties
142:            }
143:
144:            /* Must be done in execute not init as task attributes not available in init */
145:            public void execute() throws BuildException {
146:                configureDefaultFromProjectProperties();
147:
148:                if (getResultpath() == null) {
149:                    setResultpath(getProject().resolveFile("webtest-results"));
150:                }
151:                prepareResultDir(getResultpath());
152:                if (isSummary()) {
153:                    Checker.assertTrue(getResultFile() != null,
154:                            "Result file cannot be null when writing summary");
155:                    fSummaryFile = new File(getWebTestResultDir(),
156:                            getResultFile());
157:                    LOG.debug("Result file: " + fSummaryFile.getAbsolutePath());
158:                }
159:
160:                setupWebClient();
161:            }
162:
163:            protected void setupWebClient() {
164:                fContext.setWebClient(createWebClient());
165:            }
166:
167:            private void configureDefaultFromProjectProperties() {
168:                // read the properties that have been configured, they should not be replaced!
169:                final Set existingProps = new HashSet();
170:                if (getRuntimeConfigurableWrapper() != null) // null when no config is used
171:                {
172:                    for (final Iterator iter = getRuntimeConfigurableWrapper()
173:                            .getAttributeMap().keySet().iterator(); iter
174:                            .hasNext();) {
175:                        existingProps.add(((String) iter.next()).toLowerCase());
176:                    }
177:                }
178:
179:                final IntrospectionHelper ih = IntrospectionHelper.getHelper(
180:                        getProject(), getClass());
181:                for (int i = 0; i < PROPERTIES.length; ++i) {
182:                    final String propName = PROPERTIES[i];
183:                    if (!existingProps.contains(propName)) {
184:                        final String propValue = getProject().getProperty(
185:                                "wt.config." + propName);
186:                        if (propValue != null) {
187:                            LOG.info("Using " + propName
188:                                    + " from project property wt.config."
189:                                    + propName + ": " + propValue);
190:                            ih.setAttribute(getProject(), this , propName,
191:                                    propValue);
192:                        }
193:                    }
194:                }
195:            }
196:
197:            // package protection for testing purposes
198:            void prepareResultDir(final File resultDir) {
199:                if (isSummary() || isSaveResponse()) {
200:                    if (resultDir.exists() && !resultDir.isDirectory()) {
201:                        throw new BuildException(
202:                                "Result dir is not a directory: "
203:                                        + resultDir.getAbsolutePath());
204:                    }
205:
206:                    // compute subdir for this test
207:                    fWebtestResultDir = computeSubFolder(resultDir);
208:                    LOG.info("Creating result directory: "
209:                            + fWebtestResultDir.getAbsolutePath());
210:
211:                    if (!fWebtestResultDir.mkdirs()) {
212:                        throw new BuildException(
213:                                "Failed to create result dir: "
214:                                        + fWebtestResultDir.getAbsolutePath());
215:                    }
216:                } else {
217:                    LOG
218:                            .warn("Result dir '"
219:                                    + resultDir.getName()
220:                                    + "' not created (may not be needed), may cause problems if individual steps set save attribute");
221:                }
222:            }
223:
224:            /**
225:             * Compute the name of the subfolder for this test
226:             * @param _resultDir the "main" result dir
227:             * @return the name of the subfolder
228:             */
229:            protected File computeSubFolder(final File _resultDir) {
230:                if (resultFolderIndex == -1)
231:                    resultFolderIndex = getResultFolderIndex(_resultDir);
232:
233:                final String prefix = StringUtils.leftPad(String
234:                        .valueOf(resultFolderIndex), 3, '0');
235:                final String fixedTestName = WordUtils.capitalize(
236:                        fContext.getWebtest().getName()).replaceAll("\\W", "");
237:                final String name = prefix + "_" + fixedTestName;
238:
239:                final int dirNameMaxLength = 20;
240:                return new File(_resultDir, StringUtils.left(name,
241:                        dirNameMaxLength));
242:            }
243:
244:            /**
245:             * Sets the index of the result folder. Normally this shouldn't be set from
246:             * outside but the new experimental feature "WebTest parallel" currently needs it. 
247:             * @param index the index
248:             */
249:            public void setResultFolderIndex(final int index) {
250:                resultFolderIndex = index;
251:            }
252:
253:            /**
254:             * Get the index to use as prefix for the dedicated result folder of this test
255:             * @param _resultDir the base result directory
256:             * @return the index
257:             */
258:            protected int getResultFolderIndex(final File _resultDir) {
259:                int lastIndex = 0;
260:                final File[] children = _resultDir.listFiles();
261:                if (children != null) // null when _resultDir is not (yet?) a directory
262:                {
263:                    for (int i = 0; i < children.length; i++) {
264:                        final File f = children[i];
265:                        if (f.getName().matches("\\d{3}_.*")) {
266:                            final int index = Integer.parseInt(f.getName()
267:                                    .substring(0, 3));
268:                            lastIndex = Math.max(lastIndex, index);
269:                        }
270:                    }
271:                }
272:                return lastIndex + 1;
273:            }
274:
275:            /**
276:             * Gets the file where the summary should be written.<p>
277:             *
278:             * @return <code>null</code> if no resultfile was specified
279:             */
280:            public File getSummaryFile() {
281:                // TODO: remove it!
282:                return fSummaryFile;
283:            }
284:
285:            /**
286:             *
287:             * @param header
288:             * @webtest.nested.parameter
289:             *    required="no"
290:             *    description="Specify http headers by name and value"
291:             */
292:            public void addHeader(final Header header) {
293:                fHeaderList.add(header);
294:            }
295:
296:            public List getHeaderList() {
297:                return fHeaderList;
298:            }
299:
300:            /**
301:             *
302:             * @param option
303:             * @webtest.nested.parameter
304:             *    required="no"
305:             *    description="Tweak the underlying web client options/settings"
306:             */
307:            public void addOption(final Option option) {
308:                fOptionList.add(option);
309:            }
310:
311:            public List getOptionList() {
312:                return fOptionList;
313:            }
314:
315:            public String getBasePath() {
316:                return fBasePath;
317:            }
318:
319:            /**
320:             * Gets the User-Agent header to be sent.<p>
321:             *
322:             * @return <code>null</code> if none has been configured
323:             */
324:            public String getUserAgent() {
325:                LOG.debug("Headers: " + getHeaderList());
326:                for (final Iterator iter = getHeaderList().iterator(); iter
327:                        .hasNext();) {
328:                    final Header elt = (Header) iter.next();
329:                    if ("User-Agent".equals(elt.getName())) {
330:                        LOG.debug("Found User-Agent header: " + elt.getValue());
331:                        return elt.getValue();
332:                    }
333:                    LOG.debug("Not User-Agent header: " + elt.getName());
334:                }
335:                return null;
336:            }
337:
338:            /**
339:             * Indicates if the default port for the protocol is used (that is port is not needed in the url).<p>
340:             */
341:            private boolean isDefaultPort() {
342:                return (PROTOCOL_HTTP.equals(getProtocol()) && PORT_HTTP == getPort())
343:                        || (PROTOCOL_HTTPS.equals(getProtocol()) && PORT_HTTPS == getPort());
344:            }
345:
346:            public String getHost() {
347:                return fHost;
348:            }
349:
350:            public int getPort() {
351:                return fPort;
352:            }
353:
354:            public String getProtocol() {
355:                return fProtocol;
356:            }
357:
358:            /**
359:             * This is the configured general result dir.
360:             * This value should not be used directly as results will be placed in a sub folder of it in the future
361:             * @return the configured result path
362:             */
363:            File getResultpath() {
364:                return fResultPath;
365:            }
366:
367:            /**
368:             * Gets the directory where all artifacts of this specific test should be saved.
369:             * This is currently the same than {@link #getResultpath()} but this may change in the future.
370:             * @return the folder
371:             */
372:            public File getWebTestResultDir() {
373:                return fWebtestResultDir;
374:            }
375:
376:            public String getSavePrefix() {
377:                return fSavePrefix;
378:            }
379:
380:            /**
381:             * Completes a URL based on configuration values by expanding
382:             * where needed from a base URL (protocol and optionally
383:             * host:port). If the provided page is complete (already with protocol), it is returned as is.<p>
384:             *
385:             * @param page the maybe relative target URL
386:             * @return the assembled URL
387:             */
388:            public String getUrlForPage(final String page) {
389:                // first test if the page starts with a protocol like "http://", "https://", "file:/"
390:                final int index = StringUtils.indexOf(page, "://");
391:                if (index > -1
392:                        && index < 6
393:                        || (page != null && page.toLowerCase().startsWith(
394:                                "file:/"))) {
395:                    return page;
396:                } else if (PROTOCOL_FILE.equals(getProtocol())) {
397:                    return createFileBasedUrl(page);
398:                } else {
399:                    return createNetworkBasedUrl(page);
400:                }
401:            }
402:
403:            private String createFileBasedUrl(final String page) {
404:                return getProtocol() + ":"
405:                        + combineBasePathAndPage(getBasePath(), page);
406:            }
407:
408:            private String createNetworkBasedUrl(final String page) {
409:                final StringBuffer url = new StringBuffer(getProtocol());
410:                url.append("://");
411:                url.append(getHost());
412:                if (!isDefaultPort()) {
413:                    url.append(":");
414:                    url.append(getPort());
415:                }
416:                url.append(combineBasePathAndPage(getBasePath(), page));
417:                return url.toString();
418:            }
419:
420:            private static String combineBasePathAndPage(final String basePath,
421:                    final String page) {
422:                String basePathClean = StringUtils.strip(basePath,
423:                        URL_SEPARATOR);
424:                basePathClean = StringUtils.isEmpty(basePathClean) ? ""
425:                        : (URL_SEPARATOR + basePathClean);
426:                String pageClean = StringUtils.stripStart(page, URL_SEPARATOR);
427:                pageClean = StringUtils.isEmpty(pageClean) ? ""
428:                        : (URL_SEPARATOR + pageClean);
429:                return basePathClean + pageClean;
430:            }
431:
432:            public boolean isSaveResponse() {
433:                return fSaveResponse;
434:            }
435:
436:            public boolean isSummary() {
437:                return fSummary;
438:            }
439:
440:            public void setSavePrefix(String savePrefix) {
441:                fSavePrefix = savePrefix;
442:            }
443:
444:            /**
445:             * Defines the constant base path used to construct request URLs,
446:             * e.g. "shop" can be considered a basepath in "http://www.myhost.com/shop/productlist"
447:             * and "http://www.myhost.com/shop/checkout".<p>
448:             *
449:             * @param newBasePath the new value
450:             */
451:            public void setBasepath(final String newBasePath) {
452:                fBasePath = newBasePath;
453:            }
454:
455:            public void setHost(final String newHost) {
456:                fHost = newHost;
457:            }
458:
459:            public void setPort(final int newPort) {
460:                fPort = newPort;
461:            }
462:
463:            public void setProtocol(final String newProtocol) {
464:                fProtocol = newProtocol;
465:            }
466:
467:            public void setResultpath(final File newResultPath) {
468:                fResultPath = newResultPath;
469:            }
470:
471:            public void setSaveresponse(final boolean newSaveResponse) {
472:                fSaveResponse = newSaveResponse;
473:            }
474:
475:            public void setSummary(final boolean newSummary) {
476:                fSummary = newSummary;
477:            }
478:
479:            public void setHaltonerror(final boolean haltOnError) {
480:                fHaltOnError = haltOnError;
481:            }
482:
483:            public void setHaltonfailure(final boolean haltOnFailure) {
484:                fHaltOnFailure = haltOnFailure;
485:            }
486:
487:            public void setErrorProperty(final String errorProperty) {
488:                fErrorProperty = errorProperty;
489:            }
490:
491:            public void setFailureProperty(final String failureProperty) {
492:                fFailureProperty = failureProperty;
493:            }
494:
495:            public String getFailureProperty() {
496:                return fFailureProperty;
497:            }
498:
499:            public String getErrorProperty() {
500:                return fErrorProperty;
501:            }
502:
503:            public String getDefaultPropertyType() {
504:                return fDefaultPropertyType;
505:            }
506:
507:            public void setDefaultPropertyType(final String type) {
508:                fDefaultPropertyType = type;
509:            }
510:
511:            public void setShowhtmlparseroutput(final boolean showParserOutput) {
512:                fShowHtmlParserOutput = showParserOutput;
513:            }
514:
515:            public boolean isShowHtmlParserOutput() {
516:                return fShowHtmlParserOutput;
517:            }
518:
519:            public boolean isHaltOnFailure() {
520:                return fHaltOnFailure;
521:            }
522:
523:            public boolean isHaltOnError() {
524:                return fHaltOnError;
525:            }
526:
527:            public Map getParameterDictionary() {
528:                final Map map = new HashMap();
529:                map.put("host", getHost());
530:                map.put("protocol", getProtocol());
531:                map.put("port", String.valueOf(getPort()));
532:                map.put("timeout", String.valueOf(getTimeout()));
533:                map.put("basepath", getBasePath());
534:                map.put("resultpath", getResultpath());
535:                map.put("summary", isSummary() ? "yes" : "no");
536:                map.put("saveresponse", isSaveResponse() ? "yes" : "no");
537:                map.put("saveprefix", getSavePrefix());
538:                map.put("haltonerror", isHaltOnError() ? "yes" : "no");
539:                map.put("haltonfailure", isHaltOnFailure() ? "yes" : "no");
540:                MapUtil.putIfNotNull(map, "errorproperty", getErrorProperty());
541:                MapUtil.putIfNotNull(map, "failureproperty",
542:                        getFailureProperty());
543:                MapUtil.putIfNotNull(map, "defaultpropertytype",
544:                        getDefaultPropertyType());
545:                map.put("autorefresh", getAutoRefresh());
546:                map.put("showhtmlparseroutput",
547:                        isShowHtmlParserOutput() ? "yes" : "no");
548:                map.put("resultfile", getResultFile());
549:
550:                return map;
551:            }
552:
553:            public String getResultFile() {
554:                return fResultFile;
555:            }
556:
557:            public void setResultfile(final String resultFile) {
558:                //        fResultFile = resultFile;
559:            }
560:
561:            public void setPropertyHandler(
562:                    final IPropertyHandler propertyHandler) {
563:                fPropertyHandler = propertyHandler;
564:            }
565:
566:            public String getExternalProperty(final String name) {
567:                if (fPropertyHandler == null) {
568:                    throw new IllegalStateException(
569:                            "No property handler configured!");
570:                }
571:                return fPropertyHandler.getProperty(name);
572:            }
573:
574:            /**
575:             * Returns true if the client should automatically follow page refresh requests.<p>
576:             */
577:            public String getAutoRefresh() {
578:                return fAutoRefresh;
579:            }
580:
581:            /**
582:             * Determines if the client should automatically follow page refresh requests.<p>
583:             *
584:             * @param str the new refresh value
585:             */
586:            public void setAutoRefresh(final String str) {
587:                fAutoRefresh = str;
588:            }
589:
590:            /**
591:             * Defines the context. This is called to set the context on the task before {@link #execute()}
592:             * is called
593:             * @param context the context
594:             */
595:            public void setContext(final Context context) {
596:                fContext = context;
597:            }
598:
599:            /**
600:             * Configures the webclient used for the test
601:             *
602:             */
603:            public WebClient createWebClient() {
604:                final Configuration cfg = this ;
605:                final String strUserAgent = cfg.getUserAgent();
606:                final BrowserVersion browserVersion = setupBrowserVersion(strUserAgent);
607:                final WebClient webClient = setupWebClient(browserVersion);
608:
609:                webClient.setTimeout(getTimeout() * 1000);
610:
611:                setupHtmlParser(webClient, cfg);
612:                setupRefreshHandler(webClient, cfg); // auto refresh settings
613:                webClient.setThrowExceptionOnScriptError(true); // option for this and report js errors?
614:                WebClient.setIgnoreOutsideContent(true);
615:                setupHttpHeaders(webClient, cfg);
616:                setupOptions(webClient, cfg);
617:
618:                configurePageCreator(webClient);
619:
620:                return webClient;
621:            }
622:
623:            /**
624:             * Configures WebTest's custom page creator able to create PDFPage (as long as this is not integrated
625:             * directly into HtmlUnit)
626:             */
627:            protected void configurePageCreator(final WebClient webClient) {
628:                final DefaultPageCreator pageCreator = new DefaultPageCreator() {
629:                    public Page createPage(final WebResponse webResponse,
630:                            final WebWindow webWindow) throws IOException {
631:                        final String contentType = webResponse.getContentType()
632:                                .toLowerCase();
633:
634:                        if ("application/pdf".equals(contentType)) {
635:                            final PDFPage newPage = new PdfBoxPDFPage(
636:                                    webResponse, webWindow);
637:                            webWindow.setEnclosedPage(newPage);
638:                            return newPage;
639:                        } else
640:                            return super .createPage(webResponse, webWindow);
641:                    }
642:                };
643:                webClient.setPageCreator(pageCreator);
644:            }
645:
646:            private static BrowserVersion setupBrowserVersion(
647:                    final String strUserAgent) {
648:                final BrowserVersion browserVersion;
649:
650:                if (strUserAgent == null) {
651:                    browserVersion = BrowserVersion.INTERNET_EXPLORER_6_0;
652:                    LOG.info("Surfing with browser "
653:                            + browserVersion.getUserAgent());
654:                } else {
655:                    // as long as all browser properties are not configurable from the task,
656:                    // use a "base" browser
657:                    final BrowserVersion baseBrowser;
658:
659:                    if (strUserAgent.indexOf("Gecko") != -1) {
660:                        baseBrowser = BrowserVersion.FIREFOX_2;
661:                    } else if (strUserAgent.indexOf(BrowserVersion.NETSCAPE) != -1) {
662:                        baseBrowser = new BrowserVersion(
663:                                BrowserVersion.NETSCAPE,
664:                                "5.0 (Windows; en-US)",
665:                                "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US;rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3",
666:                                "1.2", 6);
667:                    } else {
668:                        baseBrowser = BrowserVersion.INTERNET_EXPLORER_6_0;
669:                    }
670:
671:                    browserVersion = new BrowserVersion(baseBrowser
672:                            .getApplicationName(), baseBrowser
673:                            .getApplicationVersion(), strUserAgent, baseBrowser
674:                            .getJavaScriptVersion(), baseBrowser
675:                            .getBrowserVersionNumeric());
676:                    LOG
677:                            .info("Using browser version ("
678:                                    + browserVersion.getApplicationName()
679:                                    + ", "
680:                                    + browserVersion.getApplicationVersion()
681:                                    + ", "
682:                                    + strUserAgent
683:                                    + ", "
684:                                    + browserVersion.getJavaScriptVersion()
685:                                    + ", "
686:                                    + browserVersion.getBrowserVersionNumeric()
687:                                    + "). If the javascript support is not as expected, then it's time to go into the sources");
688:                }
689:                return browserVersion;
690:            }
691:
692:            // Paul Devine 4/12/2005: adding proxy support (for now only UsernamePasswordCredentials. For a proxy
693:            // that does not require authentication the credentials will not be consulted anyway, so it's ok to
694:            // leave user/password null or blank in those situations.)
695:            // package protected for testing purposes
696:            static WebClient setupWebClient(final BrowserVersion browserVersion) {
697:                final WebClient webClient;
698:                final DefaultCredentialsProvider credentialProvider = new DefaultCredentialsProvider();
699:                String proxyHost = System.getProperty("http.proxyHost");
700:                if (proxyHost != null && proxyHost.length() > 0) {
701:                    // the properties are set for instance by org.apache.tools.ant.taskdefs.optional.net.SetProxy
702:
703:                    // the proxy setting
704:                    final int proxyPort = Integer.parseInt(System.getProperty(
705:                            "http.proxyPort", "80"));
706:                    LOG
707:                            .info("Configuring proxy from http.proxyHost* system properties: "
708:                                    + proxyHost + ":" + proxyPort);
709:                    webClient = new WebClient(browserVersion, proxyHost,
710:                            proxyPort);
711:
712:                    configureProxy(webClient, credentialProvider);
713:                } else {
714:                    webClient = new WebClient(browserVersion);
715:                }
716:
717:                webClient.setCredentialsProvider(credentialProvider);
718:
719:                return webClient;
720:            }
721:
722:            /**
723:             * Configures the proxy settings from the system properties
724:             */
725:            static void configureProxy(final WebClient webClient,
726:                    final DefaultCredentialsProvider credentialProvider) {
727:                // the non proxy hosts if any
728:                final String nonProxyHostsSetting = System
729:                        .getProperty("http.nonProxyHosts");
730:                LOG
731:                        .info("Configuring proxy from http.nonProxyHosts system property: "
732:                                + nonProxyHostsSetting);
733:                if (nonProxyHostsSetting != null) {
734:                    final String[] nonProxyHosts = nonProxyHostsSetting
735:                            .split("\\|");
736:                    for (int i = 0; i < nonProxyHosts.length; ++i) {
737:                        String nonProxyHost = nonProxyHosts[i];
738:                        nonProxyHost = nonProxyHost.replaceAll("\\.", "\\\\."); // escape "."
739:                        nonProxyHost = nonProxyHost.replaceAll("\\*", ".*"); // give regex meaning to *
740:                        LOG.debug("addHostsToProxyBypass: >" + nonProxyHost
741:                                + "<");
742:                        webClient.addHostsToProxyBypass(nonProxyHost);
743:                    }
744:                }
745:
746:                // does the proxy need authentification?
747:                if (System.getProperty("http.proxyUser") != null) {
748:                    final String proxyUser = System
749:                            .getProperty("http.proxyUser");
750:                    final String proxyPassword = System
751:                            .getProperty("http.proxyPassword");
752:                    LOG
753:                            .info("Configuring proxy credentials from http.proxyHost* system properties: "
754:                                    + proxyUser + ", " + proxyPassword);
755:                    credentialProvider.addProxyCredentials(proxyUser,
756:                            proxyPassword);
757:                }
758:            }
759:
760:            private static void setupHtmlParser(final WebClient webClient,
761:                    final Configuration cfg) {// Sets a collector to catch parser warnings in order to report
762:                // misformed/invalid HTML in responses
763:                if (cfg.isShowHtmlParserOutput()) {
764:                    webClient
765:                            .setHTMLParserListener(new HtmlParserMessage.MessageCollector());
766:                    LOG
767:                            .debug("Configured a parser listener to collect messages generated while parsing html");
768:                } else {
769:                    LOG
770:                            .debug("showHtmlParserOutput is off, no listener configured");
771:                }
772:            }
773:
774:            private static void setupRefreshHandler(final WebClient webClient,
775:                    final Configuration cfg) {
776:                final boolean bUseDelay;
777:                final boolean bRefreshAll;
778:                final int acceptedRefreshDelay;
779:                if (cfg.getAutoRefresh().matches("\\d+")) {
780:                    bUseDelay = true;
781:                    bRefreshAll = false;
782:                    acceptedRefreshDelay = Integer.parseInt(cfg
783:                            .getAutoRefresh());
784:                } else {
785:                    bUseDelay = false;
786:                    bRefreshAll = Project.toBoolean(cfg.getAutoRefresh());
787:                    acceptedRefreshDelay = 0;
788:                }
789:
790:                LOG.debug("Configuring RefreshHandler (refreshAll: "
791:                        + bRefreshAll + ", useDelay: " + bUseDelay
792:                        + ", refreshDelay: " + acceptedRefreshDelay);
793:                final RefreshHandler refreshHandler = new RefreshHandler() {
794:                    public void handleRefresh(final Page page, final URL url,
795:                            final int iTimeBeforeRefresh) throws IOException {
796:                        final boolean bRefresh = bRefreshAll
797:                                || (bUseDelay && iTimeBeforeRefresh <= acceptedRefreshDelay);
798:                        if (bRefresh) {
799:                            LOG.info("Performing refresh to " + url
800:                                    + " (delay: " + iTimeBeforeRefresh
801:                                    + ") according to configuration");
802:                            final WebWindow window = page.getEnclosingWindow();
803:                            if (window == null) {
804:                                return;
805:                            }
806:                            final WebClient client = window.getWebClient();
807:                            client.getPage(window, new WebRequestSettings(url));
808:                        } else {
809:                            LOG.info("no refresh performed to " + url
810:                                    + " (delay: " + iTimeBeforeRefresh
811:                                    + ") according to configuration");
812:                        }
813:                    }
814:
815:                };
816:
817:                webClient.setRefreshHandler(refreshHandler);
818:            }
819:
820:            /**
821:             * Sets the http headers configured through the &lt;header/&gt; subelements of
822:             * &lt;config&gt;
823:             */
824:            private static void setupHttpHeaders(final WebClient webClient,
825:                    final Configuration cfg) {
826:                if (cfg.getHeaderList().size() > 0) {
827:                    LOG.info("Configuring " + cfg.getHeaderList().size()
828:                            + " HTTP header field(s)");
829:                }
830:                for (final Iterator iter = cfg.getHeaderList().iterator(); iter
831:                        .hasNext();) {
832:                    final Header header = (Header) iter.next();
833:
834:                    if ("User-Agent".equals(header.getName())) {
835:                        LOG
836:                                .info("Skipped User-Agent header as it has already been configured in the BrowserVersion");
837:                    } else {
838:                        webClient.addRequestHeader(header.getName(), header
839:                                .getValue());
840:                        LOG.info("Configured header \"" + header.getName()
841:                                + "\": " + header.getValue());
842:                    }
843:                }
844:            }
845:
846:            /**
847:             * Prepares the underlying browser client using option subelements
848:             * in the config. Currently calls setXXX methods in the WebClient
849:             * API. See the HtmlUnit JavaDocs for more details.
850:             */
851:            private static void setupOptions(final WebClient webClient,
852:                    final Configuration cfg) {
853:                final List options = cfg.getOptionList();
854:                for (Iterator iter = options.iterator(); iter.hasNext();) {
855:                    final Option option = (Option) iter.next();
856:                    boolean found = tryBooleanCallingMethod(option, webClient);
857:                    if (!found) {
858:                        found = tryIntCallingMethod(option, webClient);
859:                    }
860:                    if (!found) {
861:                        LOG.warn("Unknown option <" + option.getName()
862:                                + ">. Ignored.");
863:                    }
864:                }
865:            }
866:
867:            /**
868:             * Invokes a setXXX method in response to an option subelement
869:             * in the config named 'XXX'. Currently only boolean values are supported.
870:             *
871:             * @param option
872:             * @param optionObject
873:             * @return <code>true</code> if option has been successfully set
874:             */
875:            private static boolean tryBooleanCallingMethod(final Option option,
876:                    final Object optionObject) {
877:                final Class[] booleanClass = { boolean.class };
878:                try {
879:                    tryCallMethod(optionObject, option, booleanClass,
880:                            new Object[] { Boolean.valueOf(option.getValue()) });
881:                    return true;
882:                } catch (Exception e) {
883:                    LOG.info("Exception while trying to set boolean option: "
884:                            + e.getMessage());
885:                    return false;
886:                }
887:            }
888:
889:            /**
890:             * Invokes a setXXX method in response to an option subelement
891:             * in the config named 'XXX'. Currently only boolean values are supported.
892:             *
893:             * @param option
894:             * @param optionObject
895:             * @return <code>true</code> if option has been successfully set
896:             */
897:            private static boolean tryIntCallingMethod(final Option option,
898:                    final Object optionObject) {
899:                final Class[] intClass = { int.class };
900:                try {
901:                    tryCallMethod(optionObject, option, intClass,
902:                            new Object[] { Integer.valueOf(option.getValue()) });
903:                    return true;
904:                } catch (Exception e) {
905:                    LOG.info("Exception while trying to set integer option: "
906:                            + e.getMessage());
907:                    return false;
908:                }
909:            }
910:
911:            private static void tryCallMethod(final Object optionObject,
912:                    final Option option, final Class[] typeSpec,
913:                    final Object[] params) throws Exception {
914:                final Method method = optionObject.getClass()
915:                        .getDeclaredMethod("set" + option.getName(), typeSpec);
916:                method.invoke(optionObject, params);
917:                LOG.info("set option <" + option.getName() + "> to value <"
918:                        + option.getValue() + ">");
919:            }
920:
921:            /**
922:             * Gets the timeout in seconds
923:             * @return the timeout (default value is {@link #DEFAULT_TIMEOUT}).
924:             */
925:            public int getTimeout() {
926:                return fTimeout;
927:            }
928:
929:            /**
930:             * Sets the timeout
931:             * @param timeout the new value (in seconds), set <code>0</code> for no timeout
932:             */
933:            public void setTimeout(final int timeout) {
934:                fTimeout = timeout;
935:            }
936:
937:            /**
938:             * Indicates if WebTest should wait for completion of background js tasks after each step.
939:             * This should become true per default once HtmlUnit has the necessary functionality to
940:             * control this which is not yet the case with HtmlUnit 1.14.
941:             * This feature is intentionally undocumented.
942:             * @param b the new value
943:             */
944:            public void setEasyAjax(final boolean b) {
945:                fEasyAjax = b;
946:            }
947:
948:            public boolean isEasyAjax() {
949:                return fEasyAjax;
950:            }
951:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.