org.dasein.cloud.google.Google.java Source code

Java tutorial

Introduction

Here is the source code for org.dasein.cloud.google.Google.java

Source

/**
 * Copyright (C) 2012-2013 Dell, Inc
 * See annotations for authorship information
 *
 * ====================================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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.dasein.cloud.google;

import java.io.*;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.ComputeScopes;
import com.google.api.services.storage.Storage;
import org.apache.log4j.Logger;
import org.dasein.cloud.*;
import org.dasein.cloud.dc.Region;
import org.dasein.cloud.google.compute.GoogleCompute;
import org.dasein.cloud.google.network.GoogleNetwork;
import org.dasein.cloud.google.storage.GoogleDrive;
import org.dasein.cloud.util.Cache;
import org.dasein.cloud.util.CacheLevel;
import org.dasein.util.uom.time.Hour;
import org.dasein.util.uom.time.TimePeriod;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * Support for the Google API through Dasein Cloud.
 * <p>Created by George Reese: 12/06/2012 9:35 AM</p>
 * @author George Reese
 * @version 2013.01 initial version
 * @since 2013.01
 */
public class Google extends AbstractCloud {
    static private final Logger logger = getLogger(Google.class);

    private static final String DSN_P12_CERT = "p12Certificate";
    private static final String DSN_SERVICE_ACCOUNT = "serviceAccount";

    public final static String ISO8601_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
    public final static String ISO8601_NO_MS_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    static private @Nonnull String getLastItem(@Nonnull String name) {
        int idx = name.lastIndexOf('.');

        if (idx < 0) {
            return name;
        } else if (idx == (name.length() - 1)) {
            return "";
        }
        return name.substring(idx + 1);
    }

    static public @Nonnull Logger getLogger(@Nonnull Class<?> cls) {
        String pkg = getLastItem(cls.getPackage().getName());

        if (pkg.equals("google")) {
            pkg = "";
        } else {
            pkg = pkg + ".";
        }
        return Logger.getLogger("dasein.cloud.google.std." + pkg + getLastItem(cls.getName()));
    }

    static public @Nonnull Logger getWireLogger(@Nonnull Class<?> cls) {
        return Logger.getLogger("dasein.cloud.google.wire." + getLastItem(cls.getPackage().getName()) + "."
                + getLastItem(cls.getName()));
    }

    public Google() {
    }

    @Override
    public @Nonnull String getCloudName() {
        ProviderContext ctx = getContext();
        String name = (ctx == null ? null : ctx.getCloudName());

        return (name == null ? "GCE" : name);
    }

    @Override
    public @Nonnull ContextRequirements getContextRequirements() {
        return new ContextRequirements(
                new ContextRequirements.Field(DSN_P12_CERT, "The p12 file for the account",
                        ContextRequirements.FieldType.KEYPAIR, ContextRequirements.Field.X509, true),
                new ContextRequirements.Field(DSN_SERVICE_ACCOUNT,
                        "The service account email registered to the account", ContextRequirements.FieldType.TEXT,
                        ContextRequirements.Field.ACCESS_KEYS, true));
    }

    @Override
    public @Nonnull DataCenters getDataCenterServices() {
        return new DataCenters(this);
    }

    @Override
    public @Nonnull GoogleCompute getComputeServices() {
        return new GoogleCompute(this);
    }

    @Override
    public @Nonnull GoogleNetwork getNetworkServices() {
        return new GoogleNetwork(this);
    }

    @Override
    public @Nonnull GoogleDrive getStorageServices() {
        return new GoogleDrive(this);
    }

    @Override
    public @Nonnull String getProviderName() {
        ProviderContext ctx = getContext();
        String name = (ctx == null ? null : ctx.getProviderName());

        return (name == null ? "Google" : name);
    }

    public Compute getGoogleCompute() throws CloudException, InternalException {
        ProviderContext ctx = getContext();

        Cache<Compute> cache = Cache.getInstance(this, "ComputeAccess", Compute.class, CacheLevel.CLOUD_ACCOUNT,
                new TimePeriod<Hour>(1, TimePeriod.HOUR));
        Collection<Compute> googleCompute = (Collection<Compute>) cache.get(ctx);
        Compute gce = null;

        if (googleCompute == null) {
            googleCompute = new ArrayList<Compute>();
            HttpTransport transport = new NetHttpTransport();
            JsonFactory jsonFactory = new JacksonFactory();

            try {
                String serviceAccountId = "";
                byte[] p12Bytes = null;
                String p12Password = "";

                List<ContextRequirements.Field> fields = getContextRequirements().getConfigurableValues();
                for (ContextRequirements.Field f : fields) {
                    if (f.type.equals(ContextRequirements.FieldType.KEYPAIR)) {
                        byte[][] keyPair = (byte[][]) getContext().getConfigurationValue(f);
                        p12Bytes = keyPair[0];
                        p12Password = new String(keyPair[1], "utf-8");
                    } else if (f.type.equals(ContextRequirements.FieldType.TEXT)) {
                        serviceAccountId = (String) getContext().getConfigurationValue(f);
                    }
                }

                KeyStore keyStore = KeyStore.getInstance("PKCS12");
                InputStream p12AsStream = new ByteArrayInputStream(p12Bytes);
                keyStore.load(p12AsStream, p12Password.toCharArray());

                GoogleCredential creds = new GoogleCredential.Builder().setTransport(transport)
                        .setJsonFactory(jsonFactory).setServiceAccountId(serviceAccountId)
                        .setServiceAccountScopes(ComputeScopes.all())
                        .setServiceAccountPrivateKey(
                                (PrivateKey) keyStore.getKey("privateKey", p12Password.toCharArray()))//This is always the password for p12 files
                        .build();
                creds.setExpirationTimeMilliseconds(3600000L);

                gce = new Compute.Builder(transport, jsonFactory, creds).setApplicationName(ctx.getAccountNumber())
                        .setHttpRequestInitializer(creds).build();
                googleCompute.add(gce);
                cache.put(ctx, googleCompute);
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new CloudException(CloudErrorType.AUTHENTICATION, 400, "Bad Credentials",
                        "An authentication error has occurred: Bad Credentials");
            }
        } else {
            gce = googleCompute.iterator().next();
        }
        return gce;
    }

