net.opentracker.android.OTSend.java Source code

Java tutorial

Introduction

Here is the source code for net.opentracker.android.OTSend.java

Source

/*
 *  Copyright (C) 2011 Opentracker.net 
 * 
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 * 
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 * 
 *  The full license is located at the root of this distribution
 *  in the LICENSE file.
 *
 *  Please report bugs to support@opentracker.net
 *
 */
package net.opentracker.android;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

/**
 * OTSend provides methods for sending key value pairs to Opentracker's logging/
 * analytics engines via HTTP POST requests, and uploading (compressed) files.
 * 
 * For the HTTP POST requests to work on android you must declare Internet
 * permissions in your apps manifest by adding the following line to
 * AndroidManifest.xml. This allows your application to use any Internet
 * connections.
 * 
 * The application will need the following android permissions defined:
 * <uses-permission android:name="android.permission.INTERNET" />
 * 
 * @author $Author: eddie $ (latest svn author)
 * @version $Id: OTSend.java 14171 2012-03-08 15:32:37Z eddie $
 */
public class OTSend {

    private static final String boundary = "*****";

    private static byte[] buffer;

    private static int bytesRead, bytesAvailable, bufferSize;

    private static HttpURLConnection conn = null;

    /*
     * The default socket timeout (SO_TIMEOUT) in milliseconds which is the
     * timeout for waiting for data. A timeout value of zero is interpreted as
     * an infinite timeout. This value is used when no socket timeout is set in
     * the HTTP method parameters.
     */
    private static final int HTTP_SOCKET_TIMEOUT = 3000;

    public static final String DEFAULT_LOG_URL = "http://log.opentracker.net/";

    private static final String DEFAULT_UPLOAD_SERVER = "http://upload.opentracker.net/upload/upload.jsp";

    private static DataOutputStream dos = null;

    private static DataInputStream inStream = null;

    private static final String lineEnd = "\r\n";

    private static final int maxBufferSize = 1 * 1024 * 1024;

    private static final String TAG = OTSend.class.getName();

    private static final String twoHyphens = "--";

    /**
     * getResponseBody function gives out the HTTP POST data from the given
     * httpResponse output: data from the http as string input : httpEntity type
     * 
     * based on:
     * http://thinkandroid.wordpress.com/2009/12/30/getting-response-body
     * -of-httpresponse/
     */
    private static String getResponseBody(final HttpEntity entity) throws IOException, ParseException {
        LogWrapper.v(TAG, "getResponseBody(final HttpEntity entity)");

        if (entity == null) {
            throw new IllegalArgumentException("HTTP entity may not be null");
        }
        InputStream instream = entity.getContent();
        if (instream == null) {
            return "";
        }
        if (entity.getContentLength() > Integer.MAX_VALUE) {
            throw new IllegalArgumentException("HTTP entity too large to be buffered in memory");
        }
        String charset = EntityUtils.getContentCharSet(entity);
        if (charset == null) {
            charset = HTTP.DEFAULT_CONTENT_CHARSET;
        }
        Reader reader = new InputStreamReader(instream, charset);
        StringBuilder buffer = new StringBuilder();
        try {
            char[] tmp = new char[1024];
            int l;
            while ((l = reader.read(tmp)) != -1) {
                buffer.append(tmp, 0, l);
            }
        } finally {
            reader.close();
        }
        return buffer.toString();
    }

