001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027package org.apache.http.benchmark;
028
029import java.io.File;
030import java.net.MalformedURLException;
031import java.net.URL;
032
033import org.apache.commons.cli.CommandLine;
034import org.apache.commons.cli.HelpFormatter;
035import org.apache.commons.cli.Option;
036import org.apache.commons.cli.Options;
037
038public class CommandLineUtils {
039
040    public static Options getOptions() {
041        final Option iopt = new Option("i", false, "Do HEAD requests instead of GET (deprecated)");
042        iopt.setRequired(false);
043
044        final Option oopt = new Option("o", false, "Use HTTP/S 1.0 instead of 1.1 (default)");
045        oopt.setRequired(false);
046
047        final Option kopt = new Option("k", false, "Enable the HTTP KeepAlive feature, " +
048            "i.e., perform multiple requests within one HTTP session. " +
049            "Default is no KeepAlive");
050        kopt.setRequired(false);
051
052        final Option uopt = new Option("u", false, "Chunk entity. Default is false");
053        uopt.setRequired(false);
054
055        final Option xopt = new Option("x", false, "Use Expect-Continue. Default is false");
056        xopt.setRequired(false);
057
058        final Option gopt = new Option("g", false, "Accept GZip. Default is false");
059        gopt.setRequired(false);
060
061        final Option nopt = new Option("n", true, "Number of requests to perform for the " +
062            "benchmarking session. The default is to just perform a single " +
063            "request which usually leads to non-representative benchmarking " +
064            "results");
065        nopt.setRequired(false);
066        nopt.setArgName("requests");
067
068        final Option copt = new Option("c", true, "Concurrency while performing the " +
069            "benchmarking session. The default is to just use a single thread/client");
070        copt.setRequired(false);
071        copt.setArgName("concurrency");
072
073        final Option popt = new Option("p", true, "File containing data to POST or PUT");
074        popt.setRequired(false);
075        popt.setArgName("Payload file");
076
077        final Option mopt = new Option("m", true, "HTTP Method. Default is POST. " +
078                "Possible options are GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE");
079        mopt.setRequired(false);
080        mopt.setArgName("HTTP method");
081
082        final Option Topt = new Option("T", true, "Content-type header to use for POST/PUT data");
083        Topt.setRequired(false);
084        Topt.setArgName("content-type");
085
086        final Option topt = new Option("t", true, "Client side socket timeout (in ms) - default 60 Secs");
087        topt.setRequired(false);
088        topt.setArgName("socket-Timeout");
089
090        final Option Hopt = new Option("H", true, "Add arbitrary header line, " +
091            "eg. 'Accept-Encoding: gzip' inserted after all normal " +
092            "header lines. (repeatable as -H \"h1: v1\",\"h2: v2\" etc)");
093        Hopt.setRequired(false);
094        Hopt.setArgName("header");
095
096        final Option vopt = new Option("v", true, "Set verbosity level - 4 and above " +
097            "prints response content, 3 and above prints " +
098            "information on headers, 2 and above prints response codes (404, 200, " +
099            "etc.), 1 and above prints warnings and info");
100        vopt.setRequired(false);
101        vopt.setArgName("verbosity");
102
103        final Option hopt = new Option("h", false, "Display usage information");
104        nopt.setRequired(false);
105
106        final Options options = new Options();
107        options.addOption(iopt);
108        options.addOption(mopt);
109        options.addOption(uopt);
110        options.addOption(xopt);
111        options.addOption(gopt);
112        options.addOption(kopt);
113        options.addOption(nopt);
114        options.addOption(copt);
115        options.addOption(popt);
116        options.addOption(Topt);
117        options.addOption(vopt);
118        options.addOption(Hopt);
119        options.addOption(hopt);
120        options.addOption(topt);
121        options.addOption(oopt);
122        return options;
123    }
124
125    public static void parseCommandLine(final CommandLine cmd, final Config config) {
126        if (cmd.hasOption('v')) {
127            final String s = cmd.getOptionValue('v');
128            try {
129                config.setVerbosity(Integer.parseInt(s));
130            } catch (final NumberFormatException ex) {
131                printError("Invalid verbosity level: " + s);
132            }
133        }
134
135        if (cmd.hasOption('k')) {
136            config.setKeepAlive(true);
137        }
138
139        if (cmd.hasOption('c')) {
140            final String s = cmd.getOptionValue('c');
141            try {
142                config.setThreads(Integer.parseInt(s));
143            } catch (final NumberFormatException ex) {
144                printError("Invalid number for concurrency: " + s);
145            }
146        }
147
148        if (cmd.hasOption('n')) {
149            final String s = cmd.getOptionValue('n');
150            try {
151                config.setRequests(Integer.parseInt(s));
152            } catch (final NumberFormatException ex) {
153                printError("Invalid number of requests: " + s);
154            }
155        }
156
157        if (cmd.hasOption('p')) {
158            final File file = new File(cmd.getOptionValue('p'));
159            if (!file.exists()) {
160                printError("File not found: " + file);
161            }
162            config.setPayloadFile(file);
163        }
164
165        if (cmd.hasOption('T')) {
166            config.setContentType(cmd.getOptionValue('T'));
167        }
168
169        if (cmd.hasOption('i')) {
170            config.setHeadInsteadOfGet(true);
171        }
172
173        if (cmd.hasOption('H')) {
174            final String headerStr = cmd.getOptionValue('H');
175            config.setHeaders(headerStr.split(","));
176        }
177
178        if (cmd.hasOption('t')) {
179            final String t = cmd.getOptionValue('t');
180            try {
181                config.setSocketTimeout(Integer.parseInt(t));
182            } catch (final NumberFormatException ex) {
183                printError("Invalid socket timeout: " + t);
184            }
185        }
186
187        if (cmd.hasOption('o')) {
188            config.setUseHttp1_0(true);
189        }
190
191        if (cmd.hasOption('m')) {
192            config.setMethod(cmd.getOptionValue('m'));
193        } else if (cmd.hasOption('p')) {
194            config.setMethod("POST");
195        }
196
197        if (cmd.hasOption('u')) {
198            config.setUseChunking(true);
199        }
200
201        if (cmd.hasOption('x')) {
202            config.setUseExpectContinue(true);
203        }
204
205        if (cmd.hasOption('g')) {
206            config.setUseAcceptGZip(true);
207        }
208
209        final String[] cmdargs = cmd.getArgs();
210        if (cmdargs.length > 0) {
211            try {
212                config.setUrl(new URL(cmdargs[0]));
213            } catch (final MalformedURLException e) {
214                printError("Invalid request URL : " + cmdargs[0]);
215            }
216        }
217    }
218
219    static void showUsage(final Options options) {
220        final HelpFormatter formatter = new HelpFormatter();
221        formatter.printHelp("HttpBenchmark [options] [http://]hostname[:port]/path?query", options);
222    }
223
224    static void printError(final String msg) {
225        System.err.println(msg);
226        showUsage(getOptions());
227        System.exit(-1);
228    }
229}