org.akvo.flow.deploy.Deploy.java Source code

Java tutorial

Introduction

Here is the source code for org.akvo.flow.deploy.Deploy.java

Source

/*
 * Copyright 2010-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 org.akvo.flow.deploy;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.tools.remoteapi.RemoteApiInstaller;
import com.google.appengine.tools.remoteapi.RemoteApiOptions;

/**
 * Uploads a single Akvo FLOW APK to s3. There are seven arguments: - accessKey
 * - S3 access key - secretKey - S3 secret key - instanceId - name of the
 * instance, - apkPath - the local path to the APK file to be - version - APK
 * version name - username - Google Account username - password - Google Account
 * password
 */
public class Deploy {
    private static final int S3_ACCESS_KEY = 0;
    private static final int S3_SECRET_KEY = 1;
    private static final int INSTANCE_ID = 2;
    private static final int APK_PATH = 3;
    private static final int VERSION = 4;
    private static final int ACCOUNT_ID = 5;
    private static final int ACCOUNT_SECRET = 6;

    private static final String BUCKET_NAME = "akvoflow";

    public static void main(String[] args) throws IOException {
        if (args.length != 7) {
            System.err.println("Missing argument, please provide S3 access key, S3 secret key, "
                    + "instanceId , apkPath, version, GAE username and GAE password");
            return;
        }

        File file = new File(args[APK_PATH]);
        if (!file.exists()) {
            System.err.println("Can't find apk at " + args[APK_PATH]);
            return;
        }

        final String accessKey = args[S3_ACCESS_KEY];
        final String secretKey = args[S3_SECRET_KEY];
        final String instance = args[INSTANCE_ID];
        final String accountId = args[ACCOUNT_ID];
        final String accountSecret = args[ACCOUNT_SECRET];
        final String version = args[VERSION];

        final String s3Path = "apk/" + instance + "/" + file.getName();
        final String s3Url = "http://akvoflow.s3.amazonaws.com/apk/" + instance + '/' + file.getName();
        final String host = instance + ".appspot.com";

        try {
            uploadS3(accessKey, secretKey, s3Path, file);
            updateVersion(host, accountId, accountSecret, s3Url, version, getMD5Checksum(file));
        } catch (AmazonServiceException ase) {
            System.err.println("Caught an AmazonServiceException, which means your request made it "
                    + "to Amazon S3, but was rejected with an error response for some reason.");
            System.err.println("Error Message:    " + ase.getMessage());
            System.err.println("HTTP Status Code: " + ase.getStatusCode());
            System.err.println("AWS Error Code:   " + ase.getErrorCode());
            System.err.println("Error Type:       " + ase.getErrorType());
            System.err.println("Request ID:       " + ase.getRequestId());
        } catch (AmazonClientException ace) {
            System.err.println("Caught an AmazonClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with S3, "
                    + "such as not being able to access the network.");
            System.err.println("Error Message: " + ace.getMessage());
        } catch (IOException e) {
            System.err.println("Error updating APK version in GAE");
            e.printStackTrace();
        }

    }

    private static void uploadS3(String accessKey, String secretKey, String s3Path, File file)
            throws AmazonServiceException, AmazonClientException {
        BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
        AmazonS3 s3 = new AmazonS3Client(credentials);

        PutObjectRequest putRequest = new PutObjectRequest(BUCKET_NAME, s3Path, file);
        ObjectMetadata metadata = new ObjectMetadata();

        // set content type as android package file
        metadata.setContentType("application/vnd.android.package-archive");

        // set content length to length of file
        metadata.setContentLength(file.length());

        // set access to public
        putRequest.setMetadata(metadata);
        putRequest.setCannedAcl(CannedAccessControlList.PublicRead);

        // try to put the apk in S3
        PutObjectResult result = s3.putObject(putRequest);
        System.out.println("Apk uploaded successfully, with result ETag " + result.getETag());
    }

    private static void updateVersion(String host, String accountId, String accountSecret, String url,
            String version, String md5) throws IOException {
        RemoteApiOptions options = new RemoteApiOptions().server(host, 443).useServiceAccountCredential(accountId,
                accountSecret);
        RemoteApiInstaller installer = new RemoteApiInstaller();
        installer.install(options);
        try {
            DatastoreService ds = DatastoreServiceFactory.getDatastoreService();

            Entity e = new Entity("DeviceApplication");
            e.setProperty("appCode", "flowapp");
            e.setProperty("deviceType", "androidPhone");
            e.setProperty("version", version);
            e.setProperty("fileName", url);
            e.setProperty("md5Checksum", md5);

            final Date date = new Date();// use the same timestampt
            e.setProperty("createdDateTime", date);
            e.setProperty("lastUpdateDateTime", date);
            ds.put(e);
        } finally {
            installer.uninstall();
        }
        System.out.println("New APK version successfully stored in GAE");
    }

    private static String getMD5Checksum(File file) {
        InputStream in = null;
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
            in = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[8192];
            int read;
            while ((read = in.read(buffer)) != -1) {
                md.update(buffer, 0, read);
            }
            byte[] rawHash = md.digest();

            StringBuilder builder = new StringBuilder();
            for (byte b : rawHash) {
                builder.append(String.format("%02x", b));
            }
            return builder.toString();
        } catch (NoSuchAlgorithmException e) {
            System.out.println(e.getMessage());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                in.close();
            } catch (Exception ignored) {
            }
        }
        return null;
    }

}