All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.disney.groovity.GroovityBuilder Maven / Gradle / Ivy

There is a newer version: 2.1.0-beta.1
Show newest version
/*******************************************************************************
 * © 2018 Disney | ABC Television Group
 *
 * Licensed under the Apache License, Version 2.0 (the "Apache License")
 * with the following modification; you may not use this file except in
 * compliance with the Apache License and the following modification to it:
 * Section 6. Trademarks. is deleted and replaced with:
 *
 * 6. Trademarks. This License does not grant permission to use the trade
 *     names, trademarks, service marks, or product names of the Licensor
 *     and its affiliates, except as required to comply with Section 4(c) of
 *     the License and to reproduce the content of the NOTICE file.
 *
 * You may obtain a copy of the Apache License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Apache License with the above modification is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the Apache License for the specific
 * language governing permissions and limitations under the Apache License.
 *******************************************************************************/
package com.disney.groovity;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.http.impl.client.HttpClientBuilder;

import com.disney.groovity.conf.Configurator;
import com.disney.groovity.conf.EnvConfigurator;
import com.disney.groovity.conf.MultiConfigurator;
import com.disney.groovity.conf.PropertiesFileConfigurator;
import com.disney.groovity.conf.PropertiesResourceConfigurator;
import com.disney.groovity.conf.PropertiesURLConfigurator;
import com.disney.groovity.conf.SystemConfigurator;
import com.disney.groovity.source.AbstractGroovitySourceLocator;
import com.disney.groovity.source.ClasspathGroovitySourceLocator;
import com.disney.groovity.source.FileGroovitySourceLocator;
import com.disney.groovity.source.GroovitySourceLocator;
import com.disney.groovity.source.HttpGroovitySourceLocator;

/**
 * A fluent builder API to configure and instantiate a Groovity.  Each of the setter
 * methods has comments describing the purpose of that option.
 * 
 * @author Alex Vigdor
 *
 */
public class GroovityBuilder {
	private ArgsLookup argsLookup = null;
	private int asyncThreads = 128;
	private Map defaultBinding;
	private BindingDecorator bindingDecorator;
	private boolean caseSensitive = true;
	private int maxHttpConnPerRoute = 128;
	private int maxHttpConnTotal = 512;
	private File jarDirectory = null;
	private EnumSet sourcePhases = EnumSet.of(GroovityPhase.STARTUP);
	private EnumSet jarPhases = EnumSet.of(GroovityPhase.STARTUP);
	private Collection sourceLocations = null;
	private Collection sourceLocators = null;
	private int sourcePollSeconds = -1;
	private String scriptBaseClass = "com.disney.groovity.GroovityScript";
	private HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().useSystemProperties();
	private ClassLoader parentClassLoader;
	private Configurator configurator;
	private String propsResource;
	private File propsFile;
	private URL propsURL;
	
