com.ottogroup.bi.asap.node.server.AsapProcessingNodeServer.java Source code

Java tutorial

Introduction

Here is the source code for com.ottogroup.bi.asap.node.server.AsapProcessingNodeServer.java

Source

/**
 * Copyright 2014 Otto (GmbH & Co KG)
 *
 * 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.ottogroup.bi.asap.node.server;

import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.ottogroup.bi.asap.exception.RemoteClientConnectionFailedException;
import com.ottogroup.bi.asap.exception.RequiredInputMissingException;
import com.ottogroup.bi.asap.message.registration.ProcessingNodeRegistration.ProcessingNodeRegistrationResponse;
import com.ottogroup.bi.asap.message.registration.ProcessingNodeRegistration.ProcessingNodeRegistrationState;
import com.ottogroup.bi.asap.node.resource.AsapResourceManagerClient;
import com.ottogroup.bi.asap.node.resource.pipeline.PipelineResource;
import com.ottogroup.bi.asap.node.server.configuration.ApplicationRepositoryConfiguration;
import com.ottogroup.bi.asap.node.server.configuration.AsapProcessingNodeConfiguration;
import com.ottogroup.bi.asap.pipeline.MicroPipelineManager;
import com.ottogroup.bi.asap.repository.ComponentDescriptor;
import com.ottogroup.bi.asap.repository.ComponentRepository;

/**
 * Core component ramping up the asap processing node
 * @author mnxfst
 * @since Nov 26, 2014
 */
public class AsapProcessingNodeServer extends Application<AsapProcessingNodeConfiguration> {

    /** our faithful logging facility ;-) */
    private static final Logger logger = Logger.getLogger(AsapProcessingNodeServer.class);

    /** pipeline manager */
    private MicroPipelineManager pipelineManager;
    /** resource manager client */
    private AsapResourceManagerClient resourceManagerClient;

    /**
     * @see io.dropwizard.Application#initialize(io.dropwizard.setup.Bootstrap)
     */
    public void initialize(Bootstrap<AsapProcessingNodeConfiguration> bootstrap) {
    }

    /**
     * @see io.dropwizard.Application#run(io.dropwizard.Configuration, io.dropwizard.setup.Environment)
     */
    public void run(AsapProcessingNodeConfiguration configuration, Environment environment) throws Exception {

        PropertyConfigurator.configure(configuration.getLog4jConfiguration());

        this.pipelineManager = new MicroPipelineManager(
                loadAndDeployApplicationRepository(configuration.getApplicationRepository()));
        environment.jersey().register(new PipelineResource(this.pipelineManager));

        this.resourceManagerClient = new AsapResourceManagerClient(configuration.getResourceManagerConfiguration());
        try {
            ProcessingNodeRegistrationResponse registrationResponse = this.resourceManagerClient
                    .registerProcessingNode(InetAddress.getLocalHost().getHostName(),
                            configuration.getServicePort(), configuration.getAdminPort());
            if (registrationResponse == null) {
                logger.error(
                        "Failed to register processing node with remote resource manager. Error: no response received. Processing node operates in standalone mode");
            } else {
                if (registrationResponse.getState() != ProcessingNodeRegistrationState.OK)
                    throw new RuntimeException(
                            "[error=" + registrationResponse.getState() + "] " + registrationResponse.getMessage());
            }
        } catch (RemoteClientConnectionFailedException e) {
            logger.error(
                    "Failed to register processing node with remote resource manager. Error: no response received. Processing node operates in standalone mode");
        }
    }

    /**
     * Reads contents from {@link ApplicationRepositoryConfiguration referenced repository} and deploys them to given
     * {@link ActorRef deployment receiver}.
     * @param cfg
     * @param jarDeploymentReceiverRef
     * @throws RequiredInputMissingException
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    public ComponentRepository loadAndDeployApplicationRepository(final ApplicationRepositoryConfiguration cfg)
            throws RequiredInputMissingException, JsonParseException, JsonMappingException, IOException {

        ////////////////////////////////////////////////////////////////////////////
        // validate provided input and ensure that folder exists
        if (cfg == null)
            throw new RequiredInputMissingException("Missing required input for parameter 'cfg'");

        if (StringUtils.isBlank(cfg.getRepositoryPath()))
            throw new RequiredInputMissingException("Missing required input for parameter 'repositoryPath'");

        File repositoryFolder = new File(cfg.getRepositoryPath());
        if (repositoryFolder == null || !repositoryFolder.isDirectory())
            throw new RequiredInputMissingException(
                    "No repository found at provided folder '" + cfg.getRepositoryPath() + "'");
        //
        ////////////////////////////////////////////////////////////////////////////

        ////////////////////////////////////////////////////////////////////////////

        final ComponentRepository library = new ComponentRepository();

        ////////////////////////////////////////////////////////////////////////////
        // find component repositories below repository folder 
        File[] repoFolders = repositoryFolder.listFiles();
        if (repoFolders == null || repoFolders.length < 1)
            return library;
        //
        ////////////////////////////////////////////////////////////////////////////

        ////////////////////////////////////////////////////////////////////////////
        // for each entry check if it is a folder and pass it on the library
        int folderCount = 0;
        int componentsCount = 0;
        for (File folder : repoFolders) {
            if (folder.isDirectory()) {
                try {
                    logger.info("Processing folder '" + folder.getAbsolutePath() + "'");
                    Map<String, ComponentDescriptor> descriptors = library
                            .addComponentFolder(folder.getAbsolutePath());
                    componentsCount = componentsCount + descriptors.size();
                    folderCount++;
                } catch (Exception e) {
                    logger.error("Failed to add folder '" + folder.getAbsolutePath()
                            + "' to component repository. Error: " + e.getMessage());
                }
            }
        }
        //
        ////////////////////////////////////////////////////////////////////////////

        logger.info("Components deployment finished [repo=" + cfg.getRepositoryPath() + ", componentFolders="
                + folderCount + ", componets=" + componentsCount + "]");
        return library;
    }

    /**
     * Reads the contents from the referenced files and returns them as array of bytes
     * @param fileName
     * @return
     * @throws IOException
     */
    protected byte[] readFileContents(final String fileName) throws IOException, RequiredInputMissingException {

        if (StringUtils.isBlank(fileName))
            throw new RequiredInputMissingException("Missing required input for parameter 'fileName'");

        ///////////////////////////////////////////////////////////////////////////////////
        // read repo file contents
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName));
        int read = 0;
        final ByteArrayOutputStream os = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024]; // buffer size
        while ((read = bis.read(buffer)) != -1) {
            os.write(buffer, 0, read);
        }
        bis.close();
        //
        ///////////////////////////////////////////////////////////////////////////////////

        return os.toByteArray();
    }

    /**
     * Run the server component
     * @param args
     */
    public static void main(String[] args) throws Exception {
        new AsapProcessingNodeServer().run(args);
    }

}