    public Storage getGoogleStorage() throws CloudException, InternalException {
        ProviderContext ctx = getContext();

        Cache<Storage> cache = Cache.getInstance(this, "DriveAccess", Storage.class, CacheLevel.CLOUD,
                new TimePeriod<Hour>(1, TimePeriod.HOUR));
        Collection<Storage> googleDrive = (Collection<Storage>) cache.get(ctx);
        Storage drive = null;

        if (googleDrive == null) {
            googleDrive = new ArrayList<Storage>();

            HttpTransport transport = new NetHttpTransport();
            JsonFactory jsonFactory = new JacksonFactory();

            try {
                String serviceAccountId = "";
                byte[] p12Bytes = null;
                String p12Password = "";

                List<ContextRequirements.Field> fields = getContextRequirements().getConfigurableValues();
                for (ContextRequirements.Field f : fields) {
                    if (f.type.equals(ContextRequirements.FieldType.KEYPAIR)) {
                        byte[][] keyPair = (byte[][]) getContext().getConfigurationValue(f);
                        p12Bytes = keyPair[0];
                        p12Password = new String(keyPair[1], "utf-8");
                    } else if (f.type.equals(ContextRequirements.FieldType.TEXT)) {
                        serviceAccountId = (String) getContext().getConfigurationValue(f);
                    }
                }

                KeyStore keyStore = KeyStore.getInstance("PKCS12");
                InputStream p12AsStream = new ByteArrayInputStream(p12Bytes);
                keyStore.load(p12AsStream, p12Password.toCharArray());

                GoogleCredential creds = new GoogleCredential.Builder().setTransport(transport)
                        .setJsonFactory(jsonFactory).setServiceAccountId(serviceAccountId)
                        .setServiceAccountScopes(ComputeScopes.all())
                        .setServiceAccountPrivateKey(
                                (PrivateKey) keyStore.getKey("privateKey", p12Password.toCharArray()))//This is always the password for p12 files
                        .build();
                creds.setExpirationTimeMilliseconds(3600000L);

                drive = new Storage.Builder(transport, jsonFactory, creds)
                        .setApplicationName(ctx.getAccountNumber()).setHttpRequestInitializer(creds).build();
                googleDrive.add(drive);
                cache.put(ctx, googleDrive);
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new CloudException(CloudErrorType.AUTHENTICATION, 400, "Bad Credentials",
                        "An authentication error has occurred: Bad Credentials");
            }
        } else {
            drive = googleDrive.iterator().next();
        }
        return drive;
    }

    @Override
    public @Nullable String testContext() {
        if (logger.isTraceEnabled()) {
            logger.trace("ENTER - " + Google.class.getName() + ".testContext()");
        }
        try {
            ProviderContext ctx = getContext();

            if (ctx == null) {
                return null;
            }
            if (ctx.getRegionId() == null) {
                Collection<Region> regions = getDataCenterServices().listRegions();
                if (regions.size() > 0) {
                    ctx.setRegionId(regions.iterator().next().getProviderRegionId());
                }
            }

            if (!getComputeServices().getVirtualMachineSupport().isSubscribed()) {
                return null;
            }
            return ctx.getAccountNumber();
        } catch (Throwable t) {
            logger.error("Error querying API key: " + t.getMessage());
            t.printStackTrace();
            return null;
        } finally {
            if (logger.isTraceEnabled()) {
                logger.trace("EXIT - " + Google.class.getName() + ".textContext()");
            }
        }
    }

    public long parseTime(@Nullable String time) throws CloudException {
        if (time == null) {
            return 0L;
        }
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

        if (time.length() > 0) {
            try {
                return fmt.parse(time).getTime();
            } catch (ParseException e) {
                fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
                try {
                    return fmt.parse(time).getTime();
                } catch (ParseException encore) {
                    throw new CloudException("Could not parse date: " + time);
                }
            }
        }
        return 0L;
    }
}