at.alladin.rmbt.client.v2.task.HttpProxyTask.java Source code

Java tutorial

Introduction

Here is the source code for at.alladin.rmbt.client.v2.task.HttpProxyTask.java

Source

/*******************************************************************************
 * Copyright 2013-2014 alladin-IT GmbH
 * 
 * Licensed 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
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package at.alladin.rmbt.client.v2.task;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URI;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.client.RedirectHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;

import at.alladin.rmbt.client.QualityOfServiceTest;
import at.alladin.rmbt.client.RMBTClient;
import at.alladin.rmbt.client.v2.task.result.QoSTestResult;
import at.alladin.rmbt.client.v2.task.result.QoSTestResultEnum;

/**
 * 
 * @author lb
 *
 */
public class HttpProxyTask extends AbstractQoSTask {

    private final String target;

    private final String range;

    private final long connectionTimeout;

    private final long downloadTimeout;

    public final static long DEFAULT_CONNECTION_TIMEOUT = 5000000000L;

    public final static long DEFAULT_DOWNLOAD_TIMEOUT = 10000000000L;

    public final static String PARAM_TARGET = "url";

    public final static String PARAM_RANGE = "range";

    public final static String PARAM_CONNECTION_TIMEOUT = "conn_timeout";

    public final static String PARAM_DOWNLOAD_TIMEOUT = "download_timeout";

    public final static String RESULT_STATUS = "http_result_status";

    public final static String RESULT_DURATION = "http_result_duration";

    public final static String RESULT_LENGTH = "http_result_length";

    public final static String RESULT_HEADER = "http_result_header";

    public final static String RESULT_RANGE = "http_objective_range";

    public final static String RESULT_TARGET = "http_objective_url";

    public final static String RESULT_HASH = "http_result_hash";

    public final AtomicBoolean downloadCompleted = new AtomicBoolean(false);

    public final AtomicBoolean timeOutReached = new AtomicBoolean(false);

    /**
     * 
     * @param taskDesc
     */
    public HttpProxyTask(QualityOfServiceTest nnTest, TaskDesc taskDesc, int threadId) {
        super(nnTest, taskDesc, threadId);
        this.target = (String) taskDesc.getParams().get(PARAM_TARGET);
        this.range = (String) taskDesc.getParams().get(PARAM_RANGE);

        String value = (String) taskDesc.getParams().get(PARAM_CONNECTION_TIMEOUT);
        this.connectionTimeout = value != null ? Long.valueOf(value) : DEFAULT_CONNECTION_TIMEOUT;

        value = (String) taskDesc.getParams().get(PARAM_DOWNLOAD_TIMEOUT);
        this.downloadTimeout = value != null ? Long.valueOf(value) : DEFAULT_DOWNLOAD_TIMEOUT;
    }

    /*
     * (non-Javadoc)
     * @see java.util.concurrent.Callable#call()
     */
    public QoSTestResult call() throws Exception {
        final QoSTestResult result = initQoSTestResult(QoSTestResultEnum.HTTP_PROXY);
        try {
            onStart(result);

            Future<QoSTestResult> httpTimeoutTask = RMBTClient.getCommonThreadPool()
                    .submit(new Callable<QoSTestResult>() {

                        public QoSTestResult call() throws Exception {
                            httpGet(result);
                            return result;
                        }

                    });

            final QoSTestResult testResult = httpTimeoutTask.get((int) (downloadTimeout / 1000000),
                    TimeUnit.SECONDS);
            return testResult;
        } catch (TimeoutException e) {
            e.printStackTrace();
            result.getResultMap().put(RESULT_HASH, "TIMEOUT");
        } catch (Exception e) {
            throw e;
        } finally {
            onEnd(result);
        }

        return result;
    }

    /**
     * 
     * @return
     */
    private QoSTestResult httpGet(final QoSTestResult result) throws Exception {
        final HttpGet httpGet = new HttpGet(new URI(this.target));

        if (range != null && range.startsWith("bytes")) {
            httpGet.addHeader("Range", range);
        }

        HttpParams httpParameters = new BasicHttpParams();

        // Set the timeout
        HttpConnectionParams.setConnectionTimeout(httpParameters, (int) (connectionTimeout / 1000000));
        // Set the default socket timeout (SO_TIMEOUT) in milliseconds which is the timeout for waiting for data.
        HttpConnectionParams.setSoTimeout(httpParameters, (int) (downloadTimeout / 1000000));

        System.out.println("Downloading: " + target);

        DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);

        //prevent redirects:
        httpClient.setRedirectHandler(new RedirectHandler() {

            public boolean isRedirectRequested(HttpResponse response, HttpContext context) {
                return false;
            }

            public URI getLocationURI(HttpResponse response, HttpContext context) throws ProtocolException {
                return null;
            }
        });

