com.github.consiliens.harv.util.Utils.java Source code

Java tutorial

Introduction

Here is the source code for com.github.consiliens.harv.util.Utils.java

Source

/*******************************************************************************
 * Copyright (c) 2011 consiliens (consiliens@gmail.com).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 ******************************************************************************/
package com.github.consiliens.harv.util;

import static com.github.consiliens.harv.util.Invoke.invoke;
import static com.github.consiliens.harv.util.Invoke.invokeStatic;

import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.binary.Hex;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.jboss.netty.handler.codec.http.Cookie;
import org.jboss.netty.handler.codec.http.CookieDateFormat;
import org.jboss.netty.handler.codec.http.CookieDecoder;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;

import com.github.consiliens.harv.gson.R;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import com.subgraph.vega.api.model.IModel;
import com.subgraph.vega.api.model.IWorkspace;
import com.subgraph.vega.api.model.IWorkspaceEntry;
import com.subgraph.vega.api.model.requests.IRequestLogRecord;
import com.subgraph.vega.internal.model.Model;
import com.subgraph.vega.internal.model.WorkspaceEntry;

import edu.umass.cs.benchlab.har.HarCache;
import edu.umass.cs.benchlab.har.HarContent;
import edu.umass.cs.benchlab.har.HarCookie;
import edu.umass.cs.benchlab.har.HarCookies;
import edu.umass.cs.benchlab.har.HarEntry;
import edu.umass.cs.benchlab.har.HarEntryTimings;
import edu.umass.cs.benchlab.har.HarHeader;
import edu.umass.cs.benchlab.har.HarHeaders;
import edu.umass.cs.benchlab.har.HarPostData;
import edu.umass.cs.benchlab.har.HarPostDataParam;
import edu.umass.cs.benchlab.har.HarPostDataParams;
import edu.umass.cs.benchlab.har.HarQueryParam;
import edu.umass.cs.benchlab.har.HarQueryString;
import edu.umass.cs.benchlab.har.HarRequest;
import edu.umass.cs.benchlab.har.HarResponse;
import edu.umass.cs.benchlab.har.ISO8601DateFormatter;

/** Utils mostly related to creating a HAR file. **/
public class Utils {

    public static final String UTF8 = "UTF-8";
    public static final String SHA256 = "SHA-256";

    /** Prints the objects string value or "null" if null. **/
    public static void p(final Object o) {
        if (o == null) {
            System.out.println("null");
            return;
        }

        System.out.println(o.toString());
    }

    /** Prints an empty string. **/
    public static void p() {
        System.out.println();
    }

    /** Create a fake object until Vega adds support for timings. **/
    public static HarEntryTimings getFakeHarEntryTimings() {
        final long send = 0L;
        final long wait = 0L;
        final long receive = 0L;

        return new HarEntryTimings(send, wait, receive);
    }

    /**
     * Extracts headers from allHeaders and updates harHeaders and harCookies.
     * 
     * Returns the size of the headers (calculated by summing the length of
     * each name and value in UTF8 bytes).
     **/
    public static long extractHeadersAndCookies(final Header[] allHeaders, final HarHeaders harHeaders,
            final HarCookies harCookies) {

        long headersSize = 0;
        final CookieDecoder decoder = new CookieDecoder();
        final CookieDateFormat format = new CookieDateFormat();

        for (final Header header : allHeaders) {
            final String headerName = header.getName();
            final String headerValue = header.getValue();

            try {
                headersSize += headerName.getBytes(UTF8).length + headerValue.getBytes(UTF8).length;
            } catch (final UnsupportedEncodingException e1) {
                e1.printStackTrace();
            }

            harHeaders.addHeader(new HarHeader(headerName, headerValue));

            if (headerValue != null && headerName.equalsIgnoreCase("Cookie")) {
                final Set<Cookie> cookies = decoder.decode(headerValue);

                for (final Cookie cookie : cookies) {
                    Date expires = null;
                    final int maxAge = cookie.getMaxAge();

                    if (maxAge != -1) {
                        try {
                            // TODO: Is CookieDateFormat formatting maxAge
                            // properly?
                            expires = format.parse(format.format(maxAge));
                        } catch (final ParseException e) {
                            e.printStackTrace();
                        }
                    }
                    harCookies.addCookie(
                            new HarCookie(cookie.getName(), cookie.getValue(), cookie.getPath(), cookie.getDomain(),
                                    expires, cookie.isHttpOnly(), cookie.isSecure(), cookie.getComment()));
                }
            }
        }

        return headersSize;
    }

