Source Code Cross Referenced for HTTPSamplerBase.java in  » Testing » jakarta-jmeter » org » apache » jmeter » protocol » http » sampler » 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 » jakarta jmeter » org.apache.jmeter.protocol.http.sampler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *   http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:        package org.apache.jmeter.protocol.http.sampler;
0018:
0019:        import java.io.ByteArrayOutputStream;
0020:        import java.io.FileReader;
0021:        import java.io.IOException;
0022:        import java.io.PrintStream;
0023:        import java.io.UnsupportedEncodingException;
0024:        import java.net.MalformedURLException;
0025:        import java.net.URI;
0026:        import java.net.URISyntaxException;
0027:        import java.net.URL;
0028:        import java.util.Arrays;
0029:        import java.util.Collections;
0030:        import java.util.HashMap;
0031:        import java.util.Iterator;
0032:        import java.util.List;
0033:        import java.util.Map;
0034:
0035:        import org.apache.commons.io.IOUtils;
0036:        import org.apache.jmeter.config.Argument;
0037:        import org.apache.jmeter.config.Arguments;
0038:        import org.apache.jmeter.engine.event.LoopIterationEvent;
0039:        import org.apache.jmeter.protocol.http.control.AuthManager;
0040:        import org.apache.jmeter.protocol.http.control.CookieManager;
0041:        import org.apache.jmeter.protocol.http.control.HeaderManager;
0042:        import org.apache.jmeter.protocol.http.parser.HTMLParseException;
0043:        import org.apache.jmeter.protocol.http.parser.HTMLParser;
0044:        import org.apache.jmeter.protocol.http.util.EncoderCache;
0045:        import org.apache.jmeter.protocol.http.util.HTTPArgument;
0046:        import org.apache.jmeter.protocol.http.util.HTTPConstantsInterface;
0047:        import org.apache.jmeter.samplers.AbstractSampler;
0048:        import org.apache.jmeter.samplers.Entry;
0049:        import org.apache.jmeter.samplers.SampleResult;
0050:        import org.apache.jmeter.testelement.TestElement;
0051:        import org.apache.jmeter.testelement.TestListener;
0052:        import org.apache.jmeter.testelement.ThreadListener;
0053:        import org.apache.jmeter.testelement.property.BooleanProperty;
0054:        import org.apache.jmeter.testelement.property.IntegerProperty;
0055:        import org.apache.jmeter.testelement.property.JMeterProperty;
0056:        import org.apache.jmeter.testelement.property.PropertyIterator;
0057:        import org.apache.jmeter.testelement.property.StringProperty;
0058:        import org.apache.jmeter.testelement.property.TestElementProperty;
0059:        import org.apache.jmeter.util.JMeterUtils;
0060:        import org.apache.jorphan.logging.LoggingManager;
0061:        import org.apache.jorphan.util.JOrphanUtils;
0062:        import org.apache.log.Logger;
0063:        import org.apache.oro.text.MalformedCachePatternException;
0064:        import org.apache.oro.text.regex.Pattern;
0065:        import org.apache.oro.text.regex.Perl5Matcher;
0066:
0067:        /**
0068:         * Common constants and methods for HTTP samplers
0069:         * 
0070:         */
0071:        public abstract class HTTPSamplerBase extends AbstractSampler implements 
0072:                TestListener, ThreadListener, HTTPConstantsInterface {
0073:
0074:            private static final Logger log = LoggingManager
0075:                    .getLoggerForClass();
0076:
0077:            public final static String ARGUMENTS = "HTTPsampler.Arguments"; // $NON-NLS-1$
0078:
0079:            public final static String AUTH_MANAGER = "HTTPSampler.auth_manager"; // $NON-NLS-1$
0080:
0081:            public final static String COOKIE_MANAGER = "HTTPSampler.cookie_manager"; // $NON-NLS-1$
0082:
0083:            public final static String HEADER_MANAGER = "HTTPSampler.header_manager"; // $NON-NLS-1$
0084:
0085:            public final static String MIMETYPE = "HTTPSampler.mimetype"; // $NON-NLS-1$
0086:
0087:            public final static String DOMAIN = "HTTPSampler.domain"; // $NON-NLS-1$
0088:
0089:            public final static String PORT = "HTTPSampler.port"; // $NON-NLS-1$
0090:
0091:            public final static String METHOD = "HTTPSampler.method"; // $NON-NLS-1$
0092:
0093:            public final static String CONTENT_ENCODING = "HTTPSampler.contentEncoding"; // $NON-NLS-1$
0094:
0095:            public final static String IMPLEMENTATION = "HTTPSampler.implementation"; // $NON-NLS-1$
0096:
0097:            public final static String PATH = "HTTPSampler.path"; // $NON-NLS-1$
0098:
0099:            public final static String FOLLOW_REDIRECTS = "HTTPSampler.follow_redirects"; // $NON-NLS-1$
0100:
0101:            public final static String AUTO_REDIRECTS = "HTTPSampler.auto_redirects"; // $NON-NLS-1$
0102:
0103:            public final static String PROTOCOL = "HTTPSampler.protocol"; // $NON-NLS-1$
0104:
0105:            private static final String PROTOCOL_FILE = "file"; // $NON-NLS-1$
0106:
0107:            private final static String DEFAULT_PROTOCOL = PROTOCOL_HTTP;
0108:
0109:            public final static String URL = "HTTPSampler.URL"; // $NON-NLS-1$
0110:
0111:            public static final String CLIENT = "HTTPSampler.client"; // $NON-NLS-1$
0112:
0113:            public final static String DEFAULT_METHOD = GET; // $NON-NLS-1$
0114:            // Supported methods:
0115:            private final static String[] METHODS = { DEFAULT_METHOD, // i.e. GET
0116:                    POST, HEAD, PUT, OPTIONS, TRACE, DELETE, };
0117:
0118:            private final static List METHODLIST = Collections
0119:                    .unmodifiableList(Arrays.asList(METHODS));
0120:
0121:            public final static String USE_KEEPALIVE = "HTTPSampler.use_keepalive"; // $NON-NLS-1$
0122:
0123:            public final static String FILE_NAME = "HTTPSampler.FILE_NAME"; // $NON-NLS-1$
0124:
0125:            public final static String DO_MULTIPART_POST = "HTTPSampler.DO_MULTIPART_POST"; // $NON-NLS-1$
0126:
0127:            /* Shown as Parameter Name on the GUI */
0128:            public final static String FILE_FIELD = "HTTPSampler.FILE_FIELD"; // $NON-NLS-1$
0129:
0130:            //	public final static String FILE_DATA = "HTTPSampler.FILE_DATA"; // $NON-NLS-1$
0131:
0132:            //	public final static String FILE_MIMETYPE = "HTTPSampler.FILE_MIMETYPE"; // $NON-NLS-1$
0133:
0134:            public final static String CONTENT_TYPE = "HTTPSampler.CONTENT_TYPE"; // $NON-NLS-1$
0135:
0136:            //	public final static String NORMAL_FORM = "normal_form"; // $NON-NLS-1$
0137:
0138:            //	public final static String MULTIPART_FORM = "multipart_form"; // $NON-NLS-1$
0139:
0140:            // public final static String ENCODED_PATH= "HTTPSampler.encoded_path";
0141:
0142:            // IMAGE_PARSER now really means EMBEDDED_PARSER
0143:            public final static String IMAGE_PARSER = "HTTPSampler.image_parser"; // $NON-NLS-1$
0144:
0145:            // Embedded URLs must match this RE (if provided)
0146:            public final static String EMBEDDED_URL_RE = "HTTPSampler.embedded_url_re"; // $NON-NLS-1$
0147:
0148:            public final static String MONITOR = "HTTPSampler.monitor"; // $NON-NLS-1$
0149:
0150:            /** A number to indicate that the port has not been set. * */
0151:            public static final int UNSPECIFIED_PORT = 0;
0152:            public static final String UNSPECIFIED_PORT_AS_STRING = "0"; // $NON-NLS-1$
0153:
0154:            protected final static String NON_HTTP_RESPONSE_CODE = "Non HTTP response code";
0155:
0156:            protected final static String NON_HTTP_RESPONSE_MESSAGE = "Non HTTP response message";
0157:
0158:            private static final String ARG_VAL_SEP = "="; // $NON-NLS-1$
0159:
0160:            private static final String QRY_SEP = "&"; // $NON-NLS-1$
0161:
0162:            private static final String QRY_PFX = "?"; // $NON-NLS-1$
0163:
0164:            protected static final int MAX_REDIRECTS = JMeterUtils
0165:                    .getPropDefault("httpsampler.max_redirects", 5); // $NON-NLS-1$
0166:
0167:            protected static final int MAX_FRAME_DEPTH = JMeterUtils
0168:                    .getPropDefault("httpsampler.max_frame_depth", 5); // $NON-NLS-1$
0169:
0170:            // Derive the mapping of content types to parsers
0171:            private static Map parsersForType = new HashMap();
0172:            // Not synch, but it is not modified after creation
0173:
0174:            private static final String RESPONSE_PARSERS = // list of parsers
0175:            JMeterUtils.getProperty("HTTPResponse.parsers");//$NON-NLS-1$
0176:
0177:            static {
0178:                String[] parsers = JOrphanUtils.split(RESPONSE_PARSERS, " ",
0179:                        true);// returns empty array for null
0180:                for (int i = 0; i < parsers.length; i++) {
0181:                    final String parser = parsers[i];
0182:                    String classname = JMeterUtils.getProperty(parser
0183:                            + ".className");//$NON-NLS-1$
0184:                    if (classname == null) {
0185:                        log.info("Cannot find .className property for "
0186:                                + parser + ", using default");
0187:                        classname = "";
0188:                    }
0189:                    String typelist = JMeterUtils
0190:                            .getProperty(parser + ".types");//$NON-NLS-1$
0191:                    if (typelist != null) {
0192:                        String[] types = JOrphanUtils
0193:                                .split(typelist, " ", true);
0194:                        for (int j = 0; j < types.length; j++) {
0195:                            final String type = types[j];
0196:                            log.info("Parser for " + type + " is " + classname);
0197:                            parsersForType.put(type, classname);
0198:                        }
0199:                    } else {
0200:                        log.warn("Cannot find .types property for " + parser);
0201:                    }
0202:                }
0203:                if (parsers.length == 0) { // revert to previous behaviour
0204:                    parsersForType.put("text/html", ""); //$NON-NLS-1$ //$NON-NLS-2$
0205:                    log
0206:                            .info("No response parsers defined: text/html only will be scanned for embedded resources");
0207:                }
0208:            }
0209:
0210:            ////////////////////// Variables //////////////////////
0211:
0212:            private boolean dynamicPath = false;// Set false if spaces are already encoded
0213:
0214:            ////////////////////// Code ///////////////////////////
0215:
0216:            public HTTPSamplerBase() {
0217:                setArguments(new Arguments());
0218:            }
0219:
0220:            /**
0221:             * The name parameter to be applied to the file
0222:             */
0223:            public void setFileField(String value) {
0224:                setProperty(FILE_FIELD, value);
0225:            }
0226:
0227:            /**
0228:             * The name parameter to be applied to the file
0229:             */
0230:            public String getFileField() {
0231:                return getPropertyAsString(FILE_FIELD);
0232:            }
0233:
0234:            /**
0235:             * The actual name of the file to POST
0236:             */
0237:            public void setFilename(String value) {
0238:                setProperty(FILE_NAME, value);
0239:            }
0240:
0241:            /**
0242:             * The actual name of the file to POST
0243:             */
0244:            public String getFilename() {
0245:                return getPropertyAsString(FILE_NAME);
0246:            }
0247:
0248:            /**
0249:             * Determine if the file should be sent as the entire Post body,
0250:             * i.e. without any additional wrapping
0251:             * 
0252:             * @return true if specified file is to be sent as the body,
0253:             * i.e. FileField is blank
0254:             */
0255:            public boolean getSendFileAsPostBody() {
0256:                // If no file field is specified, the file is sent as post body
0257:                return getFileField().length() == 0
0258:                        && getFilename().length() > 0;
0259:            }
0260:
0261:            /**
0262:             * Determine if none of the parameters have a name, and if that
0263:             * is the case, it means that the parameter values should be sent
0264:             * as the post body
0265:             * 
0266:             * @return true if none of the parameters have a name specified
0267:             */
0268:            public boolean getSendParameterValuesAsPostBody() {
0269:                boolean noArgumentsHasName = true;
0270:                PropertyIterator args = getArguments().iterator();
0271:                while (args.hasNext()) {
0272:                    HTTPArgument arg = (HTTPArgument) args.next()
0273:                            .getObjectValue();
0274:                    if (arg.getName() != null && arg.getName().length() > 0) {
0275:                        noArgumentsHasName = false;
0276:                        break;
0277:                    }
0278:                }
0279:                return noArgumentsHasName;
0280:            }
0281:
0282:            /**
0283:             * Determine if we should use multipart/form-data or 
0284:             * application/x-www-form-urlencoded for the post
0285:             * 
0286:             * @return true if multipart/form-data should be used and method is POST
0287:             */
0288:            public boolean getUseMultipartForPost() {
0289:                // We use multipart if we have been told so, or files are present
0290:                // and the files should not be send as the post body
0291:                if (POST.equals(getMethod())
0292:                        && (getDoMultipartPost() || (hasUploadableFiles() && !getSendFileAsPostBody()))) {
0293:                    return true;
0294:                } else {
0295:                    return false;
0296:                }
0297:            }
0298:
0299:            public void setProtocol(String value) {
0300:                setProperty(PROTOCOL, value.toLowerCase());
0301:            }
0302:
0303:            public String getProtocol() {
0304:                String protocol = getPropertyAsString(PROTOCOL);
0305:                if (protocol == null || protocol.length() == 0) {
0306:                    return DEFAULT_PROTOCOL;
0307:                }
0308:                return protocol;
0309:            }
0310:
0311:            public String getClient() {// TODO should it have a default?
0312:                return getPropertyAsString(CLIENT);
0313:            }
0314:
0315:            public void setClient(String client) {
0316:                setProperty(CLIENT, client);
0317:            }
0318:
0319:            /**
0320:             * Sets the Path attribute of the UrlConfig object Also calls parseArguments
0321:             * to extract and store any query arguments
0322:             * 
0323:             * @param path
0324:             *            The new Path value
0325:             */
0326:            public void setPath(String path) {
0327:                // We know that URL arguments should always be encoded in UTF-8 according to spec
0328:                setPath(path, EncoderCache.URL_ARGUMENT_ENCODING);
0329:            }
0330:
0331:            /**
0332:             * Sets the Path attribute of the UrlConfig object Also calls parseArguments
0333:             * to extract and store any query arguments
0334:             * 
0335:             * @param path
0336:             *            The new Path value
0337:             * @param contentEncoding
0338:             *            The encoding used for the querystring parameter values
0339:             */
0340:            public void setPath(String path, String contentEncoding) {
0341:                if (GET.equals(getMethod()) || DELETE.equals(getMethod())) {
0342:                    int index = path.indexOf(QRY_PFX);
0343:                    if (index > -1) {
0344:                        setProperty(PATH, path.substring(0, index));
0345:                        // Parse the arguments in querystring, assuming specified encoding for values
0346:                        parseArguments(path.substring(index + 1),
0347:                                contentEncoding);
0348:                    } else {
0349:                        setProperty(PATH, path);
0350:                    }
0351:                } else {
0352:                    setProperty(PATH, path);
0353:                }
0354:            }
0355:
0356:            public String getPath() {
0357:                String p = getPropertyAsString(PATH);
0358:                if (dynamicPath) {
0359:                    return encodeSpaces(p);
0360:                }
0361:                return p;
0362:            }
0363:
0364:            public void setFollowRedirects(boolean value) {
0365:                setProperty(new BooleanProperty(FOLLOW_REDIRECTS, value));
0366:            }
0367:
0368:            public boolean getFollowRedirects() {
0369:                return getPropertyAsBoolean(FOLLOW_REDIRECTS);
0370:            }
0371:
0372:            public void setAutoRedirects(boolean value) {
0373:                setProperty(new BooleanProperty(AUTO_REDIRECTS, value));
0374:            }
0375:
0376:            public boolean getAutoRedirects() {
0377:                return getPropertyAsBoolean(AUTO_REDIRECTS);
0378:            }
0379:
0380:            public void setMethod(String value) {
0381:                setProperty(METHOD, value);
0382:            }
0383:
0384:            public String getMethod() {
0385:                return getPropertyAsString(METHOD);
0386:            }
0387:
0388:            public void setContentEncoding(String value) {
0389:                setProperty(CONTENT_ENCODING, value);
0390:            }
0391:
0392:            public String getContentEncoding() {
0393:                return getPropertyAsString(CONTENT_ENCODING);
0394:            }
0395:
0396:            public void setUseKeepAlive(boolean value) {
0397:                setProperty(new BooleanProperty(USE_KEEPALIVE, value));
0398:            }
0399:
0400:            public boolean getUseKeepAlive() {
0401:                return getPropertyAsBoolean(USE_KEEPALIVE);
0402:            }
0403:
0404:            public void setDoMultipartPost(boolean value) {
0405:                setProperty(new BooleanProperty(DO_MULTIPART_POST, value));
0406:            }
0407:
0408:            public boolean getDoMultipartPost() {
0409:                return getPropertyAsBoolean(DO_MULTIPART_POST, false);
0410:            }
0411:
0412:            public void setMonitor(String value) {
0413:                this .setProperty(MONITOR, value);
0414:            }
0415:
0416:            public void setMonitor(boolean truth) {
0417:                this .setProperty(MONITOR, truth);
0418:            }
0419:
0420:            public String getMonitor() {
0421:                return this .getPropertyAsString(MONITOR);
0422:            }
0423:
0424:            public boolean isMonitor() {
0425:                return this .getPropertyAsBoolean(MONITOR);
0426:            }
0427:
0428:            public void setImplementation(String value) {
0429:                this .setProperty(IMPLEMENTATION, value);
0430:            }
0431:
0432:            public String getImplementation() {
0433:                return this .getPropertyAsString(IMPLEMENTATION);
0434:            }
0435:
0436:            /**
0437:             * Add an argument which has already been encoded
0438:             */
0439:            public void addEncodedArgument(String name, String value) {
0440:                this .addEncodedArgument(name, value, ARG_VAL_SEP);
0441:            }
0442:
0443:            public void addEncodedArgument(String name, String value,
0444:                    String metaData, String contentEncoding) {
0445:                if (log.isDebugEnabled()) {
0446:                    log.debug("adding argument: name: " + name + " value: "
0447:                            + value + " metaData: " + metaData
0448:                            + " contentEncoding: " + contentEncoding);
0449:                }
0450:
0451:                HTTPArgument arg = null;
0452:                if (contentEncoding != null) {
0453:                    arg = new HTTPArgument(name, value, metaData, true,
0454:                            contentEncoding);
0455:                } else {
0456:                    arg = new HTTPArgument(name, value, metaData, true);
0457:                }
0458:
0459:                // Check if there are any difference between name and value and their encoded name and value
0460:                String valueEncoded = null;
0461:                if (contentEncoding != null) {
0462:                    try {
0463:                        valueEncoded = arg.getEncodedValue(contentEncoding);
0464:                    } catch (UnsupportedEncodingException e) {
0465:                        log.warn("Unable to get encoded value using encoding "
0466:                                + contentEncoding);
0467:                        valueEncoded = arg.getEncodedValue();
0468:                    }
0469:                } else {
0470:                    valueEncoded = arg.getEncodedValue();
0471:                }
0472:                // If there is no difference, we mark it as not needing encoding
0473:                if (arg.getName().equals(arg.getEncodedName())
0474:                        && arg.getValue().equals(valueEncoded)) {
0475:                    arg.setAlwaysEncoded(false);
0476:                }
0477:                this .getArguments().addArgument(arg);
0478:            }
0479:
0480:            public void addEncodedArgument(String name, String value,
0481:                    String metaData) {
0482:                this .addEncodedArgument(name, value, metaData, null);
0483:            }
0484:
0485:            public void addNonEncodedArgument(String name, String value,
0486:                    String metadata) {
0487:                HTTPArgument arg = new HTTPArgument(name, value, metadata,
0488:                        false);
0489:                arg.setAlwaysEncoded(false);
0490:                this .getArguments().addArgument(arg);
0491:            }
0492:
0493:            public void addArgument(String name, String value) {
0494:                this .getArguments().addArgument(new HTTPArgument(name, value));
0495:            }
0496:
0497:            public void addArgument(String name, String value, String metadata) {
0498:                this .getArguments().addArgument(
0499:                        new HTTPArgument(name, value, metadata));
0500:            }
0501:
0502:            public boolean hasArguments() {
0503:                return getArguments().getArgumentCount() > 0;
0504:            }
0505:
0506:            public void addTestElement(TestElement el) {
0507:                if (el instanceof  CookieManager) {
0508:                    setCookieManager((CookieManager) el);
0509:                } else if (el instanceof  HeaderManager) {
0510:                    setHeaderManager((HeaderManager) el);
0511:                } else if (el instanceof  AuthManager) {
0512:                    setAuthManager((AuthManager) el);
0513:                } else {
0514:                    super .addTestElement(el);
0515:                }
0516:            }
0517:
0518:            public void setPort(int value) {
0519:                setProperty(new IntegerProperty(PORT, value));
0520:            }
0521:
0522:            public static int getDefaultPort(String protocol, int port) {
0523:                if (port == -1) {
0524:                    return protocol.equalsIgnoreCase(PROTOCOL_HTTP) ? DEFAULT_HTTP_PORT
0525:                            : protocol.equalsIgnoreCase(PROTOCOL_HTTPS) ? DEFAULT_HTTPS_PORT
0526:                                    : port;
0527:                }
0528:                return port;
0529:            }
0530:
0531:            /**
0532:             * Tell whether the default port for the specified protocol is used
0533:             * 
0534:             * @return true if the default port number for the protocol is used, false otherwise
0535:             */
0536:            public boolean isProtocolDefaultPort() {
0537:                final int port = getPropertyAsInt(PORT);
0538:                final String protocol = getProtocol();
0539:                if (port == UNSPECIFIED_PORT
0540:                        || (PROTOCOL_HTTP.equalsIgnoreCase(protocol) && port == DEFAULT_HTTP_PORT)
0541:                        || (PROTOCOL_HTTPS.equalsIgnoreCase(protocol) && port == DEFAULT_HTTPS_PORT)) {
0542:                    return true;
0543:                } else {
0544:                    return false;
0545:                }
0546:            }
0547:
0548:            public int getPort() {
0549:                int port = getPropertyAsInt(PORT);
0550:                if (port == UNSPECIFIED_PORT) {
0551:                    String prot = getProtocol();
0552:                    if (PROTOCOL_HTTPS.equalsIgnoreCase(prot)) {
0553:                        return DEFAULT_HTTPS_PORT;
0554:                    }
0555:                    if (!PROTOCOL_HTTP.equalsIgnoreCase(prot)) {
0556:                        log.warn("Unexpected protocol: " + prot);
0557:                        // TODO - should this return something else?
0558:                    }
0559:                    return DEFAULT_HTTP_PORT;
0560:                }
0561:                return port;
0562:            }
0563:
0564:            public void setDomain(String value) {
0565:                setProperty(DOMAIN, value);
0566:            }
0567:
0568:            public String getDomain() {
0569:                return getPropertyAsString(DOMAIN);
0570:            }
0571:
0572:            public void setArguments(Arguments value) {
0573:                setProperty(new TestElementProperty(ARGUMENTS, value));
0574:            }
0575:
0576:            public Arguments getArguments() {
0577:                return (Arguments) getProperty(ARGUMENTS).getObjectValue();
0578:            }
0579:
0580:            public void setAuthManager(AuthManager value) {
0581:                AuthManager mgr = getAuthManager();
0582:                if (mgr != null) {
0583:                    log.warn("Existing Manager " + mgr.getName()
0584:                            + " superseded by " + value.getName());
0585:                }
0586:                setProperty(new TestElementProperty(AUTH_MANAGER, value));
0587:            }
0588:
0589:            public AuthManager getAuthManager() {
0590:                return (AuthManager) getProperty(AUTH_MANAGER).getObjectValue();
0591:            }
0592:
0593:            public void setHeaderManager(HeaderManager value) {
0594:                HeaderManager mgr = getHeaderManager();
0595:                if (mgr != null) {
0596:                    log.warn("Existing Manager " + mgr.getName()
0597:                            + " superseded by " + value.getName());
0598:                }
0599:                setProperty(new TestElementProperty(HEADER_MANAGER, value));
0600:            }
0601:
0602:            public HeaderManager getHeaderManager() {
0603:                return (HeaderManager) getProperty(HEADER_MANAGER)
0604:                        .getObjectValue();
0605:            }
0606:
0607:            public void setCookieManager(CookieManager value) {
0608:                CookieManager mgr = getCookieManager();
0609:                if (mgr != null) {
0610:                    log.warn("Existing Manager " + mgr.getName()
0611:                            + " superseded by " + value.getName());
0612:                }
0613:                setProperty(new TestElementProperty(COOKIE_MANAGER, value));
0614:            }
0615:
0616:            public CookieManager getCookieManager() {
0617:                return (CookieManager) getProperty(COOKIE_MANAGER)
0618:                        .getObjectValue();
0619:            }
0620:
0621:            public void setMimetype(String value) {
0622:                setProperty(MIMETYPE, value);
0623:            }
0624:
0625:            public String getMimetype() {
0626:                return getPropertyAsString(MIMETYPE);
0627:            }
0628:
0629:            public boolean isImageParser() {
0630:                return getPropertyAsBoolean(IMAGE_PARSER);
0631:            }
0632:
0633:            public void setImageParser(boolean parseImages) {
0634:                setProperty(new BooleanProperty(IMAGE_PARSER, parseImages));
0635:            }
0636:
0637:            /**
0638:             * Get the regular expression URLs must match.
0639:             * 
0640:             * @return regular expression (or empty) string
0641:             */
0642:            public String getEmbeddedUrlRE() {
0643:                return getPropertyAsString(EMBEDDED_URL_RE, "");
0644:            }
0645:
0646:            public void setEmbeddedUrlRE(String regex) {
0647:                setProperty(new StringProperty(EMBEDDED_URL_RE, regex));
0648:            }
0649:
0650:            /**
0651:             * Obtain a result that will help inform the user that an error has occured
0652:             * during sampling, and how long it took to detect the error.
0653:             * 
0654:             * @param e
0655:             *            Exception representing the error.
0656:             * @param res
0657:             *            SampleResult
0658:             * @return a sampling result useful to inform the user about the exception.
0659:             */
0660:            protected HTTPSampleResult errorResult(Throwable e,
0661:                    HTTPSampleResult res) {
0662:                res.setSampleLabel("Error");
0663:                res.setDataType(HTTPSampleResult.TEXT);
0664:                ByteArrayOutputStream text = new ByteArrayOutputStream(200);
0665:                e.printStackTrace(new PrintStream(text));
0666:                res.setResponseData(text.toByteArray());
0667:                res.setResponseCode(NON_HTTP_RESPONSE_CODE + ": "
0668:                        + e.getClass().getName());
0669:                res.setResponseMessage(NON_HTTP_RESPONSE_MESSAGE + ": "
0670:                        + e.getMessage());
0671:                res.setSuccessful(false);
0672:                res.setMonitor(this .isMonitor());
0673:                return res;
0674:            }
0675:
0676:            /**
0677:             * Get the URL, built from its component parts.
0678:             * 
0679:             * @return The URL to be requested by this sampler.
0680:             * @throws MalformedURLException
0681:             */
0682:            public URL getUrl() throws MalformedURLException {
0683:                StringBuffer pathAndQuery = new StringBuffer(100);
0684:                String path = this .getPath();
0685:                if (!path.startsWith("/")) { // $NON-NLS-1$
0686:                    pathAndQuery.append("/"); // $NON-NLS-1$
0687:                }
0688:                pathAndQuery.append(path);
0689:
0690:                // Add the query string if it is a HTTP GET or DELETE request
0691:                if (GET.equals(getMethod()) || DELETE.equals(getMethod())) {
0692:                    // Get the query string encoded in specified encoding
0693:                    // If no encoding is specified by user, we will get it
0694:                    // encoded in UTF-8, which is what the HTTP spec says
0695:                    String queryString = getQueryString(getContentEncoding());
0696:                    if (queryString.length() > 0) {
0697:                        if (path.indexOf(QRY_PFX) > -1) {
0698:                            pathAndQuery.append(QRY_SEP);
0699:                        } else {
0700:                            pathAndQuery.append(QRY_PFX);
0701:                        }
0702:                        pathAndQuery.append(queryString);
0703:                    }
0704:                }
0705:                // If default port for protocol is used, we do not include port in URL
0706:                if (isProtocolDefaultPort()) {
0707:                    return new URL(getProtocol(), getDomain(), pathAndQuery
0708:                            .toString());
0709:                } else {
0710:                    return new URL(getProtocol(), getDomain(), getPort(),
0711:                            pathAndQuery.toString());
0712:                }
0713:            }
0714:
0715:            /**
0716:             * Gets the QueryString attribute of the UrlConfig object, using
0717:             * UTF-8 to encode the URL
0718:             * 
0719:             * @return the QueryString value
0720:             */
0721:            public String getQueryString() {
0722:                // We use the encoding which should be used according to the HTTP spec, which is UTF-8
0723:                return getQueryString(EncoderCache.URL_ARGUMENT_ENCODING);
0724:            }
0725:
0726:            /**
0727:             * Gets the QueryString attribute of the UrlConfig object, using the
0728:             * specified encoding to encode the parameter values put into the URL
0729:             * 
0730:             * @param contentEncoding the encoding to use for encoding parameter values
0731:             * @return the QueryString value
0732:             */
0733:            public String getQueryString(String contentEncoding) {
0734:                // Check if the sampler has a specified content encoding        
0735:                if (contentEncoding == null
0736:                        || contentEncoding.trim().length() == 0) {
0737:                    // We use the encoding which should be used according to the HTTP spec, which is UTF-8
0738:                    contentEncoding = EncoderCache.URL_ARGUMENT_ENCODING;
0739:                }
0740:                StringBuffer buf = new StringBuffer();
0741:                PropertyIterator iter = getArguments().iterator();
0742:                boolean first = true;
0743:                while (iter.hasNext()) {
0744:                    HTTPArgument item = null;
0745:                    /*
0746:                     * N.B. Revision 323346 introduced the ClassCast check, but then used iter.next()
0747:                     * to fetch the item to be cast, thus skipping the element that did not cast.
0748:                     * Reverted to work more like the original code, but with the check in place.
0749:                     * Added a warning message so can track whether it is necessary
0750:                     */
0751:                    Object objectValue = iter.next().getObjectValue();
0752:                    try {
0753:                        item = (HTTPArgument) objectValue;
0754:                    } catch (ClassCastException e) {
0755:                        log.warn("Unexpected argument type: "
0756:                                + objectValue.getClass().getName());
0757:                        item = new HTTPArgument((Argument) objectValue);
0758:                    }
0759:                    final String encodedName = item.getEncodedName();
0760:                    if (encodedName.length() == 0) {
0761:                        continue; // Skip parameters with a blank name (allows use of optional variables in parameter lists)
0762:                    }
0763:                    if (!first) {
0764:                        buf.append(QRY_SEP);
0765:                    } else {
0766:                        first = false;
0767:                    }
0768:                    buf.append(encodedName);
0769:                    if (item.getMetaData() == null) {
0770:                        buf.append(ARG_VAL_SEP);
0771:                    } else {
0772:                        buf.append(item.getMetaData());
0773:                    }
0774:
0775:                    // Encode the parameter value in the specified content encoding
0776:                    try {
0777:                        buf.append(item.getEncodedValue(contentEncoding));
0778:                    } catch (UnsupportedEncodingException e) {
0779:                        log
0780:                                .warn("Unable to encode parameter in encoding "
0781:                                        + contentEncoding
0782:                                        + ", parameter value not included in query string");
0783:                    }
0784:                }
0785:                return buf.toString();
0786:            }
0787:
0788:            // Mark Walsh 2002-08-03, modified to also parse a parameter name value
0789:            // string, where string contains only the parameter name and no equal sign.
0790:            /**
0791:             * This method allows a proxy server to send over the raw text from a
0792:             * browser's output stream to be parsed and stored correctly into the
0793:             * UrlConfig object.
0794:             * 
0795:             * For each name found, addArgument() is called
0796:             * 
0797:             * @param queryString -
0798:             *            the query string
0799:             * @param contentEncoding -
0800:             *            the content encoding of the query string. The query string might
0801:             *            actually be the post body of a http post request.
0802:             */
0803:            public void parseArguments(String queryString,
0804:                    String contentEncoding) {
0805:                String[] args = JOrphanUtils.split(queryString, QRY_SEP);
0806:                for (int i = 0; i < args.length; i++) {
0807:                    // need to handle four cases: 
0808:                    // - string contains name=value
0809:                    // - string contains name=
0810:                    // - string contains name
0811:                    // - empty string
0812:
0813:                    String metaData; // records the existance of an equal sign
0814:                    String name;
0815:                    String value;
0816:                    int length = args[i].length();
0817:                    int endOfNameIndex = args[i].indexOf(ARG_VAL_SEP);
0818:                    if (endOfNameIndex != -1) {// is there a separator?
0819:                        // case of name=value, name=
0820:                        metaData = ARG_VAL_SEP;
0821:                        name = args[i].substring(0, endOfNameIndex);
0822:                        value = args[i].substring(endOfNameIndex + 1, length);
0823:                    } else {
0824:                        metaData = "";
0825:                        name = args[i];
0826:                        value = "";
0827:                    }
0828:                    if (name.length() > 0) {
0829:                        // If we know the encoding, we can decode the argument value,
0830:                        // to make it easier to read for the user
0831:                        if (contentEncoding != null) {
0832:                            addEncodedArgument(name, value, metaData,
0833:                                    contentEncoding);
0834:                        } else {
0835:                            // If we do not know the encoding, we just use the encoded value
0836:                            // The browser has already done the encoding, so save the values as is
0837:                            addNonEncodedArgument(name, value, metaData);
0838:                        }
0839:                    }
0840:                }
0841:            }
0842:
0843:            public void parseArguments(String queryString) {
0844:                // We do not know the content encoding of the query string
0845:                parseArguments(queryString, null);
0846:            }
0847:
0848:            public String toString() {
0849:                try {
0850:                    StringBuffer stringBuffer = new StringBuffer();
0851:                    stringBuffer.append(this .getUrl().toString());
0852:                    // Append body if it is a post or put
0853:                    if (POST.equals(getMethod()) || PUT.equals(getMethod())) {
0854:                        stringBuffer.append("\nQuery Data: ");
0855:                        stringBuffer.append(getQueryString());
0856:                    }
0857:                    return stringBuffer.toString();
0858:                } catch (MalformedURLException e) {
0859:                    return "";
0860:                }
0861:            }
0862:
0863:            /**
0864:             * Do a sampling and return its results.
0865:             * 
0866:             * @param e
0867:             *            <code>Entry</code> to be sampled
0868:             * @return results of the sampling
0869:             */
0870:            public SampleResult sample(Entry e) {
0871:                return sample();
0872:            }
0873:
0874:            /**
0875:             * Perform a sample, and return the results
0876:             * 
0877:             * @return results of the sampling
0878:             */
0879:            public SampleResult sample() {
0880:                SampleResult res = null;
0881:                try {
0882:                    if (PROTOCOL_FILE.equalsIgnoreCase(getProtocol())) {
0883:                        res = fileSample(new URI(PROTOCOL_FILE, getPath(), null));
0884:                    } else {
0885:                        res = sample(getUrl(), getMethod(), false, 0);
0886:                    }
0887:                    res.setSampleLabel(getName());
0888:                    return res;
0889:                } catch (MalformedURLException e) {
0890:                    return errorResult(e, new HTTPSampleResult());
0891:                } catch (IOException e) {
0892:                    return errorResult(e, new HTTPSampleResult());
0893:                } catch (URISyntaxException e) {
0894:                    return errorResult(e, new HTTPSampleResult());
0895:                }
0896:            }
0897:
0898:            private HTTPSampleResult fileSample(URI uri) throws IOException {
0899:
0900:                String urlStr = uri.toString();
0901:
0902:                HTTPSampleResult res = new HTTPSampleResult();
0903:                res.setMonitor(isMonitor());
0904:                res.setHTTPMethod(GET); // Dummy
0905:                res.setURL(new URL(urlStr));
0906:                res.setSampleLabel(urlStr);
0907:                FileReader reader = null;
0908:                res.sampleStart();
0909:                try {
0910:                    byte[] responseData;
0911:                    StringBuffer ctb = new StringBuffer("text/html"); // $NON-NLS-1$
0912:                    reader = new FileReader(getPath());
0913:                    String contentEncoding = getContentEncoding();
0914:                    if (contentEncoding.length() == 0) {
0915:                        responseData = IOUtils.toByteArray(reader);
0916:                    } else {
0917:                        ctb.append("; charset="); // $NON-NLS-1$
0918:                        ctb.append(contentEncoding);
0919:                        responseData = IOUtils.toByteArray(reader,
0920:                                contentEncoding);
0921:                    }
0922:                    res.sampleEnd();
0923:                    res.setResponseData(responseData);
0924:                    res.setResponseCodeOK();
0925:                    res.setResponseMessageOK();
0926:                    res.setSuccessful(true);
0927:                    String ct = ctb.toString();
0928:                    res.setContentType(ct);
0929:                    res.setEncodingAndType(ct);
0930:                } finally {
0931:                    IOUtils.closeQuietly(reader);
0932:                }
0933:
0934:                //res.setResponseHeaders("");
0935:
0936:                return res;
0937:            }
0938:
0939:            /**
0940:             * Samples the URL passed in and stores the result in
0941:             * <code>HTTPSampleResult</code>, following redirects and downloading
0942:             * page resources as appropriate.
0943:             * <p>
0944:             * When getting a redirect target, redirects are not followed and resources
0945:             * are not downloaded. The caller will take care of this.
0946:             * 
0947:             * @param u
0948:             *            URL to sample
0949:             * @param method
0950:             *            HTTP method: GET, POST,...
0951:             * @param areFollowingRedirect
0952:             *            whether we're getting a redirect target
0953:             * @param depth
0954:             *            Depth of this target in the frame structure. Used only to
0955:             *            prevent infinite recursion.
0956:             * @return results of the sampling
0957:             */
0958:            protected abstract HTTPSampleResult sample(URL u, String method,
0959:                    boolean areFollowingRedirect, int depth);
0960:
0961:            /**
0962:             * Download the resources of an HTML page.
0963:             * <p>
0964:             * If createContainerResult is true, the returned result will contain one
0965:             * subsample for each request issued, including the original one that was
0966:             * passed in. It will otherwise look exactly like that original one.
0967:             * <p>
0968:             * If createContainerResult is false, one subsample will be added to the
0969:             * provided result for each requests issued.
0970:             * 
0971:             * @param res
0972:             *            result of the initial request - must contain an HTML response
0973:             * @param container
0974:             *            for storing the results
0975:             * @param frameDepth
0976:             *            Depth of this target in the frame structure. Used only to
0977:             *            prevent infinite recursion.
0978:             * @return "Container" result with one subsample per request issued
0979:             */
0980:            protected HTTPSampleResult downloadPageResources(
0981:                    HTTPSampleResult res, HTTPSampleResult container,
0982:                    int frameDepth) {
0983:                Iterator urls = null;
0984:                try {
0985:                    final byte[] responseData = res.getResponseData();
0986:                    if (responseData.length > 0) { // Bug 39205
0987:                        String parserName = getParserClass(res);
0988:                        if (parserName != null) {
0989:                            final HTMLParser parser = parserName.length() > 0 ? // we have a name
0990:                            HTMLParser.getParser(parserName)
0991:                                    : HTMLParser.getParser(); // we don't; use the default parser
0992:                            urls = parser.getEmbeddedResourceURLs(responseData,
0993:                                    res.getURL());
0994:                        }
0995:                    }
0996:                } catch (HTMLParseException e) {
0997:                    // Don't break the world just because this failed:
0998:                    res.addSubResult(errorResult(e, res));
0999:                    res.setSuccessful(false);
1000:                }
1001:
1002:                // Iterate through the URLs and download each image:
1003:                if (urls != null && urls.hasNext()) {
1004:                    if (container == null) {
1005:                        res = new HTTPSampleResult(res);
1006:                    } else {
1007:                        res = container;
1008:                    }
1009:
1010:                    // Get the URL matcher
1011:                    String re = getEmbeddedUrlRE();
1012:                    Perl5Matcher localMatcher = null;
1013:                    Pattern pattern = null;
1014:                    if (re.length() > 0) {
1015:                        try {
1016:                            pattern = JMeterUtils.getPattern(re);
1017:                            localMatcher = JMeterUtils.getMatcher();// don't fetch unless pattern compiles
1018:                        } catch (MalformedCachePatternException e) {
1019:                            log.warn("Ignoring embedded URL match string: "
1020:                                    + e.getMessage());
1021:                        }
1022:                    }
1023:                    while (urls.hasNext()) {
1024:                        Object binURL = urls.next();
1025:                        try {
1026:                            URL url = (URL) binURL;
1027:                            if (url == null) {
1028:                                log
1029:                                        .warn("Null URL detected (should not happen)");
1030:                            } else {
1031:                                String urlstr = url.toString();
1032:                                String urlStrEnc = encodeSpaces(urlstr);
1033:                                if (!urlstr.equals(urlStrEnc)) {// There were some spaces in the URL
1034:                                    try {
1035:                                        url = new URL(urlStrEnc);
1036:                                    } catch (MalformedURLException e) {
1037:                                        res
1038:                                                .addSubResult(errorResult(
1039:                                                        new Exception(
1040:                                                                urlStrEnc
1041:                                                                        + " is not a correct URI"),
1042:                                                        res));
1043:                                        res.setSuccessful(false);
1044:                                        continue;
1045:                                    }
1046:                                }
1047:                                // I don't think localMatcher can be null here, but check just in case
1048:                                if (pattern != null
1049:                                        && localMatcher != null
1050:                                        && !localMatcher.matches(urlStrEnc,
1051:                                                pattern)) {
1052:                                    continue; // we have a pattern and the URL does not match, so skip it
1053:                                }
1054:                                HTTPSampleResult binRes = sample(url, GET,
1055:                                        false, frameDepth + 1);
1056:                                res.addSubResult(binRes);
1057:                                res.setSuccessful(res.isSuccessful()
1058:                                        && binRes.isSuccessful());
1059:                            }
1060:                        } catch (ClassCastException e) {
1061:                            res.addSubResult(errorResult(new Exception(binURL
1062:                                    + " is not a correct URI"), res));
1063:                            res.setSuccessful(false);
1064:                            continue;
1065:                        }
1066:                    }
1067:                }
1068:                return res;
1069:            }
1070:
1071:            /*
1072:             * @param res HTTPSampleResult to check
1073:             * @return parser class name (may be "") or null if entry does not exist
1074:             */
1075:            private String getParserClass(HTTPSampleResult res) {
1076:                final String ct = res.getMediaType();
1077:                return (String) parsersForType.get(ct);
1078:            }
1079:
1080:            // TODO: make static?
1081:            protected String encodeSpaces(String path) {
1082:                return JOrphanUtils.replaceAllChars(path, ' ', "%20"); // $NON-NLS-1$
1083:            }
1084:
1085:            /*
1086:             * (non-Javadoc)
1087:             * 
1088:             * @see org.apache.jmeter.testelement.TestListener#testEnded()
1089:             */
1090:            public void testEnded() {
1091:                dynamicPath = false;
1092:            }
1093:
1094:            /*
1095:             * (non-Javadoc)
1096:             * 
1097:             * @see org.apache.jmeter.testelement.TestListener#testEnded(java.lang.String)
1098:             */
1099:            public void testEnded(String host) {
1100:                testEnded();
1101:            }
1102:
1103:            /*
1104:             * (non-Javadoc)
1105:             * 
1106:             * @see org.apache.jmeter.testelement.TestListener#testIterationStart(org.apache.jmeter.engine.event.LoopIterationEvent)
1107:             */
1108:            public void testIterationStart(LoopIterationEvent event) {
1109:            }
1110:
1111:            /*
1112:             * (non-Javadoc)
1113:             * 
1114:             * @see org.apache.jmeter.testelement.TestListener#testStarted()
1115:             */
1116:            public void testStarted() {
1117:                JMeterProperty pathP = getProperty(PATH);
1118:                log.debug("path property is a " + pathP.getClass().getName());
1119:                log.debug("path beginning value = " + pathP.getStringValue());
1120:                if (pathP instanceof  StringProperty
1121:                        && !"".equals(pathP.getStringValue())) {
1122:                    log.debug("Encoding spaces in path");
1123:                    pathP.setObjectValue(encodeSpaces(pathP.getStringValue()));
1124:                    dynamicPath = false;
1125:                } else {
1126:                    log.debug("setting dynamic path to true");
1127:                    dynamicPath = true;
1128:                }
1129:                log.debug("path ending value = " + pathP.getStringValue());
1130:            }
1131:
1132:            /*
1133:             * (non-Javadoc)
1134:             * 
1135:             * @see org.apache.jmeter.testelement.TestListener#testStarted(java.lang.String)
1136:             */
1137:            public void testStarted(String host) {
1138:                testStarted();
1139:            }
1140:
1141:            /*
1142:             * (non-Javadoc)
1143:             * 
1144:             * @see java.lang.Object#clone()
1145:             */
1146:            public Object clone() {
1147:                HTTPSamplerBase base = (HTTPSamplerBase) super .clone();
1148:                base.dynamicPath = dynamicPath;
1149:                return base;
1150:            }
1151:
1152:            /**
1153:             * Iteratively download the redirect targets of a redirect response.
1154:             * <p>
1155:             * The returned result will contain one subsample for each request issued,
1156:             * including the original one that was passed in. It will be an
1157:             * HTTPSampleResult that should mostly look as if the final destination of
1158:             * the redirect chain had been obtained in a single shot.
1159:             * 
1160:             * @param res
1161:             *            result of the initial request - must be a redirect response
1162:             * @param frameDepth
1163:             *            Depth of this target in the frame structure. Used only to
1164:             *            prevent infinite recursion.
1165:             * @return "Container" result with one subsample per request issued
1166:             */
1167:            protected HTTPSampleResult followRedirects(HTTPSampleResult res,
1168:                    int frameDepth) {
1169:                HTTPSampleResult totalRes = new HTTPSampleResult(res);
1170:                HTTPSampleResult lastRes = res;
1171:
1172:                int redirect;
1173:                for (redirect = 0; redirect < MAX_REDIRECTS; redirect++) {
1174:                    boolean invalidRedirectUrl = false;
1175:                    // Browsers seem to tolerate Location headers with spaces,
1176:                    // replacing them automatically with %20. We want to emulate
1177:                    // this behaviour.
1178:                    String location = encodeSpaces(lastRes
1179:                            .getRedirectLocation());
1180:                    try {
1181:                        lastRes = sample(new URL(lastRes.getURL(), location),
1182:                                GET, true, frameDepth);
1183:                    } catch (MalformedURLException e) {
1184:                        lastRes = errorResult(e, lastRes);
1185:                        // The redirect URL we got was not a valid URL
1186:                        invalidRedirectUrl = true;
1187:                    }
1188:                    if (lastRes.getSubResults() != null
1189:                            && lastRes.getSubResults().length > 0) {
1190:                        SampleResult[] subs = lastRes.getSubResults();
1191:                        for (int i = 0; i < subs.length; i++) {
1192:                            totalRes.addSubResult(subs[i]);
1193:                        }
1194:                    } else {
1195:                        // Only add sample if it is a sample of valid url redirect, i.e. that
1196:                        // we have actually sampled the URL
1197:                        if (!invalidRedirectUrl) {
1198:                            totalRes.addSubResult(lastRes);
1199:                        }
1200:                    }
1201:
1202:                    if (!lastRes.isRedirect()) {
1203:                        break;
1204:                    }
1205:                }
1206:                if (redirect >= MAX_REDIRECTS) {
1207:                    lastRes = errorResult(new IOException(
1208:                            "Exceeeded maximum number of redirects: "
1209:                                    + MAX_REDIRECTS), lastRes);
1210:                    totalRes.addSubResult(lastRes);
1211:                }
1212:
1213:                // Now populate the any totalRes fields that need to
1214:                // come from lastRes:
1215:                totalRes.setSampleLabel(totalRes.getSampleLabel() + "->"
1216:                        + lastRes.getSampleLabel());
1217:                // The following three can be discussed: should they be from the
1218:                // first request or from the final one? I chose to do it this way
1219:                // because that's what browsers do: they show the final URL of the
1220:                // redirect chain in the location field.
1221:                totalRes.setURL(lastRes.getURL());
1222:                totalRes.setHTTPMethod(lastRes.getHTTPMethod());
1223:                totalRes.setQueryString(lastRes.getQueryString());
1224:                totalRes.setRequestHeaders(lastRes.getRequestHeaders());
1225:
1226:                totalRes.setResponseData(lastRes.getResponseData());
1227:                totalRes.setResponseCode(lastRes.getResponseCode());
1228:                totalRes.setSuccessful(lastRes.isSuccessful());
1229:                totalRes.setResponseMessage(lastRes.getResponseMessage());
1230:                totalRes.setDataType(lastRes.getDataType());
1231:                totalRes.setResponseHeaders(lastRes.getResponseHeaders());
1232:                totalRes.setContentType(lastRes.getContentType());
1233:                totalRes.setDataEncoding(lastRes.getDataEncoding());
1234:                return totalRes;
1235:            }
1236:
1237:            /**
1238:             * Follow redirects and download page resources if appropriate. this works,
1239:             * but the container stuff here is what's doing it. followRedirects() is
1240:             * actually doing the work to make sure we have only one container to make
1241:             * this work more naturally, I think this method - sample() - needs to take
1242:             * an HTTPSamplerResult container parameter instead of a
1243:             * boolean:areFollowingRedirect.
1244:             * 
1245:             * @param areFollowingRedirect
1246:             * @param frameDepth
1247:             * @param res
1248:             * @return the sample result
1249:             */
1250:            protected HTTPSampleResult resultProcessing(
1251:                    boolean areFollowingRedirect, int frameDepth,
1252:                    HTTPSampleResult res) {
1253:                boolean wasRedirected = false;
1254:                if (!areFollowingRedirect) {
1255:                    if (res.isRedirect()) {
1256:                        log.debug("Location set to - "
1257:                                + res.getRedirectLocation());
1258:
1259:                        if (getFollowRedirects()) {
1260:                            res = followRedirects(res, frameDepth);
1261:                            areFollowingRedirect = true;
1262:                            wasRedirected = true;
1263:                        }
1264:                    }
1265:                }
1266:                if (isImageParser()
1267:                        && (HTTPSampleResult.TEXT).equals(res.getDataType())
1268:                        && res.isSuccessful()) {
1269:                    if (frameDepth > MAX_FRAME_DEPTH) {
1270:                        res
1271:                                .addSubResult(errorResult(
1272:                                        new Exception(
1273:                                                "Maximum frame/iframe nesting depth exceeded."),
1274:                                        res));
1275:                    } else {
1276:                        // If we followed redirects, we already have a container:
1277:                        if (!areFollowingRedirect) {
1278:                            HTTPSampleResult container = (HTTPSampleResult) (areFollowingRedirect ? res
1279:                                    .getParent()
1280:                                    : res);
1281:
1282:                            // Only download page resources if we were not redirected.
1283:                            // If we were redirected, the page resources have already been
1284:                            // downloaded for the sample made for the redirected url
1285:                            if (!wasRedirected) {
1286:                                res = downloadPageResources(res, container,
1287:                                        frameDepth);
1288:                            }
1289:                        }
1290:                    }
1291:                }
1292:                return res;
1293:            }
1294:
1295:            /**
1296:             * Determine if the HTTP status code is successful or not
1297:             * i.e. in range 200 to 399 inclusive
1298:             * 
1299:             * @return whether in range 200-399 or not
1300:             */
1301:            protected boolean isSuccessCode(int code) {
1302:                return (code >= 200 && code <= 399);
1303:            }
1304:
1305:            protected static String encodeBackSlashes(String value) {
1306:                StringBuffer newValue = new StringBuffer();
1307:                for (int i = 0; i < value.length(); i++) {
1308:                    char charAt = value.charAt(i);
1309:                    if (charAt == '\\') { // $NON-NLS-1$
1310:                        newValue.append("\\\\"); // $NON-NLS-1$
1311:                    } else {
1312:                        newValue.append(charAt);
1313:                    }
1314:                }
1315:                return newValue.toString();
1316:            }
1317:
1318:            /**
1319:             * Method to tell if the request has any files to be uploaded
1320:             */
1321:            protected boolean hasUploadableFiles() {
1322:                return getFilename() != null
1323:                        && getFilename().trim().length() > 0;
1324:            }
1325:
1326:            public static String[] getValidMethodsAsArray() {
1327:                return (String[]) METHODLIST.toArray(new String[0]);
1328:            }
1329:
1330:            public static boolean isSecure(String protocol) {
1331:                return PROTOCOL_HTTPS.equalsIgnoreCase(protocol);
1332:            }
1333:
1334:            public static boolean isSecure(URL url) {
1335:                return isSecure(url.getProtocol());
1336:            }
1337:
1338:            // Implement these here, to avoid re-implementing for sub-classes
1339:            // (previously these were implemented in all TestElements)
1340:            public void threadStarted() {
1341:            }
1342:
1343:            public void threadFinished() {
1344:            }
1345:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.