at.ac.tuwien.infosys.util.ImageUtil.java Source code

Java tutorial

Introduction

Here is the source code for at.ac.tuwien.infosys.util.ImageUtil.java

Source

/*
 * Copyright (c) 2014 Technische Universitaet Wien (TUW), Distributed SystemsGroup E184.
 * 
 * This work was partially supported by the Pacific Controls under the Pacific Controls 
 * Cloud Computing Lab (pc3l.infosys.tuwien.ac.at)
 *
 * 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.
 * 
 * Written by Michael Voegler
 */
package at.ac.tuwien.infosys.util;

import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Value;

import at.ac.tuwien.infosys.model.Component;
import at.ac.tuwien.infosys.model.Plan;
import at.ac.tuwien.infosys.model.Resource;

/**
 * @author michael
 *
 */
@org.springframework.stereotype.Component(value = "singleton")
public class ImageUtil {

    private static final String IMAGE_RUN_FILE_NAME = "run.sh";
    private static final String ID_FILE = "id";
    private static final String RUNLIST_FILE = "runlist";

    public static Logger logger = Logger.getLogger(ImageUtil.class.getName());

    private ZipUtil zipUtil;

    private Path imageTempDir;
    private String imageId;

    @Value("${working.repository}")
    private String workingRepo;

    public ImageUtil() {
    }

    @PostConstruct
    public void init() throws IOException {
        Path repo = Paths.get(workingRepo);
        Files.createDirectories(repo);
        this.imageTempDir = Files.createTempDirectory(Paths.get(repo.toString()), "image-");
        logger.info("Using temporary-folder: " + imageTempDir);
    }

    public synchronized Path createImage(Plan deviceComponentBundle, String idPrefix) throws IOException {

        if (idPrefix != null && !idPrefix.isEmpty())
            idPrefix += "_";
        else
            idPrefix = "unknown_";

        this.imageId = idPrefix + UUID.randomUUID().toString();

        logger.info("Building image with id: " + imageId);

        this.zipUtil = new ZipUtil(imageId + ".zip", imageTempDir, workingRepo);

        List<String> componentNames = new ArrayList<String>();

        // create image structure and copy files (artifacts and scripts)
        for (Component component : deviceComponentBundle.getComponents()) {
            Path compParentPath = Files.createDirectories(imageTempDir.resolve(component.getName()));
            componentNames.add(component.getName());

            Path artifactParentPath = Files.createDirectories(compParentPath.resolve("artifacts"));

            Path scriptParentPath = Files.createDirectories(compParentPath.resolve("scripts"));

            for (Resource artifact : component.getBinaries()) {
                Path artifactFile = Files.createFile(artifactParentPath.resolve(artifact.getName()));
                saveFile(artifact.getUri(), artifactFile);
            }

            for (Resource script : component.getScripts()) {
                Path scriptFile = Files.createFile(scriptParentPath.resolve(script.getName()));
                saveFile(script.getUri(), scriptFile);
            }
        }

        // create runlist file and write component-names
        StringBuilder builder = new StringBuilder();
        // boolean firstItem = true;
        for (String componentName : componentNames) {
            // if (!firstItem)
            // builder.append("\n");
            // else
            // firstItem = false;
            // builder.append(componentName);
            builder.append(componentName + "\n");
        }
        Path runlistFile = Files.createFile(imageTempDir.resolve(RUNLIST_FILE));
        Files.write(runlistFile, builder.toString().getBytes());

        // create file and write image-id
        Path idFile = Files.createFile(imageTempDir.resolve(ID_FILE));
        Files.write(idFile, imageId.getBytes());

        // add generic image-run script
        Path globalRunFile = Files.createFile(imageTempDir.resolve(IMAGE_RUN_FILE_NAME));
        saveFile(Config.IMAGE_RUN_SCRIPT, globalRunFile);

        logger.info("Finished building and initiate archiving!");

        // create final image by compressing the contents into a zip
        Path zipFile = zipUtil.createZip();

        logger.info("Finished archiving image: " + zipFile.toString());

        return zipFile;
    }

    public void clean() {
        if (imageTempDir != null && imageTempDir.toFile().exists()) {
            try {
                Files.walkFileTree(imageTempDir, new RemoveFileVisitor());
            } catch (IOException e) {
                // e.printStackTrace();
            }
        }
        if (zipUtil != null)
            zipUtil.clean();
    }

    private void saveFile(URL url, Path file) throws IOException {
        ReadableByteChannel rbc = Channels.newChannel(url.openStream());
        FileChannel channel = FileChannel.open(file, EnumSet.of(StandardOpenOption.CREATE,
                StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE));
        channel.transferFrom(rbc, 0, Long.MAX_VALUE);
        channel.close();
    }

    public String getImageId() {
        return imageId;
    }

    public void setImageId(String imageId) {
        this.imageId = imageId;
    }

    public static class RemoveFileVisitor extends SimpleFileVisitor<Path> {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
    }

    public static void main(String[] args) {
        try {
            ImageUtil util = new ImageUtil();
            util.workingRepo = "/tmp/builder/";
            util.init();
            Path zip = util.createImage(Config.DEVICE_PLAN, "");
            System.out.println("Got: " + zip);
            util.clean();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}