Package kg.apc.jmeter.samplers

Source Code of kg.apc.jmeter.samplers.HTTPRawSampler

package kg.apc.jmeter.samplers;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.util.Scanner;
import java.util.regex.Pattern;
import kg.apc.io.SocketChannelWithTimeouts;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

// FIXME: actually keep-alive does not work!
public class HTTPRawSampler extends AbstractIPSampler {
   
    private static final String FILE_NAME = "fileName";
    private static final String KEEPALIVE = "keepalive";
    private static final String PARSE = "parse";
    private static final String RNpattern = "\\r\\n";
    private static final String SPACE = " ";
    //
    protected static final Logger log = LoggingManager.getLoggerForClass();
    private static final Pattern anyContent = Pattern.compile(".+", Pattern.DOTALL);
    private SocketChannel savedSock;
    private static final int fileSendingChunk = JMeterUtils.getPropDefault("kg.apc.jmeter.samplers.FileReadChunkSize", 1024 * 4);
   
    public HTTPRawSampler() {
        super();
        log.debug("File reading chunk size: " + fileSendingChunk);
    }
   
    @Override
    public SampleResult sample(Entry entry) {
        SampleResult res = super.sample(entry);
        if (isParseResult()) {
            parseResponse(res);
        }
        return res;
    }
   
    protected byte[] readResponse(SocketChannel channel, SampleResult res) throws IOException {
        ByteArrayOutputStream response = new ByteArrayOutputStream();
       
        ByteBuffer recvBuf = getRecvBuf();
        recvBuf.clear();
       
        boolean firstPack = true;
        int cnt;
        int responseSize = 0;
       
        if (log.isDebugEnabled()) {
            log.debug("Start reading response");
        }
       
        try {
            while ((cnt = channel.read(recvBuf)) != -1) {
                responseSize += cnt;
                if (firstPack) {
                    res.latencyEnd();
                    firstPack = false;
                }
                recvBuf.flip();
                if (response.size() <= recvDataLimit) {
                    byte[] bytes = new byte[cnt];
                    recvBuf.get(bytes);
                    response.write(bytes);
                }
               
                recvBuf.clear();
            }
           
            if (response.size() < 1) {
                log.warn("Read no bytes from socket, seems it was closed. Let it be so.");
                channel.close();
            }
        } catch (IOException ex) {
            channel.close();
            throw ex;
        }
       
        if (log.isDebugEnabled()) {
            log.debug("Done reading response");
        }
       
        res.sampleEnd();
        if (!isUseKeepAlive()) {
            channel.close();
        }
       
        res.setBytes(responseSize);
        return response.toByteArray();
    }
   
    private void parseResponse(SampleResult res) {
        Scanner scanner = new Scanner(res.getResponseDataAsString());
        scanner.useDelimiter(RNpattern);
       
        if (!scanner.hasNextLine()) {
            return;
        }
       
        String httpStatus = scanner.nextLine();
       
        int s = httpStatus.indexOf(SPACE);
        int e = httpStatus.indexOf(SPACE, s + 1);
        if (s < e) {
            String rc = httpStatus.substring(s, e).trim();
            try {
                int rcInt = Integer.parseInt(rc);
                if (rcInt < 100 || rcInt > 599) {
                    return;
                }
                res.setResponseCode(rc);
                res.setResponseMessage(httpStatus.substring(e).trim());
            } catch (NumberFormatException ex) {
                return;
            }
        } else {
            return;
        }
       
        if (!scanner.hasNextLine()) {
            return;
        }
       
        int n = 1;
        StringBuilder headers = new StringBuilder();
        String line;
        while (scanner.hasNextLine() && !(line = scanner.nextLine()).isEmpty()) {
            headers.append(line).append(CRLF);
            n++;
        }
        res.setResponseHeaders(headers.toString());
       
        if (scanner.hasNext()) {
            res.setResponseData(scanner.next(anyContent).getBytes());
        } else {
            res.setResponseData("".getBytes());
        }
       
    }
   
    @Override
    protected byte[] processIO(SampleResult res) throws Exception {
        SocketChannel sock = (SocketChannel) getSocketChannel();
       
        if (!getRequestData().isEmpty()) {
            ByteBuffer sendBuf = ByteBuffer.wrap(getRequestData().getBytes()); // cannot cache it because of variable processing
            sock.write(sendBuf);
        }
        sendFile(getFileToSend(), sock);
        if (log.isDebugEnabled()) {
            log.debug("Sent request");
        }
        return readResponse(sock, res);
    }
   
    protected SocketChannel getSocketChannel() throws IOException {
        if (isUseKeepAlive() && savedSock != null) {
            return savedSock;
        }
       
        int port;
        try {
            port = Integer.parseInt(getPort());
        } catch (NumberFormatException ex) {
            log.warn("Wrong port number: " + getPort() + ", defaulting to 80", ex);
            port = 80;
        }
        InetSocketAddress address = new InetSocketAddress(getHostName(), port);

        //log.info("Open sock");
        savedSock = (SocketChannel) getChannel();
        savedSock.connect(address);
        return savedSock;
    }
   
    public boolean isUseKeepAlive() {
        return getPropertyAsBoolean(KEEPALIVE);
    }
   
    public void setUseKeepAlive(boolean selected) {
        setProperty(KEEPALIVE, selected);
    }
   
    @Override
    protected AbstractSelectableChannel getChannel() throws IOException {
        int t = getTimeoutAsInt();
        if (t > 0) {
            SocketChannelWithTimeouts res = (SocketChannelWithTimeouts) SocketChannelWithTimeouts.open();
            res.setConnectTimeout(t);
            res.setReadTimeout(t);
            return res;
        } else {
            return SocketChannel.open();
        }
    }
   
    public boolean isParseResult() {
        return getPropertyAsBoolean(PARSE);
    }
   
    public void setParseResult(boolean selected) {
        setProperty(PARSE, selected);
    }
   
    public String getFileToSend() {
        return getPropertyAsString(FILE_NAME);
    }
   
    public void setFileToSend(String text) {
        setProperty(FILE_NAME, text);
    }
   
    @Override
    public boolean interrupt() {
        if (savedSock != null && savedSock.isOpen()) {
            try {
                savedSock.close();
            } catch (IOException ex) {
                log.warn("Exception while interrupting channel: ", ex);
                return false;
            }
        }
        return true;
    }
   
    private void sendFile(String filename, SocketChannel sock) throws IOException {
        if (filename.isEmpty()) {
            return;
        }
       
        FileInputStream is = new FileInputStream(new File(filename));
        FileChannel source = is.getChannel();
       
        ByteBuffer sendBuf = ByteBuffer.allocateDirect(fileSendingChunk);
        while (source.read(sendBuf) > 0) {
            sendBuf.flip();
            if (log.isDebugEnabled()) {
                log.debug("Sending " + sendBuf);
            }
            sock.write(sendBuf);
            sendBuf.rewind();
        }
       
        source.close();
    }
}
TOP

Related Classes of kg.apc.jmeter.samplers.HTTPRawSampler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.