com.vmware.admiral.closures.util.ClosureUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.admiral.closures.util.ClosureUtils.java

Source

/*
 * Copyright (c) 2016 VMware, Inc. All Rights Reserved.
 *
 * This product is licensed to you under the Apache License, Version 2.0 (the "License").
 * You may not use this product except in compliance with the License.
 *
 * This product may include a number of subcomponents with separate copyright notices
 * and license terms. Your use of these subcomponents is subject to the terms and
 * conditions of the subcomponent's license, as noted in the LICENSE file.
 */

package com.vmware.admiral.closures.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.io.output.ByteArrayOutputStream;

import com.vmware.xenon.common.Utils;

/**
 * Closure utility class
 */
public final class ClosureUtils {

    private static final long BYTES_IN_MB = 1024 * 1024L;

    public static Long toBytes(int megabytes) {
        return megabytes * BYTES_IN_MB;
    }

    public static boolean isEmpty(String str) {
        return str == null || str.trim().length() <= 0;
    }

    public static String calculateHash(String[] envs) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            for (String e : envs) {
                md.update(e.getBytes("UTF-8"));
            }

            StringBuilder sb = new StringBuilder();
            byte[] digest = md.digest();
            for (byte b : digest) {
                sb.append(String.format("%02x", b & 0xff));
            }
            return sb.toString();
        } catch (Exception ex) {
            String errMsg = "Unable to calculate execution env. checksum! Reason: " + ex.getMessage();
            logError(errMsg);
            throw new RuntimeException(errMsg);
        }
    }

    public static byte[] loadDockerImageData(String dockerImageName, String folderFilter, Class<?> resourceClass) {
        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
        try {
            URL dirURL = resourceClass.getResource("/" + folderFilter);
            logInfo("Reading image data %s from: %s ", dockerImageName, dirURL);

            String extractImageName = extractImageName(dockerImageName);
            String folderNameFilter = folderFilter + extractImageName;
            buildTarData(dirURL, folderNameFilter, byteOutputStream);

            return byteOutputStream.toByteArray();
        } catch (Exception ex) {
            Utils.logWarning("Unable to load docker image data! Reason: ", ex);
        } finally {
            try {
                byteOutputStream.close();
            } catch (IOException e) {
                // not interested
            }
        }
        return new byte[] {};
    }

    private static String extractImageName(String dockerImageName) {
        String tagRemoved;
        if (dockerImageName.indexOf(":") <= 0) {
            tagRemoved = dockerImageName;
        } else {
            tagRemoved = dockerImageName.split(":")[0];
        }
        int repoIndex = tagRemoved.indexOf("/");
        if (repoIndex <= 0) {
            return tagRemoved;
        }

        return tagRemoved.substring(repoIndex + 1);
    }

    public static JsonElement toJsonElement(JsonNode node) {
        JsonObject jsObject = new JsonObject();

        Iterator<String> fieldsIterator = node.fieldNames();
        if (!fieldsIterator.hasNext()) {
            if (node.isObject()) {
                return jsObject;
            }
            return getPrimitiveJsonElement(node);
        }

        while (fieldsIterator.hasNext()) {
            String field = fieldsIterator.next();
            JsonNode childNode = node.get(field);
            JsonElement convertedValue = getJsonObjElement(childNode);
            jsObject.add(field, convertedValue);
        }

        return jsObject;
    }

    private static JsonElement toJsonElementArray(JsonNode node) {
        JsonArray jsObjArray = new JsonArray();
        Iterator<JsonNode> iterator = node.iterator();
        while (iterator.hasNext()) {
            JsonNode childNode = iterator.next();
            JsonElement convertedValue = getJsonObjElement(childNode);
            jsObjArray.add(convertedValue);
        }

        return jsObjArray;
    }

    private static JsonElement getJsonObjElement(JsonNode node) {
        if (node.isObject()) {
            return toJsonElement(node);
        } else if (node.isArray()) {
            return toJsonElementArray(node);
        }

        return getPrimitiveJsonElement(node);
    }

    private static JsonElement getPrimitiveJsonElement(JsonNode node) {
        if (node.isNull()) {
            return JsonNull.INSTANCE;
        } else if (node.isNumber()) {
            return new JsonPrimitive(node.numberValue());
        }

        com.google.gson.JsonParser parser = new com.google.gson.JsonParser();
        return parser.parse(node.asText());
    }

    private static void buildTarData(URL dirURL, String folderNameFilter, OutputStream outputStream)
            throws IOException {
        final JarURLConnection jarConnection = (JarURLConnection) dirURL.openConnection();
        final ZipFile jar = jarConnection.getJarFile();
        final Enumeration<? extends ZipEntry> entries = jar.entries();

        try (TarArchiveOutputStream tarArchiveOutputStream = buildTarStream(outputStream)) {
            while (entries.hasMoreElements()) {
                final ZipEntry entry = entries.nextElement();
                final String name = entry.getName();
                if (!name.startsWith(folderNameFilter)) {
                    // entry in wrong subdir -- don't copy
                    continue;
                }
                TarArchiveEntry tarEntry = new TarArchiveEntry(entry.getName().replaceAll(folderNameFilter, ""));
                try (InputStream is = jar.getInputStream(entry)) {
                    putTarEntry(tarArchiveOutputStream, tarEntry, is, entry.getSize());
                }
            }

            tarArchiveOutputStream.flush();
            tarArchiveOutputStream.close();
        }
    }

    private static void putTarEntry(TarArchiveOutputStream tarOutputStream, TarArchiveEntry tarEntry,
            InputStream inStream, long size) throws IOException {
        tarEntry.setSize(size);
        tarOutputStream.putArchiveEntry(tarEntry);
        try (InputStream input = new BufferedInputStream(inStream)) {
            long byteRead = copy(input, tarOutputStream);
            logInfo("---- BYTES READ %s ", byteRead);
            tarOutputStream.closeArchiveEntry();
        }
    }

    private static long copy(InputStream from, OutputStream to) throws IOException {
        byte[] buf = new byte[4096];
        long total = 0;
        int r;
        while ((r = from.read(buf)) > 0) {
            to.write(buf, 0, r);
            total += r;
        }
        return total;
    }

    private static TarArchiveOutputStream buildTarStream(OutputStream outputStream) throws IOException {
        OutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
        bufferedOutputStream = new GzipCompressorOutputStream(bufferedOutputStream);

        TarArchiveOutputStream tarArchiveOutputStream = new TarArchiveOutputStream(bufferedOutputStream);
        tarArchiveOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
        return tarArchiveOutputStream;
    }

    private static void logInfo(String message, Object... values) {
        Utils.log(ClosureUtils.class, ClosureUtils.class.getSimpleName(), Level.INFO, message, values);
    }

    private static void logError(String message, Object... values) {
        Utils.log(ClosureUtils.class, ClosureUtils.class.getSimpleName(), Level.SEVERE, message, values);
    }
}