| career | drupal | java | mac | mysql | perl | scala | uml | unix  

JMeter example source code file (

This example JMeter source code file ( is included in the "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - JMeter tags/keywords

httpmirrorthread, io, iso_8859_1, net, network, non-nls-1, non-nls-1, pattern, patternmatcherinput, patternmatcherinput, perl5matcher, string, string, stringbuilder, thread, transfer-encoding, transfer-encoding

The JMeter source code

 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * See the License for the specific language governing permissions and
 * limitations under the License.

package org.apache.jmeter.protocol.http.control;


import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.log.Logger;
import org.apache.oro.text.regex.MatchResult;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternMatcherInput;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;

 * Thread to handle one client request. Gets the request from the client and
 * sends the response back to the client.
public class HttpMirrorThread extends Thread {
    private static final Logger log = LoggingManager.getLoggerForClass();

    private static final String ISO_8859_1 = "ISO-8859-1"; //$NON-NLS-1$
    private static final byte[] CRLF = { 0x0d, 0x0a };

    /** Socket to client. */
    private final Socket clientSocket;

    public HttpMirrorThread(Socket _clientSocket) {

     * Main processing method for the HttpMirror object
    public void run() {"Starting thread");
        BufferedInputStream in = null;
        BufferedOutputStream out = null;

        try {
            in = new BufferedInputStream(clientSocket.getInputStream());
            out = new BufferedOutputStream(clientSocket.getOutputStream());
            // The headers are written using ISO_8859_1 encoding
            out.write("HTTP/1.0 200 OK".getBytes(ISO_8859_1)); //$NON-NLS-1$
            out.write("Content-Type: text/plain".getBytes(ISO_8859_1)); //$NON-NLS-1$

            // Read the header part, we will be looking for a content-length
            // header, so we know how much we should read.
            // We assume headers are in ISO_8859_1
            // If we do not find such a header, we will just have to read until
            // we have to block to read more, until we support chunked transfer
            int contentLength = -1;
            boolean isChunked = false;
            byte[] buffer = new byte[1024];
            StringBuilder headers = new StringBuilder();
            int length = 0;
            int positionOfBody = 0;
            while(positionOfBody <= 0 && ((length = != -1)) {
                out.write(buffer, 0, length); // echo back
                headers.append(new String(buffer, 0, length, ISO_8859_1));
                // Check if we have read all the headers
                positionOfBody = getPositionOfBody(headers.toString());

            // Check if we have found a content-length header
            final String headerString = headers.toString();
            String contentLengthHeaderValue = getRequestHeaderValue(headerString, "Content-Length"); //$NON-NLS-1$
            if(contentLengthHeaderValue != null) {
                contentLength = new Integer(contentLengthHeaderValue).intValue();
            String sleepHeaderValue = getRequestHeaderValue(headerString, "X-Sleep"); //$NON-NLS-1$
            if(sleepHeaderValue != null) {
            String transferEncodingHeaderValue = getRequestHeaderValue(headerString, "Transfer-Encoding"); //$NON-NLS-1$
            if(transferEncodingHeaderValue != null) {
                isChunked = transferEncodingHeaderValue.equalsIgnoreCase("chunked"); //$NON-NLS-1$
                // We only support chunked transfer encoding
                if(!isChunked) {
                    log.error("Transfer-Encoding header set, the value is not supported : " + transferEncodingHeaderValue);

            // If we know the content length, we can allow the reading of
            // the request to block until more data arrives.
            // If it is chunked transfer, we cannot allow the reading to
            // block, because we do not know when to stop reading, because
            // the chunked transfer is not properly supported yet
            length = 0;
            if(contentLength > 0) {
                // Check how much of the body we have already read as part of reading
                // the headers
                // We subtract two bytes for the crlf divider between header and body
                int totalReadBytes = headerString.length() - positionOfBody - 2;

                // We know when to stop reading, so we can allow the read method to block
                while((totalReadBytes < contentLength) && ((length = != -1)) {
                    out.write(buffer, 0, length);

                    totalReadBytes += length;
            else if (isChunked) {
                // It is chunked transfer encoding, which we do not really support yet.
                // So we just read without blocking, because we do not know when to
                // stop reading, so we cannot block
                // TODO propery implement support for chunked transfer, i.e. to
                // know when we have read the whole request, and therefore allow
                // the reading to block
                while(in.available() > 0 && ((length = != -1)) {
                    out.write(buffer, 0, length);
            else {
                // The reqest has no body, or it has a transfer encoding we do not support.
                // In either case, we read any data available
                while(in.available() > 0 && ((length = != -1)) {
                    out.write(buffer, 0, length);
        } catch (IOException e) {
            log.error("", e);
        } catch (InterruptedException e) {
            log.error("", e);
        } finally {
        }"End of Thread");

    private static String getRequestHeaderValue(String requestHeaders, String headerName) {
        Perl5Matcher localMatcher = JMeterUtils.getMatcher();
        // We use multi-line mask so can prefix the line with ^
        // also match \w+ to catch Transfer-Encoding: chunked
        // TODO: may need to be extended to allow for other header values with non-word contents
        String expression = "^" + headerName + ":\\s+(\\w+)"; // $NON-NLS-1$ $NON-NLS-2$
        Pattern pattern = JMeterUtils.getPattern(expression, Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK | Perl5Compiler.MULTILINE_MASK);
        if(localMatcher.contains(requestHeaders, pattern)) {
            // The value is in the first group, group 0 is the whole match
            return localMatcher.getMatch().group(1);
        else {
            return null;

    private static int getPositionOfBody(String stringToCheck) {
        Perl5Matcher localMatcher = JMeterUtils.getMatcher();
        // The headers and body are divided by a blank line (the \r is to allow for the CR before LF)
        String regularExpression = "^\\r$"; // $NON-NLS-1$
        Pattern pattern = JMeterUtils.getPattern(regularExpression, Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK | Perl5Compiler.MULTILINE_MASK);

        PatternMatcherInput input = new PatternMatcherInput(stringToCheck);
        if(localMatcher.contains(input, pattern)) {
            MatchResult match = localMatcher.getMatch();
            return match.beginOffset(0);
        // No divider was found
        return -1;

Other JMeter examples (source code examples)

Here is a short list of links related to this JMeter source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller


new blog posts


Copyright 1998-2021 Alvin Alexander,
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.