com.auditmark.jscrambler.client.JScrambler.java Source code

Java tutorial

Introduction

Here is the source code for com.auditmark.jscrambler.client.JScrambler.java

Source

/*
 * Copyright 2014, 2014 AuditMark
 *
 * This program 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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.
 *
 * You should have received a copy of the Lesser GPL
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package com.auditmark.jscrambler.client;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class JScrambler {

    private String accessKey, secretKey, apiHost;
    private int apiPort, apiVersion;

    public JScrambler(String accessKey, String secretKey) {
        this.accessKey = accessKey;
        this.secretKey = secretKey;
        apiHost = "api.jscrambler.com";
        apiPort = 80;
        this.apiVersion = 3;
    }

    public JScrambler(String accessKey, String secretKey, String apiHost) {
        this(accessKey, secretKey);
        if (apiHost != null) {
            this.apiHost = apiHost;
        }
    }

    public JScrambler(String accessKey, String secretKey, String apiHost, Integer apiPort) {
        this(accessKey, secretKey, apiHost);
        if (apiPort != null) {
            this.apiPort = apiPort;
        }
    }

    public JScrambler(String accessKey, String secretKey, String apiHost, Integer apiPort, Integer apiVersion) {
        this(accessKey, secretKey, apiHost, apiPort);
        if (apiVersion != null) {
            this.apiVersion = apiVersion;
        }
    }

    /**
     * If the content-type of the response equals application/zip returns an
     * inputstream. Otherwise returns a string.
     * 
     * @param resourcePath
     * @param params
     * @return 
     */
    public Object get(String resourcePath, Map params) {
        try {
            return httpRequest("GET", resourcePath, params);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    public Object get(String resourcePath) {
        return get(resourcePath, null);
    }

    public String post(String resourcePath, Map params) {
        try {
            return (String) httpRequest("POST", resourcePath, params);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    public String delete(String resourcePath, Map params) {
        try {
            return (String) httpRequest("DELETE", resourcePath, params);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    public String delete(String resourcePath) {
        return delete(resourcePath, null);
    }

    private String apiURL() {
        return "http" + (apiPort == 443 ? "s" : "") + "://" + apiHost + (apiPort != 80 ? (":" + apiPort) : "")
                + "/v" + apiVersion;
    }

    private Object httpRequest(String requestMethod, String resourcePath, Map params)
            throws IOException, Exception {

        String signedData = null, urlQueryPart = null;

        if (requestMethod.toUpperCase().equals("POST") && params.isEmpty()) {
            throw new IllegalArgumentException("Parameters missing for POST request.");
        }

        String[] files = null;

        if (params == null) {
            params = new TreeMap();
        } else {
            if (params.get("files") instanceof String) {
                files = new String[] { (String) params.get("files") };
                params.put("files", files);
            } else if (params.get("files") instanceof String[]) {
                files = (String[]) params.get("files");
            }
            params = new TreeMap(params);
        }

        if (requestMethod.toUpperCase().equals("POST")) {
            signedData = signedQuery(requestMethod, resourcePath, params, null);
        } else {
            urlQueryPart = "?" + signedQuery(requestMethod, resourcePath, params, null);
        }

        // http client
        HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response = null;

        try {
            if (signedData != null && requestMethod.toUpperCase().equals("POST")) {
                HttpPost httppost = new HttpPost(
                        apiURL() + resourcePath + (urlQueryPart != null ? urlQueryPart : ""));
                MultipartEntity reqEntity = new MultipartEntity();

                if (files != null) {
                    int n = 0;
                    for (String filename : files) {
                        FileBody fb = new FileBody(new File(filename));
                        reqEntity.addPart("file_" + n++, fb);
                    }
                }

                for (String param : (Set<String>) params.keySet()) {
                    if (param.equals("files") || param.startsWith("file_")) {
                        continue;
                    }
                    if (params.get(param) instanceof String) {
                        reqEntity.addPart(param, new StringBody((String) params.get(param)));
                    }
                }

                httppost.setEntity(reqEntity);
                response = httpclient.execute(httppost);

            } else if (requestMethod.toUpperCase().equals("GET")) {
                HttpGet request = new HttpGet(apiURL() + resourcePath + (urlQueryPart != null ? urlQueryPart : ""));
                response = httpclient.execute(request);
            } else if (requestMethod.toUpperCase().equals("DELETE")) {
                HttpDelete request = new HttpDelete(
                        apiURL() + resourcePath + (urlQueryPart != null ? urlQueryPart : ""));
                response = httpclient.execute(request);
            } else {
                throw new Exception("Invalid request method.");
            }

            HttpEntity httpEntity = response.getEntity();

            // if GET Zip archive
            if (requestMethod.toUpperCase().equals("GET") && resourcePath.toLowerCase().endsWith(".zip")
                    && response.getStatusLine().getStatusCode() == 200) {
                // Return inputstream
                return httpEntity.getContent();
            }
            // Otherwise return string
            return EntityUtils.toString(httpEntity, "UTF-8");

        } catch (IOException e) {
            throw e;
        } catch (Exception e) {
            throw e;
        }
    }

    private String signedQuery(String requestMethod, String resourcePath, Map params, SimpleDateFormat timestamp)
            throws FileNotFoundException, InvalidKeyException, NoSuchAlgorithmException, IOException, Exception {
        Map signedParams = signedParams(requestMethod, resourcePath, params, timestamp);
        return urlQueryString(signedParams);
    }

    private Map signedParams(String requestMethod, String resourcePath, Map params, SimpleDateFormat timestamp)
            throws FileNotFoundException, InvalidKeyException, NoSuchAlgorithmException, IOException, Exception {
        if (requestMethod.toUpperCase().equals("POST") && params.containsKey("files")) {
            Map fileParams = constructFileParams((String[]) params.get("files"));
            params.remove("files");
            params.putAll(fileParams);
        }
        params.put("timestamp", (timestamp != null ? timestamp
                : (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")).format(new Date()).toString()));
        params.put("access_key", accessKey);
        params.put("user_agent", "Java");
        params.put("signature", generateHMACSignature(requestMethod, resourcePath, params));
        return params;
    }

    private static Map constructFileParams(String[] files) throws FileNotFoundException, IOException, Exception {
        int counter = 0;
        Map map = new HashMap();
        for (String filePath : files) {
            File file = new File(filePath);
            StringBuilder contents = new StringBuilder();
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new FileReader(file));
                String text;
                while ((text = reader.readLine()) != null) {
                    contents.append(text).append(System.getProperty("line.separator"));
                }
                map.put("file_" + (counter++), md5sum(filePath));
            } catch (FileNotFoundException e) {
                System.err.println("File '" + filePath + "' not found.");
                throw e;
            } catch (IOException e) {
                throw e;
            } finally {
                try {
                    if (reader != null) {
                        reader.close();
                    }
                } catch (IOException e) {
                    throw e;
                }
            }
        }
        return map;
    }

    private static String md5sum(String filePath) throws Exception {
        try {
            byte[] b = createChecksum(filePath);
            String result = "";
            for (int i = 0; i < b.length; i++) {
                result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
            }
            return result;
        } catch (Exception e) {
            throw e;
        }
    }

    private static byte[] createChecksum(String filename) throws Exception {
        InputStream fis = new FileInputStream(filename);
        byte[] buffer = new byte[1024];
        MessageDigest complete = MessageDigest.getInstance("MD5");
        int numRead;
        do {
            numRead = fis.read(buffer);
            if (numRead > 0) {
                complete.update(buffer, 0, numRead);
            }
        } while (numRead != -1);
        fis.close();
        return complete.digest();
    }

    private String generateHMACSignature(String requestMethod, String resourcePath, Map<String, String> params)
            throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
        String data = hmacSignatureData(requestMethod, resourcePath, apiHost, params);
        try {
            SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(signingKey);
            byte[] digest = mac.doFinal(data.getBytes());
            return new sun.misc.BASE64Encoder().encode(digest);

        } catch (InvalidKeyException e) {
            System.err.println("Invalid key: " + e.getMessage());
            throw e;
        } catch (NoSuchAlgorithmException e) {
            System.err.println("No such algorithm: " + e.getMessage());
            throw e;
        }
    }

    private String hmacSignatureData(String requestMethod, String resourcePath, String host,
            Map<String, String> params) throws UnsupportedEncodingException {
        return requestMethod.toUpperCase() + ";" + host.toLowerCase() + ";" + resourcePath + ";"
                + urlQueryString(params);
    }

    private static String urlQueryString(Map<String, String> params) throws UnsupportedEncodingException {
        TreeSet<String> keys = new TreeSet<String>(params.keySet());
        String query = "";
        for (String key : keys) {
            Object obj = params.get(key);
            if (obj.getClass().toString().equals(new String().getClass().toString())) {
                String value = params.get(key);
                query += urlEncode(key) + "=" + urlEncode(value) + "&";
            }
        }
        return query.substring(0, query.length() - 1);
    }

    private static String urlEncode(String data) throws UnsupportedEncodingException {
        String encodedStr = null;
        try {
            encodedStr = java.net.URLEncoder.encode(data, "UTF-8");
            encodedStr = encodedStr.replace("%7E", "~");
            encodedStr = encodedStr.replace("+", "%20");
            encodedStr = encodedStr.replace("*", "%2A");
        } catch (UnsupportedEncodingException e) {
            throw e;
        }
        return encodedStr;
    }

    public static final int SUCCESS = 0;
}