com.github.sakserv.minicluster.impl.KnoxLocalCluster.java Source code

Java tutorial

Introduction

Here is the source code for com.github.sakserv.minicluster.impl.KnoxLocalCluster.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 com.github.sakserv.minicluster.impl;

import com.github.sakserv.minicluster.MiniCluster;
import com.github.sakserv.minicluster.util.FileUtils;
import com.google.common.base.Throwables;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.gateway.GatewayServer;
import org.apache.hadoop.gateway.services.DefaultGatewayServices;
import org.apache.hadoop.gateway.services.ServiceLifecycleException;
import org.apache.hadoop.gateway.services.topology.impl.DefaultTopologyService;
import org.apache.hadoop.gateway.topology.Service;
import org.apache.hadoop.gateway.topology.Topology;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author Vincent Devillers
 */
public class KnoxLocalCluster implements MiniCluster {

    // Logger
    private static final Logger LOG = LoggerFactory.getLogger(KnoxLocalCluster.class);

    private GatewayServer gatewayServer;
    private File gatewayDir;

    private String host;
    private Integer port;
    private String homeDir;
    private String path;
    private String topology;
    private String cluster;

    public Integer getPort() {
        return port;
    }

    public String getHomeDir() {
        return homeDir;
    }

    public String getTopology() {
        return topology;
    }

    public String getPath() {
        return path;
    }

    public String getHost() {
        return host;
    }

    public String getCluster() {
        return cluster;
    }

    private KnoxLocalCluster(Builder builder) {
        this.port = builder.port;
        this.homeDir = builder.homeDir;
        this.path = builder.path;
        this.topology = builder.topology;
        this.host = builder.host;
        this.cluster = builder.cluster;
    }

    public static class Builder {
        private String host = "localhost";
        private Integer port;
        private String homeDir;
        private String path;
        private String topology;
        private String cluster;

        public Builder setHost(String Host) {
            this.host = Host;
            return this;
        }

        public Builder setPort(Integer Port) {
            this.port = Port;
            return this;
        }

        public Builder setHomeDir(String homeDir) {
            this.homeDir = homeDir;
            return this;
        }

        public Builder setCluster(String cluster) {
            this.cluster = cluster;
            return this;
        }

        public Builder setPath(String Path) {
            this.path = Path;
            return this;
        }

        public Builder setTopology(String topology) {
            this.topology = topology;
            return this;
        }

        public KnoxLocalCluster build() {
            KnoxLocalCluster knoxLocalCluster = new KnoxLocalCluster(this);
            validateObject(knoxLocalCluster);
            return knoxLocalCluster;
        }

        public void validateObject(KnoxLocalCluster knoxLocalCluster) {
            if (knoxLocalCluster.port == null) {
                throw new IllegalArgumentException("ERROR: Missing required config: port");
            }

            if (knoxLocalCluster.homeDir == null) {
                throw new IllegalArgumentException("ERROR: Missing required config: homeDir");
            }

            if (knoxLocalCluster.path == null) {
                throw new IllegalArgumentException("ERROR: Missing required config: path");
            }

            if (knoxLocalCluster.topology == null) {
                throw new IllegalArgumentException("ERROR: Missing required config: topology");
            }

            if (knoxLocalCluster.cluster == null) {
                throw new IllegalArgumentException("ERROR: Missing required config: cluster");
            }
        }
    }