    /**
     * Sends the key value pairs to Opentracker's logging/ analytics engines via
     * HTTP POST requests.
     * 
     * Based on sending key value pairs documentated at:
     * http://api.opentracker.net/api/inserts/insert_event.jsp
     * 
     * @param keyValuePairs
     *            the key value pairs (plain text utf-8 strings) to send to the
     *            logging service.
     * 
     * @return the response as string, null if an exception is caught
     */
    protected static String send(HashMap<String, String> keyValuePairs) {
        LogWrapper.v(TAG, "send(HashMap<String, String> keyValuePairs)");

        // http://www.wikihow.com/Execute-HTTP-POST-Requests-in-Android
        // http://hc.apache.org/httpclient-3.x/tutorial.html
        HttpClient client = new DefaultHttpClient();

        // time to wait before throwing timeout exception
        client.getParams().setParameter("http.socket.timeout", new Integer(HTTP_SOCKET_TIMEOUT));

        HttpPost post = new HttpPost(DEFAULT_LOG_URL);
        post.getParams().setParameter("http.socket.timeout", new Integer(HTTP_SOCKET_TIMEOUT));

        Iterator<Entry<String, String>> it = keyValuePairs.entrySet().iterator();

        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        while (it.hasNext()) {

            Map.Entry<String, String> pair = (Map.Entry<String, String>) it.next();
            pairs.add(new BasicNameValuePair(pair.getKey(), pair.getValue()));
            if (pair.getKey().equals("ots") || pair.getKey().equals("otui"))
                LogWrapper.v(TAG, pair.getKey() + " = " + pair.getValue());
            else
                LogWrapper.v(TAG, pair.getKey() + " = " + pair.getValue());

        }

        String responseText = null;
        try {

            post.setEntity(new UrlEncodedFormEntity(pairs));
            HttpResponse response = client.execute(post);
            HttpEntity entity = response.getEntity();

            // http://hc.apache.org/httpclient-3.x/tutorial.html
            // It is vital that the response body is always read regardless of
            // the status returned by the server.
            responseText = getResponseBody(entity);

            LogWrapper.v(TAG, "Success url:" + post.getURI());
            LogWrapper.v(TAG, "Success url:" + pairs);
            return responseText;

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            LogWrapper.w(TAG, "Failed:" + e);
        } catch (UnknownHostException e) {
            e.printStackTrace();
            LogWrapper.w(TAG, "Failed:" + e);
        } catch (IOException e) {
            e.printStackTrace();
            LogWrapper.w(TAG, "Failed:" + e);
        } catch (ParseException e) {
            e.printStackTrace();
            LogWrapper.w(TAG, "Failed:" + e);
        }
        LogWrapper.e(TAG, "Got response " + responseText);
        return responseText;
    }

    /**
     * Method used for uploading a file to the default upload server
     * 
     * 
     * @param pathName
     *            The path to use taking the apps context into account
     * @param fileName
     *            The file name to append to
     */
    protected static boolean uploadFile(String pathName, String fileName) {
        LogWrapper.v(TAG, "uploadFile(String pathName, String fileName)");
        return uploadFile(DEFAULT_UPLOAD_SERVER, pathName, fileName);
    }

    /**
     * Method used for uploading a file to a server;
     * 
     * @param uploadServer
     *            The server to upload the file to
     * @param internalPathName
     *            The path to use taking the apps context into account
     * @param fileName
     *            The file name to append to
     */
    private static boolean uploadFile(String uploadServer, String internalPathName, String fileName) {
        LogWrapper.v(TAG, "uploadFile(uploadServer, pathName, fileName)");

        String randomFileName = UUID.randomUUID() + ".gz";

        try {
            // ------------------ CLIENT REQUEST
            FileInputStream fileInputStream = new FileInputStream(new File(internalPathName + fileName));

            // Open a URL connection to the Servlet
            URL url = new URL(uploadServer);

            // Open a HTTP connection to the URLs
            conn = (HttpURLConnection) url.openConnection();

            // Allow Inputs
            conn.setDoInput(true);

            // Allow Outputs
            conn.setDoOutput(true);

            // Don't use a cached copy.
            conn.setUseCaches(false);

            // Use a post method.
            conn.setRequestMethod("POST");

            conn.setRequestProperty("Connection", "Keep-Alive");

            conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

            dos = new DataOutputStream(conn.getOutputStream());

            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=\"upload\";" + " filename=\"" + randomFileName
                    + "\"" + lineEnd);
            dos.writeBytes(lineEnd);

            // create a buffer of maximum size
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            buffer = new byte[bufferSize];

            // read file and write it into form...
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);

            while (bytesRead > 0) {
                dos.write(buffer, 0, bufferSize);
                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);
            }

            // send multipart form data necesssary after file data...
            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

            // close streams
            fileInputStream.close();
            dos.flush();
            dos.close();

        } catch (MalformedURLException ex) {
            LogWrapper.w(TAG, "From ServletCom CLIENT REQUEST: " + ex);
            return false;
        } catch (IOException ioe) {
            LogWrapper.w(TAG, "From ServletCom CLIENT REQUEST: " + ioe);
            return false;
        }

        // ------------------ read the SERVER RESPONSE
        try {
            inStream = new DataInputStream(conn.getInputStream());
            String str;
            while ((str = inStream.readLine()) != null) {
                LogWrapper.v(TAG, "Server response: " + str);
            }
            inStream.close();
            return true;

        } catch (IOException ioex) {
            LogWrapper.w(TAG, "Server response: " + ioex);
            return false;
        }

    }

    private OTSend() {
    }

}