    /** Gets the headers value.  Returns null if header is null. **/
    public static String headerValue(final Header header) {
        if (header != null)
            return header.getValue();

        return null;
    }

    /** Request. **/
    public static HarRequest createHarRequest(final HttpRequest httpRequest, final HarvConfig config) {
        final RequestLine line = httpRequest.getRequestLine();

        final String method = line.getMethod();
        final String uri = line.getUri();
        final String httpVersion = line.getProtocolVersion().toString();

        final HarHeaders headers = new HarHeaders();
        final HarCookies cookies = new HarCookies();
        final long headersSize = extractHeadersAndCookies(httpRequest.getAllHeaders(), headers, cookies);

        final HarQueryString queryString = new HarQueryString();
        final QueryStringDecoder decoder = new QueryStringDecoder(uri);
        final List<HarQueryParam> queryStringParams = new ArrayList<HarQueryParam>();

        for (final Map.Entry<String, List<String>> param : decoder.getParameters().entrySet()) {
            final String name = param.getKey();
            // Create separate params for multiple values with the same key.
            // /test?t=1&t=2
            for (final String value : param.getValue()) {
                queryStringParams.add(new HarQueryParam(name, value));
            }
        }

        queryString.setQueryParams(queryStringParams);

        String comment = null;
        final String mimeType = headerValue(httpRequest.getFirstHeader("Content-Type"));
        String text = null;
        final HarPostDataParams postDataParams = new HarPostDataParams();
        long bodySize = -1;

        if (httpRequest instanceof HttpEntityEnclosingRequest) {
            try {
                final HttpEntity entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity();
                // Handle post data params.
                if (mimeType.toLowerCase().contains("application/x-www-form-urlencoded")) {
                    final String streamString = streamToString(entity.getContent());

                    for (final String nvString : streamString.split("&")) {
                        final String[] nvPair = nvString.split("=");
                        final String name = nvPair[0];
                        final String value = nvPair.length == 1 ? "" : nvPair[1];
                        postDataParams.addPostDataParam(new HarPostDataParam(name, value));
                    }
                } else {
                    if (config.isExternal()) {
                        final String sha256 = streamToFile(entity.getContent(), config.getEntityParentFolder());
                        comment = R.shaPrefix + sha256;
                    } else {
                        text = streamToString(entity.getContent());
                    }
                }

                bodySize = entity.getContentLength();
            } catch (final Exception e) {
                e.printStackTrace();
            }
        }

        // Either params or text is set, never both.
        final HarPostData postData = new HarPostData(mimeType, postDataParams, text, comment);

        // Set null comment for HarRequest.
        return new HarRequest(method, uri, httpVersion, cookies, headers, queryString, postData, headersSize,
                bodySize, null);
    }

