io.knotx.launcher.KnotxModuleVerticleFactory.java Source code

Java tutorial

Introduction

Here is the source code for io.knotx.launcher.KnotxModuleVerticleFactory.java

Source

/*
 * Copyright (C) 2016 Cognifide Limited
 *
 * 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.knotx.launcher;

import io.knotx.util.JsonObjectUtil;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
import io.vertx.core.Verticle;
import io.vertx.core.json.DecodeException;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import io.vertx.core.spi.VerticleFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.NoSuchElementException;
import java.util.Scanner;

public class KnotxModuleVerticleFactory implements VerticleFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(KnotxModuleVerticleFactory.class);
    private static final String CONFIG_KEY = "config";
    private static final String OPTIONS_KEY = "options";

    @Override
    public boolean requiresResolve() {
        return true;
    }

    @Override
    public void resolve(String id, DeploymentOptions deploymentOptions, ClassLoader classLoader,
            Future<String> resolution) {
        String identifier = VerticleFactory.removePrefix(id);
        String descriptorFile = identifier + ".json";
        try {
            JsonObject descriptor = readDescriptor(classLoader, descriptorFile);
            String main = readVerticleMainClass(descriptor, descriptorFile);

            // Any options specified in the module config will override anything specified at deployment time
            // Options and Config specified in knotx starter JSON will override those configurations
            JsonObject depOptions = deploymentOptions.toJson();
            JsonObject depConfig = depOptions.getJsonObject(CONFIG_KEY, new JsonObject());

            JsonObject knotOptions = descriptor.getJsonObject(OPTIONS_KEY, new JsonObject());
            JsonObject knotConfig = knotOptions.getJsonObject(CONFIG_KEY, new JsonObject());
            depOptions.mergeIn(knotOptions);
            depOptions.put(CONFIG_KEY, JsonObjectUtil.deepMerge(knotConfig, depConfig));

            JsonObject serviceDescriptor = new JsonObject().put(OPTIONS_KEY, depOptions);

            // Any options or config provided by system properties will override anything specified
            // at deployment time and on starter Json config
            serviceDescriptor = overrideConfigWithSystemProperties(identifier, serviceDescriptor);

            deploymentOptions.fromJson(serviceDescriptor.getJsonObject(OPTIONS_KEY));
            resolution.complete(main);
        } catch (Exception e) {
            resolution.fail(e);
        }
    }

    private JsonObject overrideConfigWithSystemProperties(String identifier, JsonObject descriptor) {
        JsonObject result = descriptor;
        try {
            SystemPropsConfiguration systemPropsConfiguration = new SystemPropsConfiguration(identifier);
            if (!systemPropsConfiguration.envConfig().isEmpty()) {
                result = systemPropsConfiguration.updateJsonObject(descriptor);
            }
        } catch (IllegalArgumentException ex) {
            LOGGER.warn("Unable to parse given system properties due to exception", ex);
        }

        return result;
    }

    @Override
    public String prefix() {
        return "knotx";
    }

    private String readVerticleMainClass(JsonObject descriptor, String descriptorFile) {
        String main = descriptor.getString("main");
        if (main == null) {
            throw new IllegalArgumentException(descriptorFile + " does not contain a main field");
        }
        return main;
    }

    @Override
    public Verticle createVerticle(String verticleName, ClassLoader classLoader) throws Exception {
        throw new IllegalStateException("Shouldn't be called");
    }

    private JsonObject readDescriptor(ClassLoader classLoader, String descriptorFile) throws IOException {
        JsonObject descriptor;
        try (InputStream is = classLoader.getResourceAsStream(descriptorFile)) {
            if (is == null) {
                throw new IllegalArgumentException(
                        "Cannot find module descriptor file " + descriptorFile + " on classpath");
            }
            try (Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A")) {
                String conf = scanner.next();
                descriptor = new JsonObject(conf);
            } catch (NoSuchElementException e) {
                throw new IllegalArgumentException(descriptorFile + " is empty", e);
            } catch (DecodeException e) {
                throw new IllegalArgumentException(descriptorFile + " contains invalid json", e);
            }
        }

        return descriptor;
    }

}