	public Map getDefaultBinding() {
		return defaultBinding;
	}
	/**
	 * Add a map of default binding values to be provided to all scripts in this groovity
	 * 
	 * @param defaultBinding
	 * @return
	 */
	public GroovityBuilder setDefaultBinding(Map defaultBinding) {
		this.defaultBinding = defaultBinding;
		return this;
	}
	public int getAsyncThreads() {
		return asyncThreads;
	}
	/**
	 * Set the maximum number of threads available for async HTTP client calls
	 * 
	 * @param asyncThreads
	 * @return
	 */
	public GroovityBuilder setAsyncThreads(int asyncThreads) {
		this.asyncThreads = asyncThreads;
		return this;
	}
	public boolean isCaseSensitive() {
		return caseSensitive;
	}
	/**
	 * Set to false to enable case insensitive paths for loading and running scripts
	 * @param caseSensitive
	 * @return
	 */
	public GroovityBuilder setCaseSensitive(boolean caseSensitive) {
		this.caseSensitive = caseSensitive;
		return this;
	}
	public int getMaxHttpConnPerRoute() {
		return maxHttpConnPerRoute;
	}
	/**
	 * Set the maximum number of http client connections per route
	 * 
	 * @param maxHttpConnPerRoute
	 * @return
	 */
	public GroovityBuilder setMaxHttpConnPerRoute(int maxHttpConnPerRoute) {
		this.maxHttpConnPerRoute = maxHttpConnPerRoute;
		return this;
	}
	public int getMaxHttpConnTotal() {
		return maxHttpConnTotal;
	}
	/**
	 * Set max total number of simultaneous http client connections
	 * @param maxHttpConnTotal
	 * @return
	 */
	public GroovityBuilder setMaxHttpConnTotal(int maxHttpConnTotal) {
		this.maxHttpConnTotal = maxHttpConnTotal;
		return this;
	}
	public File getJarDirectory() {
		return jarDirectory;
	}
	/**
	 * Define the directory where JAR files are read/written (according to JarPhases)
	 * @param jarDirectory
	 * @return
	 */
	public GroovityBuilder setJarDirectory(File jarDirectory) {
		this.jarDirectory = jarDirectory;
		return this;
	}
	public EnumSet getSourcePhases() {
		return sourcePhases;
	}
	/**
	 * Set source phases (STARTUP = compile from source at startup, RUNTIME = automatically compile changes at runtime)
	 * @param sourcePhases
	 * @return
	 */
	public GroovityBuilder setSourcePhases(EnumSet sourcePhases) {
		this.sourcePhases = sourcePhases;
		return this;
	}
	public EnumSet getJarPhases() {
		return jarPhases;
	}
	/**
	 * Set jar phases (STARTUP = read from JAR files at startup, RUNTIME = write out JAR files during compilation)
	 * @param jarPhases
	 * @return
	 */
	public GroovityBuilder setJarPhases(EnumSet jarPhases) {
		this.jarPhases = jarPhases;
		return this;
	}
	/**
	 * Convenience method for setting source phases as a String, full support = "STARTUP,RUNTIME"
	 * @param phases
	 * @return
	 */
	public GroovityBuilder setSourcePhase(String phases){
		String[] ph = phases.split("\\s*,\\s*");
		EnumSet es = EnumSet.noneOf(GroovityPhase.class);
		if(ph[0].length()>0){
			for(String p: ph){
				es.add(GroovityPhase.valueOf(p));
			}
		}
		sourcePhases=es;
		return this;
	}
	/**
	 * Convenience method for setting jar phases as a string, full JAR support = "STARTUP,RUNTIME"
	 * @param phases
	 * @return
	 */
	public GroovityBuilder setJarPhase(String phases){
		String[] ph = phases.split("\\s*,\\s*");
		EnumSet es = EnumSet.noneOf(GroovityPhase.class);
		if(ph[0].length()>0){
			for(String p: ph){
				es.add(GroovityPhase.valueOf(p));
			}
		}
		jarPhases=es;
		return this;
	}
	public Collection getSourceLocations() {
		return sourceLocations;
	}
	/**
	 * Set locations where source files can be listed and retrieved
	 * 
	 * @param sourceLocations
	 * @return
	 */
	public GroovityBuilder setSourceLocations(Collection sourceLocations) {
		this.sourceLocations = sourceLocations;
		return this;
	}
	/**
	 * Set file or HTTP locations where source files can be listed and retrieved
	 * 
	 * @param sourceLocations
	 * @return
	 */
	public GroovityBuilder setSourceLocations(URI... sourceLocations) {
		this.sourceLocations = Arrays.asList(sourceLocations);
		return this;
	}
	/**
	 * After setting all initialization parameters, call build() to construct, initialize and return the fully started Groovity
	 * 
	 * @return an initialized Groovity
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 * @throws IOException
	 * @throws URISyntaxException
	 */
	public Groovity build() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException, URISyntaxException{
		return build(true);
	}
	/**
	 * After setting all initialization parameters, call build(true) to construct, initialize and return the fully started Groovity,
	 * or build(false) to initialize the Groovity without starting (e.g. to just build jar files without initing and starting classes)
	 * 
	 * @return an initialized Groovity
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 * @throws IOException
	 * @throws URISyntaxException
	 */
	public Groovity build(boolean start) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException, URISyntaxException{
		CopyOnWriteArrayList configurators = new CopyOnWriteArrayList();
		if(propsResource!=null){
			configurators.add(new PropertiesResourceConfigurator(propsResource));
		}
		if(propsFile!=null){
			configurators.add(new PropertiesFileConfigurator(propsFile));
		}
		if(propsURL!=null){
			configurators.add(new PropertiesURLConfigurator(propsURL));
		}
		configurators.add(new EnvConfigurator());
		configurators.add(new SystemConfigurator());
		if(configurator!=null){
			configurators.add(configurator);
		}
		Groovity groovity = new Groovity();
		groovity.setJarDirectory(jarDirectory);
		groovity.setJarPhases(jarPhases);
		groovity.setSourcePhases(sourcePhases);
		groovity.setCaseSensitive(caseSensitive);
		groovity.setArgsLookup(argsLookup);
		groovity.setAsyncThreads(asyncThreads);
		groovity.setScriptBaseClass(scriptBaseClass);
		groovity.setParentLoader(parentClassLoader);
		groovity.setConfigurator(new MultiConfigurator(configurators));
		final AtomicReference bindingDecoratorRef = new AtomicReference(bindingDecorator);
		if(defaultBinding!=null){
			bindingDecoratorRef.set(new BindingMapDecorator(new ConcurrentHashMap(defaultBinding),bindingDecoratorRef.get()));
		}
		ServiceLoader.load(BindingDecorator.class).forEach(decorator ->{
			decorator.setChainedDecorator(bindingDecoratorRef.get());
			bindingDecoratorRef.set(decorator);
		});
		groovity.setBindingDecorator(bindingDecoratorRef.get());
		if(httpClientBuilder==null){
			httpClientBuilder = HttpClientBuilder.create().useSystemProperties();
		}
		if(maxHttpConnPerRoute>0){
			httpClientBuilder.setMaxConnPerRoute(maxHttpConnPerRoute);
		}
		if(maxHttpConnTotal>0){
			httpClientBuilder.setMaxConnTotal(maxHttpConnTotal);
		}
		groovity.setHttpClient(httpClientBuilder.build());
		List locators = new ArrayList();
		if(sourceLocators!=null){
			for(GroovitySourceLocator locator: sourceLocators){
				locators.add(locator);
			}
		}
		if(sourceLocations!=null){
			for(URI location: sourceLocations){
				AbstractGroovitySourceLocator sourceLocator = null;
				String scheme = location.getScheme();
				if(scheme!=null){
					scheme = scheme.toLowerCase();
					if(scheme.startsWith("http")){
						sourceLocator = new HttpGroovitySourceLocator(location);
					}
					else if(scheme.equals("classpath")){
						sourceLocator = new ClasspathGroovitySourceLocator(location.getPath());
					}
				}
				if(sourceLocator==null){
					//file locator
					if(location.isAbsolute()){
						sourceLocator = new FileGroovitySourceLocator(new File(location));
					}
					else{
						sourceLocator = new FileGroovitySourceLocator(new File(location.getPath()));
					}
				}
				sourceLocator.setInterval(sourcePollSeconds);
				locators.add(sourceLocator);
			}
		}
		groovity.setSourceLocators(locators.toArray(new GroovitySourceLocator[0]));
		if(start) {
			groovity.start();
		}
		else {
			groovity.init(false);
		}
		return groovity;
	}
	public int getSourcePollSeconds() {
		return sourcePollSeconds;
	}
	/**
	 * If RUNTIME source phase is enabled, controls how frequently this Groovity will poll locators for source changes
	 * @param sourcePollSeconds
	 * @return
	 */
	public GroovityBuilder setSourcePollSeconds(int sourcePollSeconds) {
		this.sourcePollSeconds = sourcePollSeconds;
		return this;
	}
	public String getScriptBaseClass() {
		return scriptBaseClass;
	}
	/**
	 * Specify a base class for groovity scripts, defaults to core groovy Script
	 * 
	 * @param scriptBaseClass
	 * @return
	 */
	public GroovityBuilder setScriptBaseClass(String scriptBaseClass) {
		this.scriptBaseClass = scriptBaseClass;
		return this;
	}
	public BindingDecorator getBindingDecorator() {
		return bindingDecorator;
	}
	/**
	 * Define a binding decorator to use with scripts compiled in this Groovity
	 * 
	 * @param bindingDecorator
	 * @return
	 */
	public GroovityBuilder setBindingDecorator(BindingDecorator bindingDecorator) {
		this.bindingDecorator = bindingDecorator;
		return this;
	}
	public HttpClientBuilder getHttpClientBuilder() {
		return httpClientBuilder;
	}
	/**
	 * Pass in a custom HTTPClientBuilder in order to tailor HTTP client behavior, e.g. to add ehcache or custom interceptors
	 * 
	 * @param httpClientBuilder
	 * @return
	 */
	public GroovityBuilder setHttpClientBuilder(HttpClientBuilder httpClientBuilder) {
		this.httpClientBuilder = httpClientBuilder;
		return this;
	}
	public ClassLoader getParentClassLoader() {
		return parentClassLoader;
	}
	/**
	 * Provide a custom parent classloader that all groovity script loaders will inherit from.
	 * 
	 * @param parentClassLoader
	 * @return
	 */
	public GroovityBuilder setParentClassLoader(ClassLoader parentClassLoader) {
		this.parentClassLoader = parentClassLoader;
		return this;
	}
	public Collection getSourceLocators() {
		return sourceLocators;
	}
	/**
	 * Set the GroovitySourceLocators used by this groovity, a lower-level alternative to providing source URIs
	 * 
	 * @param sourceLocators
	 * @return
	 */
	public GroovityBuilder setSourceLocators(Collection sourceLocators) {
		this.sourceLocators = sourceLocators;
		return this;
	}
	public Configurator getConfigurator() {
		return configurator;
	}
	/**
	 * Attach a configurator to this Groovity to provide configuration data to scripts
	 * 
	 * @param configurator
	 * @return
	 */
	public GroovityBuilder setConfigurator(Configurator configurator) {
		this.configurator = configurator;
		return this;
	}
	public String getPropsResource() {
		return propsResource;
	}
	/**
	 * Set a classpath properties file location that acts a source of configuration values for groovity conf blocks
	 * @param propsResource
	 * @return
	 */
	public GroovityBuilder setPropsResource(String propsResource) {
		this.propsResource = propsResource;
		return this;
	}
	public File getPropsFile() {
		return propsFile;
	}
	/**
	 * Set a properties file that acts a source of configuration values for groovity conf blocks
	 * 
	 * @param propsFile
	 * @return
	 */
	public GroovityBuilder setPropsFile(File propsFile) {
		this.propsFile = propsFile;
		return this;
	}
	/**
	 * Set an arbitrary URL for a properties file that acts a source of configuration values for groovity conf blocks
	 * 
	 * @param propsUrl
	 * @return
	 */
	public GroovityBuilder setPropsUrl(URL propsUrl) {
		this.propsURL=propsUrl;
		return this;
	}
	public ArgsLookup getArgsLookup() {
		return argsLookup;
	}
	/**
	 * Define the ArgsLookup implementation to use for this groovity
	 * 
	 * @param argsLookup
	 * @return
	 */
	public GroovityBuilder setArgsLookup(ArgsLookup argsLookup) {
		this.argsLookup = argsLookup;
		return this;
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy