io.macgyver.plugin.cloud.cloudstack.RequestBuilder.java Source code

Java tutorial

Introduction

Here is the source code for io.macgyver.plugin.cloud.cloudstack.RequestBuilder.java

Source

/**
 * 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 io.macgyver.plugin.cloud.cloudstack;

import io.macgyver.core.MacGyverConfigurationException;
import io.macgyver.core.MacGyverException;
import io.macgyver.okrest.OkRestTarget;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

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

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import okio.Buffer;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.BaseEncoding;
import com.squareup.okhttp.FormEncodingBuilder;

public class RequestBuilder {

    Map<String, String> paramMap = Maps.newHashMap();

    CloudStackClientImpl client;

    public RequestBuilder command(String n) {
        return param("command", n);
    }

    public RequestBuilder param(String key, String val) {
        paramMap.put(key, val);
        return this;
    }

    protected String generateCommandStringForHmac() {

        try {
            Map<String, String> copy = Maps.newHashMap();
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                copy.put(entry.getKey().toLowerCase(), entry.getValue().toLowerCase());
            }
            List<String> sortedKeys = Lists.newArrayList(copy.keySet());
            Collections.sort(sortedKeys);

            List<String> kvPairs = Lists.newArrayList();
            for (String x : sortedKeys) {
                String kv = URLEncoder.encode(x, "UTF-8") + "=" + URLEncoder.encode(copy.get(x), "UTF-8");
                kvPairs.add(kv);
            }

            return Joiner.on("&").join(kvPairs);

        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    protected String computeSignature() {

        Preconditions.checkNotNull(client, "client cannot be null");
        Preconditions.checkState(!Strings.isNullOrEmpty(client.secretKey), "secretKey not set");
        String cs = generateCommandStringForHmac();

        String m = hmacSha1(cs, client.secretKey);

        return m;

    }

    protected String hmacSha1(String value, String signingKeyString) {
        try {
            // Get an hmac_sha1 key from the raw key bytes
            byte[] keyBytes = signingKeyString.getBytes();
            SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");

            // Get an hmac_sha1 Mac instance and initialize with the signing key
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);

            // Compute the hmac on input data bytes
            byte[] rawHmac = mac.doFinal(value.getBytes());

            // Convert raw bytes to Hex
            return BaseEncoding.base64Url().encode(rawHmac);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public RequestBuilder listVirtualMachines() {
        return command("listVirtualMachines");
    }

    public JsonNode execute() {

        try {
            OkRestTarget t = client.target;
            param("response", "json");

            String expires = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ")
                    .print(System.currentTimeMillis() + 1000 * 60 * 5);
            param("expires", expires);
            FormEncodingBuilder b = new FormEncodingBuilder();
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                b = b.add(entry.getKey(), entry.getValue());

            }

            if (client.usernamePasswordAuth) {
                String sessionKey = client.getSessionData().path("loginresponse").path("sessionkey").asText();

                b = b.add("sessionkey", sessionKey).add("expires", expires).add("signatureversion", "3");

                t = t.header("Cookie", "JSESSIONID=" + client.getSessionData().path("JSESSIONID").asText());

            } else {
                b = b.add("apiKey", client.apiKey).add("signature", computeSignature());

            }

            return t.post(b.build()).execute(JsonNode.class);
        } catch (ExecutionException e) {
            throw new MacGyverException(e);
        }
    }
}