Friday, November 13, 2015

The Jira Auto Filer

This code uses the JIRA Rest API to gather information about issue types.  It also builds curl commands as well as links for bug filing.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
//Include dependency in pom.xml file
//<dependency>
//<groupId>net.sourceforge.htmlunit</groupId>
//<artifactId>htmlunit</artifactId>
//<version>2.13</version>
//</dependency>
import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
//Include dependency in pom.xml file
//<dependency>
//    <groupId>org.json</groupId>
//    <artifactId>json</artifactId>
//    <version>20080701</version>
//</dependency>
import org.json.JSONArray;
import org.json.JSONObject;

public class JiraAutoFiler {
    public static String JIRA_HOST = "jira.com";
    public static String JIRA_USERNAME = "myusername";
    public static String JIRA_PASSWORD = "password";

    public static IssueTypeAttributes addJIRAIssueInformation(String projectKey, String issueTypeID) {
        IssueTypeAttributes issueTypeAttributes = new IssueTypeAttributes();
        issueTypeAttributes.projectKey = projectKey;
        issueTypeAttributes.issueTypeID = issueTypeID;

        try {
            System.out.println("Step 1a: Setup Authentication Information");
    
            System.out.println("Step 1b: Install SSL Certificate");        
            SSLHandler.setupSSLContextByInstallingCertification(JIRA_HOST);
    
            System.out.println("Step 2: Query Server for Projects");    
            HttpGet httpGet = new HttpGet("https://"+JIRA_HOST+"/rest/api/2/issue/createmeta?projectKeys="+issueTypeAttributes.projectKey+"&issuetypeIds="+issueTypeAttributes.issueTypeID+"&expand=projects.issuetypes.fields");
            String basic_auth = new String(Base64.encodeBase64((JIRA_USERNAME+":"+JIRA_PASSWORD).getBytes())); // 
            httpGet.addHeader("Authorization""Basic " + basic_auth);
            CloseableHttpResponse response = new DefaultHttpClient().execute(httpGet);
            String projectResponsJSON = EntityUtils.toString(response.getEntity());
            response.close();
            System.out.println("projectResponse:"+projectResponsJSON);
            
            JSONObject metaData = new JSONObject(projectResponsJSON);
            JSONArray projects = metaData.getJSONArray("projects");
//            holder.errorMessages = holder.errorMessages + projects.toString();
            JSONObject project = projects.getJSONObject(0);
//            holder.errorMessages = holder.errorMessages + project.toString();
            issueTypeAttributes.jiraProjectName = project.getString("name");
            issueTypeAttributes.jiraProjectID = project.getString("id");
            JSONArray issuetypes = project.getJSONArray("issuetypes");
            JSONObject issuetype = issuetypes.getJSONObject(0);
            issueTypeAttributes.issueName = issuetype.getString("name");
            JSONObject fields = issuetype.getJSONObject("fields");
                    
            for(String fieldName: JSONObject.getNames(fields)) {
                JSONObject fieldJSON = fields.getJSONObject(fieldName);
                IssueTypeFieldAttributes field = new IssueTypeFieldAttributes();
                field.fieldName = fieldName;
                field.fieldDisplayName = fieldJSON.getString("name");
                field.isRequired = fieldJSON.getBoolean("required");
                JSONObject schema = fieldJSON.getJSONObject("schema");
                field.type = schema.getString("type");
                try {
                    JSONArray allowedValues = fieldJSON.getJSONArray("allowedValues");
                    for (int i = 0; i < allowedValues.length(); i++) {
                        JSONObject allowedValueJSON = allowedValues.getJSONObject(i);
                        IssueTypeFieldAllowedValue allowedValue = new IssueTypeFieldAllowedValue();
                        allowedValue.valueID = allowedValueJSON.getString("id");
                        allowedValue.valueName = allowedValueJSON.getString("value");
                        field.allowedValues.add(allowedValue);
                    }
                } catch (Exception ex) {}
                
                issueTypeAttributes.fields.add(field);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        return issueTypeAttributes;
    }

    public static class IssueTypeAttributes{
        public String projectKey;
        public String issueTypeID;
        public String jiraProjectName;
        public String jiraProjectID;
        public String issueName;
        public List<IssueTypeFieldAttributes> fields = new ArrayList<IssueTypeFieldAttributes>();
        
        public String buildCURLCommand() {
            String curlCommand = "curl -k -H \"Content-Type: application/json\" -D- -X POST --data \'{\"fields\": {";
            curlCommand = curlCommand + "\"project\":{\"key\":\""+projectKey+"\"}, \"issuetype\": {\"id\":\""+issueTypeID+"\"}";
            for(IssueTypeFieldAttributes field: fields) {
                if(field.isRequired && (field.type.equals("string") || field.type.equals("array"))) {
                    String defaultValue = null;
                    try {
                        defaultValue = "{\"id\":\""+field.allowedValues.get(0).valueID+"\"}";
                    } catch (Exception ex) {
                        defaultValue = "\"Test\"";
                    }
                    if(field.type.equals("string")) {
                        curlCommand = curlCommand + ", \""+field.fieldName+"\":"+defaultValue;
                    } else if (field.type.equals("array")) {
                        curlCommand = curlCommand + ", \""+field.fieldName+"\":["+defaultValue+"]";
                    }
                }
            }
            curlCommand = curlCommand + "}}\' https://"+JIRA_HOST+"/rest/api/2/issue -u "+JIRA_USERNAME; 
            return curlCommand;
        }
        
        public String buildJSPALink() {
            String jspaLink = "https://"+JIRA_HOST+"/secure/CreateIssueDetails!init.jspa?";
            jspaLink = jspaLink + "pid="+ jiraProjectID +"&issuetype="+issueTypeID;    
            for(IssueTypeFieldAttributes field: fields) {
                if(field.isRequired && (field.type.equals("string") || field.type.equals("array"))) {
                    String defaultValueID = null;
                    try {
                        defaultValueID = field.allowedValues.get(0).valueID;
                    } catch (Exception ex) {
                        defaultValueID = "Test";
                    }
                    jspaLink = jspaLink + "&"+field.fieldName+"="+defaultValueID;
                }
            }
            return jspaLink;
        }
    }
    public static class IssueTypeFieldAttributes{
        public String fieldName;
        public String fieldDisplayName;
        public Boolean isRequired;
        public String type;
        public List<IssueTypeFieldAllowedValue> allowedValues = new ArrayList<IssueTypeFieldAllowedValue>();
    }
    public static class IssueTypeFieldAllowedValue{
        public String valueID;
        public String valueName;
    }
    
    public static class SSLHandler{

        /**
         * Should be called right before connection
         * 
         * Installs C:\Program Files\Java\jdk1.7.0_51\jre\lib\security\jssecacerts file
         * @param host
         * @throws Exception
         */

        static Set<String> hostsInstalled = new HashSet<String>();
        public static void setupSSLContextByInstallingCertification(String host) {
            if(hostsInstalled.contains(host)) {
                return;
            } else {
                hostsInstalled.add(host);
            }
            System.out.println("Installing SSLContext Certification into Java Home...");
            try {
                int port = 443;
                char[] passphrase = "changeit".toCharArray();
                
                char SEP = File.separatorChar;
                File file = new File("jssecacerts");
                if (file.isFile() == false) {
                    File dir = new File(System.getProperty("java.home") + SEP
                            + "lib" + SEP + "security");
                    file = new File(dir, "jssecacerts");
                    if (file.isFile() == false) {
                        file = new File(dir, "cacerts");
                    }
                }
                
                System.out.println("Loading KeyStore " + file + "...");
                InputStream in = new FileInputStream(file);
                KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
                ks.load(in, passphrase);
                in.close();
         
                TrustManagerFactory tmf =
                        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                tmf.init(ks);
                final X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
                final List<X509Certificate> chainList = new ArrayList<X509Certificate>();
                
                TrustManager tm = new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                                    throws CertificateException { }
                    public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                            throws CertificateException {
                            chainList.clear();
                            if(arg0 != null) {
                                for (int i = 0; i < arg0.length; i++) {
                                    chainList.add(arg0[i]);
                                }
                            }
                            defaultTrustManager.checkServerTrusted(arg0, arg1); }
                    public X509Certificate[] getAcceptedIssuers() { return null; }
                };
                
                SSLContext context = SSLContext.getInstance("TLS");
                context.init(nullnew TrustManager[]{tm}, null);
                SSLSocketFactory factory = context.getSocketFactory();
         
                System.out.println("Opening connection to " + host + ":" + port + "...");
                SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
                socket.setSoTimeout(10000);
                try {
                    socket.startHandshake();
                    System.out.println("No errors, certificate is already trusted");
                } catch (SSLException e) { }
                socket.close();
         
                if (chainList.isEmpty()) {
                    System.out.println("Could not obtain server certificate chain");
                    return;
                }
         
                System.out.println("Server sent " + chainList.size() + " certificate(s):");

                MessageDigest sha1 = MessageDigest.getInstance("SHA1");
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                for (int i = 0; i < chainList.size(); i++) {
                    X509Certificate cert = chainList.get(i);
                    System.out.println
                            (" " + (i + 1) + " Subject " + cert.getSubjectDN());
                    System.out.println("   Issuer  " + cert.getIssuerDN());
                    sha1.update(cert.getEncoded());
                    System.out.println("   sha1    " + toHexString(sha1.digest()));
                    md5.update(cert.getEncoded());
                    System.out.println("   md5     " + toHexString(md5.digest()));
                }
                
                int k = 0;
                X509Certificate cert = chainList.get(k);
                String alias = host + "-" + (k + 1);
                ks.setCertificateEntry(alias, cert);
         
                File dir = new File(System.getProperty("java.home") + SEP
                        + "lib" + SEP + "security");
                file = new File(dir, "jssecacerts");
                OutputStream out = new FileOutputStream(file);
                ks.store(out, passphrase);
                out.close();
                
                System.out.println("Installed SSLContext Certification into Java Home: "+file.getAbsolutePath());
            } catch (Exception ex) { }
        }
     
        private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
     
        private static String toHexString(byte[] bytes) {
            StringBuilder sb = new StringBuilder(bytes.length * 3);
            for (int b : bytes) {
                b &= 0xff;
                sb.append(HEXDIGITS[b >> 4]);
                sb.append(HEXDIGITS[b & 15]);
                sb.append(' ');
            }
            return sb.toString();
        }
    }
}

Thursday, November 5, 2015

Calculating Loan Amortization with Monthly Compounding and Quarterly Payments

Say you have a loan for $100,000 and the interest rate is 17.7802%.  Payments are made quarterly in the amount of $10,500.  Here would be your payment schedule.

 
month:0      before interest balance:100000
month:0      after interest balance:101481.68333333333      interest:1481.6833333333332
month:1      before interest balance:101481.68333333333
month:1      after interest balance:102985.32052166945      interest:1503.637188336111
month:2      before interest balance:102985.32052166945
month:2      after interest balance:104511.23685161893      interest:1525.9163299494892
month:2      after payment balance:94011.23685161893      payment:10500
month:3      before interest balance:94011.23685161893
month:3      after interest balance:95404.18567950989      interest:1392.9488278909623
month:4      before interest balance:95404.18567950989
month:4      after interest balance:96817.77359802557      interest:1413.5879185156846
month:5      before interest balance:96817.77359802557
month:5      after interest balance:98252.30641313191      interest:1434.532815106345
month:5      after payment balance:87752.30641313191      payment:10500
month:6      before interest balance:87752.30641313191
month:6      after interest balance:89052.51771187088      interest:1300.2112987389733
month:7      before interest balance:89052.51771187088
month:7      after interest balance:90371.99402472138      interest:1319.4763128505053
month:8      before interest balance:90371.99402472138
month:8      after interest balance:91711.02079818667      interest:1339.0267734652925
month:8      after payment balance:81211.02079818667      payment:10500
month:9      before interest balance:81211.02079818667
month:9      after interest balance:82414.31095818327      interest:1203.2901599965987
month:10      before interest balance:82414.31095818327
month:10      after interest balance:83635.43006793218      interest:1221.1191097489084
month:11      before interest balance:83635.43006793218
month:11      after interest balance:84874.64229601038      interest:1239.2122280782062
month:11      after payment balance:74374.64229601038      payment:10500
month:12      before interest balance:74374.64229601038
month:12      after interest balance:75476.63897513665      interest:1101.9966791262698
month:13      before interest balance:75476.63897513665
month:13      after interest balance:76594.96375539142      interest:1118.3247802547705
month:14      before interest balance:76594.96375539142
month:14      after interest balance:77729.85856752776      interest:1134.8948121363421
month:14      after payment balance:67229.85856752776      payment:10500
month:15      before interest balance:67229.85856752776
month:15      after interest balance:68225.99217694638      interest:996.1336094186308
month:16      before interest balance:68225.99217694638
month:16      after interest balance:69236.8853320335      interest:1010.8931550871183
month:17      before interest balance:69236.8853320335
month:17      after interest balance:70262.75672251736      interest:1025.8713904838517
month:17      after payment balance:59762.756722517355      payment:10500
month:18      before interest balance:59762.756722517355
month:18      after interest balance:60648.25152841544      interest:885.4948058980858
month:19      before interest balance:60648.25152841544
month:19      after interest balance:61546.86656327005      interest:898.6150348546101
month:20      before interest balance:61546.86656327005
month:20      after interest balance:62458.79622732693      interest:911.9296640568783
month:20      after payment balance:51958.79622732693      payment:10500
month:21      before interest balance:51958.79622732693
month:21      after interest balance:52728.661051227864      interest:769.8648239009318
month:22      before interest balance:52728.661051227864
month:22      after interest balance:53509.93283391373      interest:781.271782685868
month:23      before interest balance:53509.93283391373
month:23      after interest balance:54302.78059039169      interest:792.8477564779606
month:23      after payment balance:43802.78059039169      payment:10500
month:24      before interest balance:43802.78059039169
month:24      after interest balance:44451.79908993609      interest:649.0184995444018
month:25      before interest balance:44451.79908993609
month:25      after interest balance:45110.43398841849      interest:658.6348984824014
month:26      before interest balance:45110.43398841849
month:26      after interest balance:45778.82777041922      interest:668.3937820007319
month:26      after payment balance:35278.82777041922      payment:10500
month:27      before interest balance:35278.82777041922
month:27      after interest balance:35801.5482816889      interest:522.7205112696732
month:28      before interest balance:35801.5482816889
month:28      after interest balance:36332.01385565397      interest:530.4655739650708
month:29      before interest balance:36332.01385565397
month:29      after interest balance:36870.33924961755      interest:538.3253939635822
month:29      after payment balance:26370.33924961755      payment:10500
month:30      before interest balance:26370.33924961755
month:30      after interest balance:26761.06417122259      interest:390.72492160504163
month:31      before interest balance:26761.06417122259
month:31      after interest balance:27157.578398870235      interest:396.5142276476433
month:32      before interest balance:27157.578398870235
month:32      after interest balance:27559.96771174323      interest:402.38931287299374
month:32      after payment balance:17059.96771174323      payment:10500
month:33      before interest balance:17059.96771174323
month:33      after interest balance:17312.742410000177      interest:252.77469825694746
month:34      before interest balance:17312.742410000177
month:34      after interest balance:17569.26242883208      interest:256.5200188319043
month:35      before interest balance:17569.26242883208
month:35      after interest balance:17829.58326202968      interest:260.3208331976001
month:35      after payment balance:7329.583262029679      payment:10500

Here is the algorithm used to calculate this:


<html> 
<body> 
<pre> 
<script> 
function log(arg) { 
    document.body.innerHTML = document.body.innerHTML + arg + '\n<br>'

function clear() { 
    document.body.innerHTML = ''


var rate = .177802;
var balance = 100000;
var payment = 10500;

for(var i=0; i<12; i++){
    for(var j=0; j<3; j++) {
        log('month:'+(i*3+j)+'      before interest balance:'+balance);
        var interest = balance*rate/12;
        balance = balance + interest;
        log('month:'+(i*3+j)+'      after interest balance:'+balance+'      interest:' + interest);
    
    if(j == 2) {
        balance = balance - payment;
            log('month:'+(i*3+j)+'      after payment balance:'+balance+'      payment:' + payment);
        }
    }
}

</script> 
</pre> 
</body> 
</html>

Friday, October 9, 2015

Making Sense of Sonar Qube Stats like Unit Test Coverage, Line Coverage and Condition Coverage


In Sonar Cube, the equations for "Coverage", "Line Coverage" and "Condition Coverage" are given as:

"Coverage"
coverage = ( (conditions_to_cover - uncovered_conditions) + (lines_to_cover - uncovered_lines) ) / ( conditions_to_cover + lines_to_cover )

"Line Coverage"
line_coverage = (lines_to_cover - uncovered_lines) / (lines_to_cover)

"Condition Coverage"
branch_coverage = (conditions_to_cover - uncovered_conditions) / (conditions_to_cover)

These equations are written using the metric values, so that you can query sonar to get the values for a given project. References include docs.sonarqube.org and www.slideshare.net.

AKA
Several of these terms have synonyms, so keep in mind:
  • 2B = conditions_to_cover
  • CT + CF = conditions_to_cover - uncovered_conditions
  • Condition Coverage = Branch Coverage
  • Condition Coverage = (CT + CF) / (2*B)
  • Coverage = (CT + CF + LC) / (2*B + EL)
  • Line Coverage = LC /EL
The 7 parameters above all have to do with Unit Test Coverage.  The 7 parameters for Integration Test Coverage and Overall Test Coverage are listed here.

"Unit Test Coverage"
  • conditions_to_cover
  • uncovered_conditions
  • lines_to_cover
  • uncovered_lines
  • coverage
  • line_coverage
  • branch_coverage
"Integration Test Coverage"
  • it_conditions_to_cover
  • it_uncovered_conditions
  • it_lines_to_cover
  • it_uncovered_lines
  • it_coverage
  • it_line_coverage
  • it_branch_coverage
"Overall Test Coverage"
  • overall_conditions_to_cover
  • overall_uncovered_conditions
  • overall_lines_to_cover
  • overall_uncovered_lines
  • overall_coverage
  • overall_line_coverage
  • overall_branch_coverage
Use Drilldown HTML Page
You can use the drilldown to find values for these specific metrics.  Just substitute your sonar domain (replace my.sonar.com) and project key (replace My-Project-Name) and the metric you are interested in (replace line_coverage).

http://my.sonar.com/drilldown/measures/My-Project-Name?metric=line_coverage 

Query using Sonar REST API
The format for the query is:

http://{sonarDomain}/api/resources?resource={keyOrID}&metrics={metrics}

http://my.sonar.com/api/resources?resource=55555&metrics=ncloc,conditions_to_cover,uncovered_conditions,lines_to_cover,uncovered_lines,coverage,line_coverage,branch_coverage,it_conditions_to_cover,it_uncovered_conditions,it_lines_to_cover,it_uncovered_lines,it_coverage,it_line_coverage,it_branch_coverage,overall_conditions_to_cover,overall_uncovered_conditions,overall_lines_to_cover,overall_uncovered_lines,overall_coverage,overall_line_coverage,overall_branch_coverage

Combining Projects
One nice thing about using these variables, rather than using the percentages is that you can combine any number of projects and re-calculate coverage.  For instance, if you have 3 projects and you would like to calculate "Unit Test Coverage", you could use an equation like the following to sum the projects values to get a total.

  • conditions_to_cover_total = conditions_to_cover_1 + conditions_to_cover_2 + conditions_to_cover_3
  • uncovered_conditions_total uncovered_conditions_1 uncovered_conditions_2 uncovered_conditions_3
  • lines_to_cover_total lines_to_cover_1 lines_to_cover_2 lines_to_cover_3
  • uncovered_lines_total uncovered_lines_1 uncovered_lines_2 uncovered_lines_3
Then, you can use the formula to calculate an overall coverage:
  • coverage_total = ( (conditions_to_cover_total - uncovered_conditions_total) + (lines_to_cover_total - uncovered_lines_total) ) / ( conditions_to_cover_total + lines_to_cover_total )

Friday, August 7, 2015

Google API Uploading Files

See also http://www.sizustech.blogspot.com/2015/08/getting-started-with-google-drive-api.html on how to generate Auth Tokens. You will need that for this next section as Auth Tokens will be referenced using ${AuthToken}

Upload Dummy File (curl)

Open Git Bash and execute the following command after replacing the Auth Token

curl -k -H "Content-Type: plain/text" -H "Authorization: Bearer ${AuthToken}" -D- -X POST --data "Test adding this content into a new file" https://www.googleapis.com/upload/drive/v2/files?uploadType=media > testUploadResponse.txt

For example, the command might look like this...
curl -k -H "Content-Type: plain/text" -H "Authorization: Bearer ya29.yAFLSqN1xaR9EKuMrcJu6iLMt9PyaRqotTK01PbaPjd7gZZMtqE9XgFgHz3A5IEwKV7-" -D- -X POST --data "Test adding this content into a new file" https://www.googleapis.com/upload/drive/v2/files?uploadType=media > testUploadResponse.txt

Go to http://www.google.com/drive under the account for which the Auth Token was created and search for a file Untitled. If you open this file in a text editor like Notepad, you will see the contents inside the file as "Test adding this content into a new file"

Upload Dummy File (Java)

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.http.entity.StringEntity;
import org.json.JSONObject;

// Step 2 - UPLOAD THE FIRST FILE
// curl -k -H "Content-Type: plain/text" -H "Authorization: Bearer ya29.yAFLSqN1xaR9EKuMrcJu6iLMt9PyaRqotTK01PbaPjd7gZZMtqE9XgFgHz3A5IEwKV7-" -D- -X POST --data "Test adding this content into a new file" https://www.googleapis.com/upload/drive/v2/files?uploadType=media > testUploadResponse.txt
public class UploadTheFirstFile {
    public static void main(String[] args) {
        try {
            String token = "ya29.yAFLSqN1xaR9EKuMrcJu6iLMt9PyaRqotTK01PbaPjd7gZZMtqE9XgFgHz3A5IEwKV7-";
            HttpPost httpPost = new HttpPost("https://www.googleapis.com/upload/drive/v2/files?uploadType=media");
            httpPost.addHeader("Authorization""Bearer "+token);
            httpPost.addHeader("Content-Type""plain/text");
        
            StringEntity entity = new StringEntity("Test adding this content into a new file");
            httpPost.setEntity(entity);
            
            CloseableHttpResponse response = new DefaultHttpClient().execute(httpPost);
            String jsonResponse = EntityUtils.toString(response.getEntity());
            response.close();
            System.out.println("jsonResponse:"+jsonResponse);
            
            JSONObject jsonObject = new JSONObject(jsonResponse);
            String id = jsonObject.getString("id");
            System.out.println("Created resource... ID: "+id);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}


Create a Folder for your Uploads (curl)

You can parse the JSON response to find the id for an existing folder.  However, for this example, we will create a folder for storage call "My Upload Folder".

curl -k -H "Authorization: Bearer {$AuthToken}" -H "Content-Type:application/json" --data '{"title":"My Upload Folder","mimeType":"application/vnd.google-apps.folder"}' https://www.googleapis.com/drive/v2/files > folderResponse.txt

The JSON response will contain the folder id, title and mimeType. You can look in the folderResponse.txt file for these.

{ ... "id""0B9pC9EpixPYFNk9WMWtmT1duQUk" ... "title""My Upload Folder" ... "mimeType""application/vnd.google-apps.folder" ... }

Note: We will use this folder ID in this blog post as {$folderID}.

Create a Folder for your Uploads (Java)

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.http.entity.StringEntity;
import org.json.JSONObject;

// curl -k -H "Authorization: Bearer {$AuthToken}" -H "Content-Type:application/json" --data '{"title":"My Upload Folder","mimeType":"application/vnd.google-apps.folder"}' https://www.googleapis.com/drive/v2/files > folderResponse.txt
public class CreateTheFirstFolder {
    public static void main(String[] args) {
        try {
            String token = "ya29.yAGZ79jCXHvo8jSGOIBgT3Rxbk6Ot1ca1kh6zF_qfpwbnlDF4gdwbN-KCJR0hKxBXo81";
            HttpPost httpPost = new HttpPost("https://www.googleapis.com/drive/v2/files");
            httpPost.addHeader("Authorization""Bearer "+token);
            httpPost.addHeader("Content-Type""application/json");
        
            JSONObject json = new JSONObject();
            json.put("title""My Upload Folder");
            json.put("mimeType""application/vnd.google-apps.folder");
            
            StringEntity entity = new StringEntity(json.toString());
            httpPost.setEntity(entity);
            
            CloseableHttpResponse response = new DefaultHttpClient().execute(httpPost);
            String jsonResponse = EntityUtils.toString(response.getEntity());
            response.close();
            System.out.println("jsonResponse:"+jsonResponse);
            
            JSONObject jsonObject = new JSONObject(jsonResponse);
            String id = jsonObject.getString("id");
            System.out.println("Created resource... ID: "+id);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}


The output was

Created resource... ID: 0B9pC9EpixPYFNk9WMWtmT1duQUk

Note: We will use this folder ID in this blog post as {$folderID}.

Upload a Text File (curl)

Now, we will add a title, provide the folder using the parent key and provide the content in a single curl command.  This will require creating a multi part request.

curl -k -H "Authorization: Bearer ${AuthToken}" -H 'Content-Type: multipart/form-data; boundary="foo_bar_baz"' --data $'--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"title": "My File.txt","parents":[{"kind":"drive#fileLink","id":"${folderID}"}]}\r\n--foo_bar_baz\r\nContent-Type: plain/text\r\n\r\nThis is in the file\r\n--foo_bar_baz--' https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart

curl -k -H "Authorization: Bearer ya29.yAG2xVUntrdwwY9DnwiWeRme6A6unAMDr1uiouTekpV5ee6LS9UnM9iISB-GGNJGZK7b" -H 'Content-Type: multipart/form-data; boundary="foo_bar_baz"' --data $'--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"title": "My File.txt","parents":[{"kind":"drive#fileLink","id":"0B9pC9EpixPYFNk9WMWtmT1duQUk"}]}\r\n--foo_bar_baz\r\nContent-Type: plain/text\r\n\r\nThis is in the file\r\n--foo_bar_baz--' https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart

The boundaries of the multi parts are marked with --foo_bar_baz and the spaces "\r\n" have to be exactly as is otherwise you will get an error "Missing end boundary in multi part body".  You also have to use the $ character to make sure these are processed as expected.

Upload a Text File (curl) - Stitching Together a Multipart Request

This is example is used to give an easy example of stitching together a mutli part form.  This is useful for stitching together files.  Note that the cat command in linux will prepend a "\n", so if you look closely, one of the "\n" characters is removed.

Below, you will have to add replace the ${AuthToken} and the ${folderID}.

touch txtDataFile.txt

echo $'--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"title""My File.txt","parents":[{"kind":"drive#fileLink","id":"${folderID}"}]}\r\n--foo_bar_baz\r\nContent-Type: plain/text\r\n\r' >> txtDataFile.txt

cat TestUpload.txt >> txtDataFile.txt

echo $'\r\n--foo_bar_baz--' >> txtDataFile.txt

curl -k -H "Authorization: Bearer ${AuthToken}" -H 'Content-Type: multipart/form-data; boundary="foo_bar_baz"' --data-binary "@txtDataFile.txt" https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart

For example...

touch txtDataFile.txt

echo $'--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"title""My File.txt","parents":[{"kind":"drive#fileLink","id":"0B9pC9EpixPYFNk9WMWtmT1duQUk"}]}\r\n--foo_bar_baz\r\nContent-Type: plain/text\r\n\r' >> txtDataFile.txt

cat TestUpload.txt >> txtDataFile.txt

echo $'\r\n--foo_bar_baz--' >> txtDataFile.txt

curl -k -H "Authorization: Bearer ya29.xwHjsm--zQ6Wi5qD6mAoMfnDcNdCl0FvaUN8TuAwCvMJ4-YYq2ozj1vKCE1aAGECW4s8" -H 'Content-Type: multipart/form-data; boundary="foo_bar_baz"' --data-binary "@txtDataFile.txt" https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart

Upload a Text File (Java)

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.http.entity.StringEntity;
import org.json.JSONArray;
import org.json.JSONObject;

// curl -k -H "Authorization: Bearer ya29.xwHjsm--zQ6Wi5qD6mAoMfnDcNdCl0FvaUN8TuAwCvMJ4-YYq2ozj1vKCE1aAGECW4s8" -H 'Content-Type: multipart/form-data; boundary="foo_bar_baz"' --data $'--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"title": "My File.txt","parents":[{"kind":"drive#fileLink","id":"0B9pC9EpixPYFNk9WMWtmT1duQUk"}]}\r\n--foo_bar_baz\r\nContent-Type: plain/text\r\n\r\nThis is in the file\r\n--foo_bar_baz--' https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart
//
// touch txtDataFile.txt
// echo $'--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"title": "My File.txt","parents":[{"kind":"drive#fileLink","id":"0B9pC9EpixPYFNk9WMWtmT1duQUk"}]}\r\n--foo_bar_baz\r\nContent-Type: plain/text\r\n\r' >> txtDataFile.txt
// cat TestUpload.txt >> txtDataFile.txt
// echo $'\r\n--foo_bar_baz--' >> txtDataFile.txt
// curl -k -H "Authorization: Bearer ya29.xwHjsm--zQ6Wi5qD6mAoMfnDcNdCl0FvaUN8TuAwCvMJ4-YYq2ozj1vKCE1aAGECW4s8" -H 'Content-Type: multipart/form-data; boundary="foo_bar_baz"' --data-binary "@txtDataFile.txt" https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart
public class CreateADataFileToUploadATextFile {
    public static void main(String[] args) {
        try {
            String accessToken = "ya29.xwHjsm--zQ6Wi5qD6mAoMfnDcNdCl0FvaUN8TuAwCvMJ4-YYq2ozj1vKCE1aAGECW4s8";
            HttpPost httpPost = new HttpPost("https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart");
            httpPost.addHeader("Authorization""Bearer "+accessToken);
            httpPost.setHeader("Content-Type","multipart/related; boundary=foo_bar_baz");

            JSONObject json = new JSONObject();
            json.put("title""My File.txt");
            JSONArray parents = new JSONArray();
            JSONObject parent = new JSONObject();
            parent.put("kind""drive#fileLink");
            parent.put("id""0B9pC9EpixPYFNk9WMWtmT1duQUk");
            parents.put(parent);
            json.put("parents", parents);
            
            String fileContent = "Contents of Test Upload File";
            
            StringEntity str=new StringEntity("--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n"+json.toString()+"\r\n--foo_bar_baz\r\nContent-Type: plain/text\r\n\r\n"+fileContent+"\r\n--foo_bar_baz--");
            httpPost.setEntity(str);
            
            CloseableHttpResponse response = new DefaultHttpClient().execute(httpPost);
            String jsonResponse = EntityUtils.toString(response.getEntity());
            response.close();
            System.out.println("jsonResponse:"+jsonResponse);
            
            JSONObject jsonObject = new JSONObject(jsonResponse);
            String id = jsonObject.getString("id");
            System.out.println("Created resource... ID: "+id);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Upload an Image File (curl)

The main difference between this and the last example is the data is larger and the Content-Type is image/jpeg instead of text/plain.

touch jpgDataFile.txt

echo $'--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"title""My JPG.jpg","parents":[{"kind":"drive#fileLink","id":"0B9pC9EpixPYFNk9WMWtmT1duQUk"}]}\r\n--foo_bar_baz\r\nContent-Type: image/jpeg\r\n\r' >> jpgDataFile.txt

cat TreeHouse15.jpg >> jpgDataFile.txt

echo $'\r\n--foo_bar_baz--' >> jpgDataFile.txt

curl -k -H "Authorization: Bearer ya29.yAG2xVUntrdwwY9DnwiWeRme6A6unAMDr1uiouTekpV5ee6LS9UnM9iISB-GGNJGZK7b" -H 'Content-Type: multipart/form-data; boundary="foo_bar_baz"' --data-binary "@jpgDataFile.txt" https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart

Uploading an Image Data URI (Java)

To make things a little more interesting, we will use a Data URI for this example.

import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.http.entity.StringEntity;
import org.json.JSONArray;
import org.json.JSONObject;

// rm jpgDataFile.txt
// touch jpgDataFile.txt
// echo $'--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{"title": "My JPG.jpg","parents":[{"kind":"drive#fileLink","id":"0B9pC9EpixPYFNk9WMWtmT1duQUk"}]}\r\n--foo_bar_baz\r\nContent-Type: image/jpeg\r\n\r' >> jpgDataFile.txt
// cat TreeHouse15.jpg >> jpgDataFile.txt
// echo $'\r\n--foo_bar_baz--' >> jpgDataFile.txt
// curl -k -H "Authorization: Bearer ya29.xwFXZu-7vgVrcLyfzd1dZOLy3zjoifxGd6-luVgCJw_o8rMNrIGoGqQLfoPhDjtzgs80" -H 'Content-Type: multipart/form-data; boundary="foo_bar_baz"' --data-binary "@jpgDataFile.txt" https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart
public class CreateADataFileToUploadAnImageFile {
    public static void main(String[] args) {
        try {
            String accessToken = "ya29.yAG2xVUntrdwwY9DnwiWeRme6A6unAMDr1uiouTekpV5ee6LS9UnM9iISB-GGNJGZK7b";
            HttpPost httpPost = new HttpPost("https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart");
            httpPost.addHeader("Authorization""Bearer "+accessToken);
            httpPost.setHeader("Content-Type","multipart/related; boundary=foo_bar_baz");

            JSONObject json = new JSONObject();
            json.put("title""My JPG.jpg");
            JSONArray parents = new JSONArray();
            JSONObject parent = new JSONObject();
            parent.put("kind""drive#fileLink");
            parent.put("id""0B9pC9EpixPYFNk9WMWtmT1duQUk");
            parents.put(parent);
            json.put("parents", parents);
            
            String dataURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC";
            String encodingPrefix = "base64,";
            int contentStartIndex = dataURI.indexOf(encodingPrefix) + encodingPrefix.length();
            byte[] imageData = Base64.decodeBase64(dataURI.substring(contentStartIndex));
            String fileContent = new String(imageData);
            
            StringEntity str=new StringEntity("--foo_bar_baz\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n"+json.toString()+"\r\n--foo_bar_baz\r\nContent-Type: image/jpeg\r\n\r\n"+fileContent+"\r\n--foo_bar_baz--");
            httpPost.setEntity(str);
            
            CloseableHttpResponse response = new DefaultHttpClient().execute(httpPost);
            String jsonResponse = EntityUtils.toString(response.getEntity());
            response.close();
            System.out.println("jsonResponse:"+jsonResponse);
            
            JSONObject jsonObject = new JSONObject(jsonResponse);
            String id = jsonObject.getString("id");
            System.out.println("Created resource... ID: "+id);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}