    /** Converts stream to string. **/
    public static String streamToString(final InputStream input) {
        try {
            final byte[] dataBytes = new byte[input.available()];
            ByteStreams.readFully(input, dataBytes);

            return new String(dataBytes, UTF8);
        } catch (final Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * Calculate SHA-256 value of given input stream. Save input stream to file
     * using the digest for a name. Return the digest value as a string
     **/
    public static String streamToFile(final InputStream input, final String entityParentFolder) {
        String fileName = null;

        try {
            final byte[] dataBytes = new byte[input.available()];
            ByteStreams.readFully(input, dataBytes);

            // shasum -a 256 file.txt
            final MessageDigest sha256 = MessageDigest.getInstance(SHA256);
            final byte[] digest = ByteStreams.getDigest(ByteStreams.newInputStreamSupplier(dataBytes), sha256);

            fileName = Hex.encodeHexString(digest);
            Files.write(dataBytes, new File(entityParentFolder, fileName));
        } catch (final Exception e) {
            e.printStackTrace();
        }

        return fileName;
    }

    /** Response. **/
    public static HarResponse createHarResponse(final HttpResponse httpResponse, final HarvConfig config) {
        final StatusLine responseStatus = httpResponse.getStatusLine();
        final int status = responseStatus.getStatusCode();
        final String statusText = responseStatus.getReasonPhrase();
        final String responseHttpVersion = httpResponse.getProtocolVersion().toString();

        final HarCookies cookies = new HarCookies();
        final HarHeaders headers = new HarHeaders();

        final long headersSize = extractHeadersAndCookies(httpResponse.getAllHeaders(), headers, cookies);

        long size = -1;
        String mimeType = "";
        String encoding = "";

        final HttpEntity entity = httpResponse.getEntity();
        if (entity != null) {
            size = entity.getContentLength();
            // TODO: Will mimeType be set properly?
            mimeType = headerValue(entity.getContentType());
            encoding = headerValue(entity.getContentEncoding());
        }

        // Compression is not implemented.
        final long compression = 0;
        String text = null;
        String comment = null;
        try {
            if (config.isExternal()) {
                final String sha256 = streamToFile(entity.getContent(), config.getEntityParentFolder());
                comment = R.shaPrefix + sha256;
            } else {
                text = streamToString(entity.getContent());
            }
        } catch (final Exception e) {
            e.printStackTrace();
        }

        // Does Location always represent the redirect URL?
        final String redirectURL = headerValue(httpResponse.getFirstHeader("Location"));
        final long bodySize = size;

        final HarContent content = new HarContent(size, compression, mimeType, text, encoding, comment);

        // Set null comment for HarResponse.
        return new HarResponse(status, statusText, responseHttpVersion, cookies, headers, content, redirectURL,
                headersSize, bodySize, null);

    }

    /** Converts a list of IRequestLogRecord to a single HAR file. **/
    public static void convertRecordsToHAR(final List<IRequestLogRecord> recordsList, final Harv har,
            final HarvConfig config) {

        for (final IRequestLogRecord record : recordsList) {

            final String pageRef = null;
            Date startedDateTime = null;

            try {
                startedDateTime = ISO8601DateFormatter
                        .parseDate(ISO8601DateFormatter.format(new Date(record.getTimestamp())));
            } catch (final ParseException e) {
                e.printStackTrace();
            }

            final long time = record.getRequestMilliseconds();
            final HarRequest request = createHarRequest(record.getRequest(), config);
            final HarResponse response = createHarResponse(record.getResponse(), config);
            final HarCache cache = null;
            final HarEntryTimings timings = getFakeHarEntryTimings();
            final String serverIPAddress = null;
            final String connection = String.valueOf(record.getRequestId());
            final String comment = null;

            // Har entry is now complete.
            har.addEntry(new HarEntry(pageRef, startedDateTime, time, request, response, cache, timings,
                    serverIPAddress, connection, comment));
        }
    }

    /** Should end with the number /user/workspace/00 **/
    public static IWorkspace openWorkspacePath(final String path) {
        return openWorkspaceFile(new File(path));
    }

    /** Opens a workspace based on the file path. **/
    public static IWorkspace openWorkspaceFile(final File ws) {
        final IWorkspaceEntry entry = (IWorkspaceEntry) invokeStatic(WorkspaceEntry.class, "createFromPath", ws);

        final IModel model = new Model();
        invoke(model, "openWorkspaceEntry", entry);

        final IWorkspace openWorkspace = model.getCurrentWorkspace();

        if (openWorkspace == null) {
            p("open workspace failed");
            return null;
        }

        return openWorkspace;
    }

    /** wsNumber must be a string because "00" converts to "0" as an int. **/
    public static IWorkspace openWorkspaceByNumber(final String wsNumber) {
        final File ws = getDefaultWorkspace(wsNumber);

        return openWorkspaceFile(ws);
    }

    /** wsNumber must be a string because "00" converts to "0" as an int. **/
    public static File getDefaultWorkspace(final String wsNumber) {
        final File ws = new File(System.getProperty("user.home"),
                ".vega" + File.separator + "workspaces" + File.separator + wsNumber);
        return ws;
    }
}