    @Override
    public void start() throws Exception {

        LOG.info("KNOX: Starting GatewayServer");
        configure();

        gatewayDir = new File(homeDir, "gateway-home-" + UUID.randomUUID());
        gatewayDir.mkdirs();

        LocalGatewayConfig config = new LocalGatewayConfig();
        config.set("GATEWAY_HOME", gatewayDir.getAbsolutePath());
        config.set(LocalGatewayConfig.HTTP_HOST, host);
        config.setInt(LocalGatewayConfig.HTTP_PORT, port);
        config.set(LocalGatewayConfig.HTTP_PATH, path);
        config.set("default.app.topology.name", cluster);
        config.set("ssl.exclude.protocols", "none");

        // {GATEWAY_HOME}/data
        File dataDir = new File(config.getGatewayDataDir());
        dataDir.mkdirs();

        // {GATEWAY_HOME}/data/deployments
        File deploymentDir = new File(config.getGatewayDeploymentDir());
        deploymentDir.mkdirs();

        // {GATEWAY_HOME}/data/security
        File securityDir = new File(config.getGatewaySecurityDir());
        securityDir.mkdirs();

        // {GATEWAY_HOME}/data/services
        File stacksDir = new File(config.getGatewayServicesDir());
        stacksDir.mkdirs();

        // {GATEWAY_HOME}/conf
        //config.set(LocalGatewayConfig.HADOOP_CONF_DIR, new File(gatewayDir, "conf").getAbsolutePath());
        File confDir = new File(config.getGatewayConfDir());
        confDir.mkdirs();

        // {GATEWAY_HOME}/conf/topologies
        File topologiesDirectory = new File(config.getGatewayTopologyDir());
        topologiesDirectory.mkdirs();

        LOG.info("Using topology: {}", topology);
        File descriptor = new File(topologiesDirectory, cluster + ".xml");
        try (FileOutputStream stream = new FileOutputStream(descriptor)) {
            stream.write(topology.getBytes());
        }

        DefaultGatewayServices services = new DefaultGatewayServices();

        Map<String, String> options = new HashMap<>();
        options.put("persist-master", "false");
        options.put("master", "password");

        try {
            services.init(config, options);
        } catch (ServiceLifecycleException e) {
            LOG.error("Unable to init the services", e);
            throw Throwables.propagate(e);
        }

        URL resource = getClass().getClassLoader().getResource("services");
        // Copy the services definitions from the JAR
        copyResourcesRecursively(resource, stacksDir);

        StringWriter writer = new StringWriter();
        config.writeXml(writer);
        LOG.info("Using gateway-site.xml:{}", writer.toString());

        gatewayServer = GatewayServer.startGateway(config, services);
        LOG.info("Gateway address = " + gatewayServer.getURI());

        DefaultTopologyService topologyService = services.getService(DefaultGatewayServices.TOPOLOGY_SERVICE);
        Topology topology = topologyService.getTopologies().iterator().next();
        for (Service service : topology.getServices()) {
            LOG.info("Deployed: {} -> {}", service.getRole(), StringUtils.join(service.getUrls(), ","));
        }
    }

    @Override
    public void stop() throws Exception {
        stop(true);
    }

    @Override
    public void stop(boolean cleanUp) throws Exception {
        LOG.info("KNOX: Stopping GatewayServer");
        gatewayServer.stop();
        if (cleanUp) {
            cleanUp();
        }
    }

    @Override
    public void configure() throws Exception {
    }

    @Override
    public void cleanUp() throws Exception {
        FileUtils.deleteFolder(gatewayDir.getAbsolutePath());
        FileUtils.deleteFolder(new File(homeDir).getAbsolutePath());
    }

    public static boolean copyFile(final File toCopy, final File destFile) {
        try {
            return copyStream(new FileInputStream(toCopy), new FileOutputStream(destFile));
        } catch (final FileNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static boolean copyFilesRecusively(final File toCopy, final File destDir) {
        assert destDir.isDirectory();

        if (!toCopy.isDirectory()) {
            return copyFile(toCopy, new File(destDir, toCopy.getName()));
        } else {
            final File newDestDir = new File(destDir, toCopy.getName());
            if (!newDestDir.exists() && !newDestDir.mkdir()) {
                return false;
            }
            for (final File child : toCopy.listFiles()) {
                if (!copyFilesRecusively(child, newDestDir)) {
                    return false;
                }
            }
        }
        return true;
    }

    public static boolean copyJarResourcesRecursively(final File destDir, final JarURLConnection jarConnection)
            throws IOException {

        final JarFile jarFile = jarConnection.getJarFile();

        for (final Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements();) {
            final JarEntry entry = e.nextElement();
            if (entry.getName().startsWith(jarConnection.getEntryName())) {
                final String filename = StringUtils.removeStart(entry.getName(), //
                        jarConnection.getEntryName());

                final File f = new File(destDir, filename);
                if (!entry.isDirectory()) {
                    final InputStream entryInputStream = jarFile.getInputStream(entry);
                    if (!copyStream(entryInputStream, f)) {
                        return false;
                    }
                    entryInputStream.close();
                } else {
                    if (!ensureDirectoryExists(f)) {
                        throw new IOException("Could not create directory: " + f.getAbsolutePath());
                    }
                }
            }
        }
        return true;
    }

    public static boolean copyResourcesRecursively( //
            final URL originUrl, final File destination) {
        try {
            final URLConnection urlConnection = originUrl.openConnection();
            if (urlConnection instanceof JarURLConnection) {
                return copyJarResourcesRecursively(destination, (JarURLConnection) urlConnection);
            } else {
                return copyFilesRecusively(new File(originUrl.getPath()), destination);
            }
        } catch (final IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static boolean copyStream(final InputStream is, final File f) {
        try {
            return copyStream(is, new FileOutputStream(f));
        } catch (final FileNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static boolean copyStream(final InputStream is, final OutputStream os) {
        try {
            final byte[] buf = new byte[1024];

            int len = 0;
            while ((len = is.read(buf)) > 0) {
                os.write(buf, 0, len);
            }
            is.close();
            os.close();
            return true;
        } catch (final IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static boolean ensureDirectoryExists(final File f) {
        return f.exists() || f.mkdir();
    }
}