        Thread timeoutThread = new Thread(new Runnable() {

            public void run() {
                try {
                    System.out.println("HTTP PROXY TIMEOUT THREAD: " + downloadTimeout + " ms");
                    Thread.sleep((int) (downloadTimeout / 1000000));

                    if (!downloadCompleted.get()) {
                        if (httpGet != null && !httpGet.isAborted()) {
                            httpGet.abort();
                        }
                        timeOutReached.set(true);
                        System.out.println("HTTP PROXY TIMEOUT REACHED");
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });

        timeoutThread.start();

        String hash = null;
        long duration = 0;

        try {
            final long start = System.nanoTime();
            HttpResponse response = httpClient.execute(httpGet);

            //get the content:
            long contentLength = -1;
            if (getQoSTest().getTestSettings().getCacheFolder() != null) {
                File cacheFile = new File(getQoSTest().getTestSettings().getCacheFolder(), "proxy" + threadId);
                contentLength = writeFileFromInputStream(response.getEntity().getContent(), cacheFile);
                duration = System.nanoTime() - start;
                hash = generateChecksum(cacheFile);
                cacheFile.delete();
            } else {
                //get Content:
                String content = getStringFromInputStream(response.getEntity().getContent());
                duration = System.nanoTime() - start;
                //calculate md5 hash:
                hash = generateChecksum(content.getBytes("UTF-8"));
            }

            //result.getResultMap().put(RESULT_DURATION, (duration / 1000000));
            result.getResultMap().put(RESULT_STATUS, response.getStatusLine().getStatusCode());
            result.getResultMap().put(RESULT_LENGTH, contentLength);

            StringBuilder header = new StringBuilder();

            for (Header h : response.getAllHeaders()) {
                header.append(h.getName());
                header.append(": ");
                header.append(h.getValue());
                header.append("\n");
            }

            result.getResultMap().put(RESULT_HEADER, header.toString());
        } catch (Exception e) {
            e.printStackTrace();
            result.getResultMap().put(RESULT_STATUS, "");
            result.getResultMap().put(RESULT_LENGTH, 0);
            result.getResultMap().put(RESULT_HEADER, "");
        } finally {
            if (timeOutReached.get()) {
                result.getResultMap().put(RESULT_HASH, "TIMEOUT");
            } else if (hash != null) {
                result.getResultMap().put(RESULT_HASH, hash);
            } else {
                result.getResultMap().put(RESULT_HASH, "ERROR");
            }
        }

        result.getResultMap().put(RESULT_RANGE, range);
        result.getResultMap().put(RESULT_TARGET, target);

        return result;
    }

    /**
     * 
     * @param is
     * @return
     */
    public static String getStringFromInputStream(InputStream is) {

        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();

        String line;
        try {

            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return sb.toString();
    }

    public long writeFileFromInputStream(InputStream is, File outputFile)
            throws FileNotFoundException, IOException {
        return copyInputStreamToOutputStream(is, new FileOutputStream(outputFile));
    }

    public long copyInputStreamToOutputStream(InputStream input, OutputStream output) throws IOException {
        byte[] buffer = new byte[4096];
        long count = 0L;
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            if (timeOutReached.get()) {
                break;
            }
            output.write(buffer, 0, n);
            count += n;
        }
        downloadCompleted.set(true);
        output.close();
        return count;
    }

    /**
     * 
     * @param input
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String generateChecksum(byte[] input) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] hash = md.digest(input);

        return generateChecksumFromDigest(hash);
    }

    /**
     * 
     * @param file
     * @return
     * @throws NoSuchAlgorithmException
     * @throws IOException 
     */
    public static String generateChecksum(File file) throws NoSuchAlgorithmException, IOException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        DigestInputStream dis = new DigestInputStream(new FileInputStream(file), md);
        int ch;
        while ((ch = dis.read()) != -1) {
            //empty block
        }
        dis.close();
        return generateChecksumFromDigest(md.digest());
    }

    /**
     * 
     * @param digest
     * @return
     */
    public static String generateChecksumFromDigest(byte[] digest) {
        StringBuilder hexString = new StringBuilder();

        for (int i = 0; i < digest.length; i++) {
            if ((0xff & digest[i]) < 0x10) {
                hexString.append("0" + Integer.toHexString((0xFF & digest[i])));
            } else {
                hexString.append(Integer.toHexString(0xFF & digest[i]));
            }
        }
        return hexString.toString();
    }

    /*
     * (non-Javadoc)
     * @see at.alladin.rmbt.client.v2.task.AbstractRmbtTask#initTask()
     */
    @Override
    public void initTask() {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * @see at.alladin.rmbt.client.v2.task.QoSTask#getTestType()
     */
    public QoSTestResultEnum getTestType() {
        return QoSTestResultEnum.HTTP_PROXY;
    }
}