| // *************************************************************************************************************************** |
| // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * |
| // * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * |
| // * to you 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 org.apache.juneau.microservice; |
| |
| import java.io.*; |
| import java.nio.file.Paths; |
| import java.util.*; |
| import java.util.jar.*; |
| import java.util.logging.*; |
| |
| import org.apache.juneau.ExecutableException; |
| import org.apache.juneau.config.*; |
| import org.apache.juneau.config.store.*; |
| import org.apache.juneau.config.vars.*; |
| import org.apache.juneau.microservice.console.*; |
| import org.apache.juneau.svl.*; |
| import org.apache.juneau.utils.*; |
| |
| /** |
| * Builder for {@link Microservice} class. |
| * |
| * <p> |
| * Instances of this class are created using {@link Microservice#create()}. |
| */ |
| public class MicroserviceBuilder { |
| |
| Args args; |
| ManifestFile manifest; |
| Logger logger; |
| LogConfig logConfig; |
| Config config; |
| String configName; |
| ConfigStore configStore; |
| ConfigBuilder configBuilder = Config.create(); |
| Boolean consoleEnabled; |
| List<ConsoleCommand> consoleCommands = new ArrayList<>(); |
| VarResolverBuilder varResolverBuilder = VarResolver.create().defaultVars().vars(ConfigVar.class); |
| Scanner consoleReader; |
| PrintWriter consoleWriter; |
| MicroserviceListener listener; |
| File workingDir = System.getProperty("juneau.workingDir") == null ? null : new File(System.getProperty("juneau.workingDir")); |
| |
| /** |
| * Constructor. |
| */ |
| protected MicroserviceBuilder() {} |
| |
| /** |
| * Copy constructor. |
| * |
| * @param copyFrom The builder to copy settings from. |
| */ |
| protected MicroserviceBuilder(MicroserviceBuilder copyFrom) { |
| this.args = copyFrom.args; |
| this.manifest = copyFrom.manifest; |
| this.logger = copyFrom.logger; |
| this.configName = copyFrom.configName; |
| this.logConfig = copyFrom.logConfig == null ? null : copyFrom.logConfig.copy(); |
| this.consoleEnabled = copyFrom.consoleEnabled; |
| this.configBuilder = copyFrom.configBuilder; |
| this.varResolverBuilder = copyFrom.varResolverBuilder; |
| this.consoleReader = copyFrom.consoleReader; |
| this.consoleWriter = copyFrom.consoleWriter; |
| this.workingDir = copyFrom.workingDir; |
| } |
| |
| /** |
| * Creates a copy of this builder. |
| * |
| * @return A new copy of this builder. |
| */ |
| public MicroserviceBuilder copy() { |
| return new MicroserviceBuilder(this); |
| } |
| |
| /** |
| * Instantiate a new microservice using the settings defined on this builder. |
| * |
| * @return A new microservice. |
| * @throws Exception Error occurred. |
| */ |
| public Microservice build() throws Exception { |
| return new Microservice(this); |
| } |
| |
| /** |
| * Specifies the command-line arguments passed into the Java command. |
| * |
| * <p> |
| * This is required if you use {@link Microservice#getArgs()} or <c>$A</c> string variables. |
| * |
| * @param args |
| * The command-line arguments passed into the Java command as a pre-parsed {@link Args} object. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder args(Args args) { |
| this.args = args; |
| return this; |
| } |
| |
| /** |
| * Specifies the command-line arguments passed into the Java command. |
| * |
| * <p> |
| * This is required if you use {@link Microservice#getArgs()} or <c>$A</c> string variables. |
| * |
| * @param args |
| * The command-line arguments passed into the Java command as the raw command-line arguments. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder args(String...args) { |
| this.args = new Args(args); |
| return this; |
| } |
| |
| /** |
| * Specifies the manifest file of the jar file this microservice is contained within. |
| * |
| * <p> |
| * This is required if you use {@link Microservice#getManifest()}. |
| * It's also used to locate initialization values such as <c>Main-Config</c>. |
| * |
| * <p> |
| * If you do not specify the manifest file, we attempt to resolve it through the following methods: |
| * <ol class='spaced-list'> |
| * <li> |
| * Looking on the file system for a file at <js>"META-INF/MANIFEST.MF"</js>. |
| * This is primarily to allow for running microservices from within eclipse workspaces where the manifest file |
| * is located in the project root. |
| * <li> |
| * Using the class loader for this class to find the file at the URL <js>"META-INF/MANIFEST.MF"</js>. |
| * </ol> |
| * |
| * @param value |
| * The manifest file of this microservice. |
| * <br>Can be any of the following types: |
| * <ul> |
| * <li>{@link ManifestFile} |
| * <li>{@link Manifest} |
| * <li>{@link Reader} - Containing the raw contents of the manifest. Note that the input must end with a newline. |
| * <li>{@link InputStream} - Containing the raw contents of the manifest. Note that the input must end with a newline. |
| * <li>{@link File} - File containing the raw contents of the manifest. |
| * <li>{@link String} - Path to file containing the raw contents of the manifest. |
| * <li>{@link Class} - Finds and loads the manifest file of the jar file that the specified class is contained within. |
| * </ul> |
| * @return This object (for method chaining). |
| * @throws IOException Thrown by underlying stream. |
| */ |
| public MicroserviceBuilder manifest(Object value) throws IOException { |
| if (value == null) |
| this.manifest = null; |
| else if (value instanceof ManifestFile) |
| this.manifest = (ManifestFile)value; |
| else if (value instanceof Manifest) |
| this.manifest = new ManifestFile((Manifest)value); |
| else if (value instanceof Reader) |
| this.manifest = new ManifestFile((Reader)value); |
| else if (value instanceof InputStream) |
| this.manifest = new ManifestFile((InputStream)value); |
| else if (value instanceof File) |
| this.manifest = new ManifestFile((File)value); |
| else if (value instanceof String) |
| this.manifest = new ManifestFile(resolveFile((String)value)); |
| else if (value instanceof Class) |
| this.manifest = new ManifestFile((Class<?>)value); |
| else |
| throw new RuntimeException("Invalid type passed to MicroserviceBuilder.manifest(Object). Type=["+value.getClass().getName()+"]"); |
| |
| return this; |
| } |
| |
| /** |
| * Specifies the logger used by the microservice and returned by the {@link Microservice#getLogger()} method. |
| * |
| * <p> |
| * Calling this method overrides the default logging mechanism controlled by the {@link #logConfig(LogConfig)} method. |
| * |
| * @param logger The logger to use for logging microservice messages. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder logger(Logger logger) { |
| this.logger = logger; |
| return this; |
| } |
| |
| /** |
| * Specifies logging instructions for the microservice. |
| * |
| * <p> |
| * If not specified, the values are taken from the <js>"Logging"</js> section of the configuration. |
| * |
| * <p> |
| * This method is ignored if {@link #logger(Logger)} is used to set the microservice logger. |
| * |
| * @param logConfig The log configuration. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder logConfig(LogConfig logConfig) { |
| this.logConfig = logConfig; |
| return this; |
| } |
| |
| /** |
| * Specifies the config for initializing this microservice. |
| * |
| * <p> |
| * Calling this method overrides the default configuration controlled by the {@link #configName(String)} and {@link #configStore(ConfigStore)} methods. |
| * |
| * @param config The configuration. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder config(Config config) { |
| this.config = config; |
| return this; |
| } |
| |
| /** |
| * Specifies the config name for initializing this microservice. |
| * |
| * <p> |
| * If you do not specify the config file location, we attempt to resolve it through the following methods: |
| * <ol class='spaced-list'> |
| * <li> |
| * Resolve file first in working directory, then in classpath, using the following names: |
| * <ul> |
| * <li> |
| * The <js>"configFile"</js> argument in the command line arguments passed in through the constructor. |
| * <li> |
| * The value of the <c>Main-Config</c> entry in the manifest file. |
| * <li> |
| * A config file in the same location and with the same name as the executable jar file. |
| * (e.g. <js>"java -jar myjar.jar"</js> will look for <js>"myjar.cfg"</js>). |
| * </ul> |
| * <li> |
| * Resolve any <js>"*.cfg"</js> file that can be found in the working directory. |
| * <li> |
| * Resolve any of the following files in the classpath: <js>"juneau.cfg"</js>, <js>"system.cfg"</js> |
| * </ol> |
| * |
| * <p> |
| * If no configuration file is found, and empty in-memory configuration is used. |
| * |
| * @param configName The configuration name. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder configName(String configName) { |
| this.configName = configName; |
| return this; |
| } |
| |
| /** |
| * Specifies the config store to use for storing and retrieving configurations. |
| * |
| * <p> |
| * By default, we use a {@link ConfigFileStore} store for configuration files. |
| * |
| * @param configStore The configuration name. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder configStore(ConfigStore configStore) { |
| this.configStore = configStore; |
| return this; |
| } |
| |
| /** |
| * Specifies that the Java console is enabled for this microservice. |
| * |
| * <p> |
| * If not specified, this value is taken from the <js>"Console/enabled"</js> configuration setting. |
| * If not specified in the configuration, defaults to <jk>false</jk>. |
| * |
| * @param consoleEnabled <jk>true</jk> if the Java console is enabled for this microservice. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder consoleEnabled(boolean consoleEnabled) { |
| this.consoleEnabled = consoleEnabled; |
| return this; |
| } |
| |
| /** |
| * Specifies console commands to make available on the Java console. |
| * |
| * <p> |
| * Note that these are ignored if the console is not enabled via {@link #consoleEnabled(boolean)}. |
| * |
| * <p> |
| * This list augments the commands defined via the <js>"Console/commands"</js> configuration setting. |
| * |
| * <p> |
| * This method can only be used on console commands with no-arg constructors. |
| * |
| * @param consoleCommands The list of console commands to append to the list of available commands. |
| * @return This object (for method chaining). |
| * @throws ExecutableException Exception occurred on invoked constructor/method/field. |
| */ |
| @SuppressWarnings("unchecked") |
| public MicroserviceBuilder consoleCommands(Class<? extends ConsoleCommand>...consoleCommands) throws ExecutableException { |
| try { |
| for (Class<? extends ConsoleCommand> cc : consoleCommands) |
| this.consoleCommands.add(cc.newInstance()); |
| } catch (InstantiationException | IllegalAccessException e) { |
| throw new ExecutableException(e); |
| } |
| return this; |
| } |
| |
| /** |
| * Specifies console commands to make available on the Java console. |
| * |
| * <p> |
| * Note that these are ignored if the console is not enabled via {@link #consoleEnabled(boolean)}. |
| * |
| * <p> |
| * This list augments the commands defined via the <js>"Console/commands"</js> configuration setting. |
| * |
| * @param consoleCommands The list of console commands to append to the list of available commands. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder consoleCommands(ConsoleCommand...consoleCommands) { |
| this.consoleCommands.addAll(Arrays.asList(consoleCommands)); |
| return this; |
| } |
| |
| /** |
| * Specifies the console input and output. |
| * |
| * <p> |
| * If not specified, uses the console returned by {@link System#console()}. |
| * If that is not available, uses {@link System#in} and {@link System#out}. |
| * |
| * <p> |
| * Note that these are ignored if the console is not enabled via {@link #consoleEnabled(boolean)}. |
| * |
| * @param consoleReader The console input. |
| * @param consoleWriter The console output. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder console(Scanner consoleReader, PrintWriter consoleWriter) { |
| this.consoleReader = consoleReader; |
| this.consoleWriter = consoleWriter; |
| return this; |
| } |
| |
| /** |
| * Augments the set of variables defined in the configuration and var resolver. |
| * |
| * <p> |
| * This calls {@link VarResolverBuilder#vars(Class[])} on the var resolver used to construct the configuration |
| * object returned by {@link Microservice#getConfig()} and the var resolver returned by {@link Microservice#getVarResolver()}. |
| * |
| * @param vars The set of variables to append to the var resolver builder. |
| * @return This object (for method chaining). |
| */ |
| @SuppressWarnings("unchecked") |
| public MicroserviceBuilder vars(Class<? extends Var>...vars) { |
| varResolverBuilder.vars(vars); |
| return this; |
| } |
| |
| /** |
| * Adds a var resolver context object for vars defined in the configuration and var resolver. |
| * |
| * <p> |
| * This calls {@link VarResolverBuilder#contextObject(String,Object)} on the var resolver used to construct the configuration |
| * object returned by {@link Microservice#getConfig()} and the var resolver returned by {@link Microservice#getVarResolver()}. |
| * |
| * @param name The context object name. |
| * @param object The context object. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder varContext(String name, Object object) { |
| varResolverBuilder.contextObject(name, object); |
| return this; |
| } |
| |
| /** |
| * Specifies the directory to use to resolve the config file and other paths defined with the config file. |
| * |
| * @param workingDir The working directory, or <jk>null</jk> to use the underlying working directory. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder workingDir(File workingDir) { |
| this.workingDir = workingDir; |
| return this; |
| } |
| |
| /** |
| * Specifies the directory to use to resolve the config file and other paths defined with the config file. |
| * |
| * @param workingDir The working directory, or <jk>null</jk> to use the underlying working directory. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder workingDir(String workingDir) { |
| this.workingDir = new File(workingDir); |
| return this; |
| } |
| |
| /** |
| * Registers an event listener for this microservice. |
| * |
| * @param listener An event listener for this microservice. |
| * @return This object (for method chaining). |
| */ |
| public MicroserviceBuilder listener(MicroserviceListener listener) { |
| this.listener = listener; |
| return this; |
| } |
| |
| /** |
| * Resolves the specified path. |
| * |
| * <p> |
| * If the working directory has been explicitly specified, relative paths are resolved relative to that. |
| * |
| * @param path The path to resolve. |
| * @return The resolved file. |
| */ |
| protected File resolveFile(String path) { |
| if (Paths.get(path).isAbsolute()) |
| return new File(path); |
| if (workingDir != null) |
| return new File(workingDir, path); |
| return new File(path); |
| } |
| } |