diff --git a/grails-aether/src/main/groovy/org/grails/dependency/resolution/maven/aether/AetherDependencyManager.groovy b/grails-aether/src/main/groovy/org/grails/dependency/resolution/maven/aether/AetherDependencyManager.groovy index 70f92c0494c..19506a5572d 100644 --- a/grails-aether/src/main/groovy/org/grails/dependency/resolution/maven/aether/AetherDependencyManager.groovy +++ b/grails-aether/src/main/groovy/org/grails/dependency/resolution/maven/aether/AetherDependencyManager.groovy @@ -16,7 +16,6 @@ package org.grails.dependency.resolution.maven.aether import grails.build.logging.GrailsConsole -import grails.util.BuildSettings import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode import groovy.util.slurpersupport.GPathResult @@ -198,7 +197,7 @@ class AetherDependencyManager implements DependencyManager { } void produceReport(String scope) { - final desc = BuildSettings.SCOPE_TO_DESC[scope] + final desc = SCOPE_TO_DESC[scope] if (desc) { reportOnScope(scope, desc) } else { @@ -241,15 +240,15 @@ class AetherDependencyManager implements DependencyManager { void produceReport() { // build scope - reportOnScope(BuildSettings.BUILD_SCOPE, BuildSettings.BUILD_SCOPE_DESC) + reportOnScope(BUILD_SCOPE, BUILD_SCOPE_DESC) // provided scope - reportOnScope(BuildSettings.PROVIDED_SCOPE, BuildSettings.PROVIDED_SCOPE_DESC) + reportOnScope(PROVIDED_SCOPE, PROVIDED_SCOPE_DESC) // compile scope - reportOnScope(BuildSettings.COMPILE_SCOPE, BuildSettings.COMPILE_SCOPE_DESC) + reportOnScope(COMPILE_SCOPE, COMPILE_SCOPE_DESC) // runtime scope - reportOnScope(BuildSettings.RUNTIME_SCOPE, BuildSettings.RUNTIME_SCOPE_DESC) + reportOnScope(RUNTIME_SCOPE, RUNTIME_SCOPE_DESC) // test scope - reportOnScope(BuildSettings.TEST_SCOPE, BuildSettings.TEST_SCOPE_DESC) + reportOnScope(TEST_SCOPE, TEST_SCOPE_DESC) } protected void reportOnScope(String scope, String desc) { @@ -669,7 +668,7 @@ class AetherDependencyManager implements DependencyManager { dependency.group == 'org.grails.plugins' || dependency.extension == 'zip' } - DependencyManager createCopy(BuildSettings buildSettings = null) { + DependencyManager createCopy() { AetherDependencyManager dependencyManager = new AetherDependencyManager() dependencyManager.repositories = this.repositories dependencyManager.settings = this.settings diff --git a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java index de7d89d1fac..e2b184fedcb 100644 --- a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java +++ b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java @@ -43,10 +43,9 @@ import jline.internal.TerminalLineSettings; import org.apache.tools.ant.BuildException; -import org.codehaus.groovy.grails.cli.ScriptExitException; -import org.codehaus.groovy.grails.cli.interactive.CandidateListCompletionHandler; -import org.codehaus.groovy.grails.cli.logging.GrailsConsoleErrorPrintStream; -import org.codehaus.groovy.grails.cli.logging.GrailsConsolePrintStream; +import org.grails.build.interactive.CandidateListCompletionHandler; +import org.grails.build.logging.GrailsConsoleErrorPrintStream; +import org.grails.build.logging.GrailsConsolePrintStream; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.runtime.StackTraceUtils; import org.codehaus.groovy.runtime.typehandling.NumberMath; @@ -679,10 +678,6 @@ public void error(Throwable error) { } private void printStackTrace(String message, Throwable error) { - if (error instanceof ScriptExitException) { - return; // don't bother with exit exceptions - } - if ((error instanceof BuildException) && error.getCause() != null) { error = error.getCause(); } diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/support/MetaClassRegistryCleaner.java b/grails-bootstrap/src/main/groovy/grails/build/support/MetaClassRegistryCleaner.java similarity index 99% rename from grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/support/MetaClassRegistryCleaner.java rename to grails-bootstrap/src/main/groovy/grails/build/support/MetaClassRegistryCleaner.java index 72c73e998a0..2050708d033 100644 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/support/MetaClassRegistryCleaner.java +++ b/grails-bootstrap/src/main/groovy/grails/build/support/MetaClassRegistryCleaner.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.codehaus.groovy.grails.cli.support; +package grails.build.support; import groovy.lang.ExpandoMetaClass; import groovy.lang.GroovySystem; diff --git a/grails-bootstrap/src/main/groovy/grails/config/ConfigMap.groovy b/grails-bootstrap/src/main/groovy/grails/config/ConfigMap.groovy index 454ff01db20..5a868e7ee69 100644 --- a/grails-bootstrap/src/main/groovy/grails/config/ConfigMap.groovy +++ b/grails-bootstrap/src/main/groovy/grails/config/ConfigMap.groovy @@ -10,9 +10,8 @@ import org.codehaus.groovy.runtime.DefaultGroovyMethods class ConfigMap implements Map { final ConfigMap rootConfig final List path - @Delegate final Map delegateMap - + public ConfigMap() { rootConfig = this path = [] @@ -25,7 +24,67 @@ class ConfigMap implements Map { this.path = path delegateMap = [:] } - + + @Override + int size() { + delegateMap.size() + } + + @Override + boolean isEmpty() { + delegateMap.isEmpty() + } + + @Override + boolean containsKey(Object key) { + delegateMap.containsKey key + } + + @Override + boolean containsValue(Object value) { + delegateMap.containsValue value + } + + @Override + Object get(Object key) { + delegateMap.get(key) + } + + @Override + Object put(String key, Object value) { + delegateMap.put(key, value) + } + + @Override + Object remove(Object key) { + delegateMap.remove key + } + + @Override + void putAll(Map m) { + delegateMap.putAll m + } + + @Override + void clear() { + delegateMap.clear() + } + + @Override + Set keySet() { + delegateMap.keySet() + } + + @Override + Collection values() { + delegateMap.values() + } + + @Override + Set> entrySet() { + delegateMap.entrySet() + } + public void merge(Map sourceMap, boolean parseFlatKeys=false) { mergeMaps(this, sourceMap, parseFlatKeys) } @@ -53,7 +112,7 @@ class ConfigMap implements Map { Object currentValue = targetMap.containsKey(sourceKey) ? targetMap.get(sourceKey) : null Object newValue if(sourceValue instanceof Map) { - ConfigMap subMap = new ConfigMap(targetMap.rootConfig, ((targetMap.path + [sourceKey]) as List).asImmutable()) + ConfigMap subMap = new ConfigMap( (ConfigMap)targetMap.rootConfig, ((targetMap.path + [sourceKey]) as List).asImmutable()) if(currentValue instanceof Map) { subMap.putAll((Map)currentValue) } @@ -110,7 +169,7 @@ class ConfigMap implements Map { if(currentItem instanceof ConfigMap) { currentMap = (ConfigMap)currentItem } else if (createMissing) { - Map newMap = new ConfigMap(currentMap.rootConfig, ((currentMap.path + [pathElement]) as List).asImmutable()) + Map newMap = new ConfigMap( (ConfigMap)currentMap.rootConfig, ((currentMap.path + [pathElement]) as List).asImmutable()) currentMap.put(pathElement, newMap) currentMap = newMap } else { @@ -166,7 +225,7 @@ class ConfigMap implements Map { } @CompileStatic - private static class NullSafeNavigator { + static class NullSafeNavigator { final ConfigMap parent final List path diff --git a/grails-bootstrap/src/main/groovy/grails/config/GrailsConfig.groovy b/grails-bootstrap/src/main/groovy/grails/config/GrailsConfig.groovy index faac74844e7..6e553b91047 100644 --- a/grails-bootstrap/src/main/groovy/grails/config/GrailsConfig.groovy +++ b/grails-bootstrap/src/main/groovy/grails/config/GrailsConfig.groovy @@ -7,43 +7,46 @@ import org.yaml.snakeyaml.Yaml @CompileStatic @Canonical -public class GrailsConfig implements Cloneable { +class GrailsConfig implements Cloneable { final ConfigMap configMap - public GrailsConfig() { + GrailsConfig() { configMap = new ConfigMap() } - public GrailsConfig(GrailsConfig copyOf) { + GrailsConfig(GrailsConfig copyOf) { this(copyOf.@configMap) } - public GrailsConfig(Map copyOf) { + GrailsConfig(Map copyOf) { this() mergeMap(copyOf) } - public GrailsConfig clone() { + GrailsConfig clone() { new GrailsConfig(this) } - public void loadYml(File ymlFile) { + void loadYml(File ymlFile) { ymlFile.withInputStream { InputStream input -> loadYml(input) } } @groovy.transform.CompileDynamic // fails with CompileStatic! - public void loadYml(InputStream input) { + void loadYml(InputStream input) { Yaml yaml = new Yaml() for(Object yamlObject : yaml.loadAll(input)) { if(yamlObject instanceof Map) { // problem here with CompileStatic mergeMap((Map)yamlObject) } } + + def flatConfig = configMap.toFlatConfig() + configMap.putAll(flatConfig) } - public void mergeMap(Map sourceMap, boolean parseFlatKeys=false) { + void mergeMap(Map sourceMap, boolean parseFlatKeys=false) { configMap.merge(sourceMap, parseFlatKeys) } @@ -56,7 +59,10 @@ public class GrailsConfig implements Cloneable { } protected T convertToType(Object value, Class requiredType) { - if(requiredType.isInstance(value)) { + if(value instanceof ConfigMap.NullSafeNavigator) { + return null + } + else if(requiredType.isInstance(value)) { return (T)value } if(requiredType==String.class) { @@ -132,6 +138,16 @@ public class GrailsConfig implements Cloneable { return this.configMap return configMap.getProperty(name) } + + public Object get(String name) { + if ("configMap".equals(name)) + return this.configMap + return configMap.getProperty(name) + } + + public T getProperty(String name, Class requiredType) { + return convertToType( configMap.getProperty(name), requiredType ) + } public void setProperty(String name, Object value) { configMap.setProperty(name, value) diff --git a/grails-bootstrap/src/main/groovy/grails/ui/console/GrailsSwingConsole.groovy b/grails-bootstrap/src/main/groovy/grails/ui/console/GrailsSwingConsole.groovy deleted file mode 100644 index 85f0985af05..00000000000 --- a/grails-bootstrap/src/main/groovy/grails/ui/console/GrailsSwingConsole.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2013 SpringSource - * - * 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 grails.ui.console - -import grails.util.BuildSettings -import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.cli.fork.ForkedGrailsProjectClassExecutor - -/** - * Forks a Groovy Swing console UI for the current application - * - * @author Graeme Rocher - * @since 2.3 - */ -@CompileStatic -class GrailsSwingConsole extends ForkedGrailsProjectClassExecutor{ - - GrailsSwingConsole(BuildSettings buildSettings) { - super(buildSettings) - } - - protected GrailsSwingConsole() { - } - - static void main(String[] args) { - new GrailsSwingConsole().run() - } - - @Override - protected URLClassLoader initializeClassLoader(BuildSettings buildSettings) { - final classLoader = (GroovyClassLoader)super.initializeClassLoader(buildSettings) - final existing = classLoader.URLs - for (File f in buildSettings.testDependencies) { - final jarURL = f.toURI().toURL() - if (!existing.contains(jarURL)) { - classLoader.addURL(jarURL) - } - } - - return classLoader - } - - @Override - protected String getProjectClassType() { "org.codehaus.groovy.grails.project.ui.GrailsProjectConsole" } - - @Override - int runInstance(instance) { - ((GroovyObject)instance).invokeMethod("run", null) - return 0 - } -} diff --git a/grails-bootstrap/src/main/groovy/grails/util/AbstractBuildSettings.java b/grails-bootstrap/src/main/groovy/grails/util/AbstractBuildSettings.java deleted file mode 100644 index 894018e91f7..00000000000 --- a/grails-bootstrap/src/main/groovy/grails/util/AbstractBuildSettings.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2004-2005 the original author or authors. - * - * 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 grails.util; - -import groovy.util.ConfigObject; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * Methods optimized to Java for the BuildSettings class. - * - * @since 1.3.4 - */ -public abstract class AbstractBuildSettings { - - private static final String KEY_PLUGIN_DIRECTORY_RESOURCES = "pluginDirectoryResources"; - private static final String KEY_INLINE_PLUGIN_LOCATIONS = "inlinePluginLocations"; - private static final String KEY_PLUGIN_BASE_DIRECTORIES = "pluginBaseDirectories"; - - /** - * Used to cache results of certain expensive operations - */ - protected Map cache = new ConcurrentHashMap(); - /** The settings stored in the project's BuildConfig.groovy file if there is one. */ - protected ConfigObject config = new ConfigObject(); - /** The location where project-specific plugins are installed to. */ - protected File projectPluginsDir; - - /** The location where global plugins are installed to. */ - protected File globalPluginsDir; - - protected boolean projectPluginsDirSet; - protected boolean globalPluginsDirSet; - - /** - * Flattened version of the ConfigObject for easy access from Java - */ - @SuppressWarnings("rawtypes") - protected Map flatConfig = Collections.emptyMap(); - - abstract File getBaseDir(); - - /** - * Clears any locally cached values - */ - void clearCache() { - cache.clear(); - } - - public ConfigObject getConfig() { - return config; - } - - public void setConfig(ConfigObject config) { - this.config = config; - } - - public File getProjectPluginsDir() { - return projectPluginsDir; - } - - public void setProjectPluginsDir(File projectPluginsDir) { - this.projectPluginsDir = projectPluginsDir; - projectPluginsDirSet = true; - } - - public File getGlobalPluginsDir() { - return globalPluginsDir; - } - - public void setGlobalPluginsDir(File globalPluginsDir) { - this.globalPluginsDir = globalPluginsDir; - globalPluginsDirSet = true; - } - - /** - * Adds a plugin directory - * @param location The plugin's locatino - */ - public void addPluginDirectory(File location, boolean isInline) { - getPluginDirectories(); - if (location != null) { - Collection directories = getPluginDirectories(); - if (!directories.contains(location)) { - directories.add(location); - if (isInline) { - getInlinePluginDirectories().add(location); - } - } - } - } - - /** - * Obtains a list of plugin directories for the application - */ - @SuppressWarnings("unchecked") - public Collection getPluginDirectories() { - Collection pluginDirectoryResources = (Collection)cache.get(KEY_PLUGIN_DIRECTORY_RESOURCES); - if (pluginDirectoryResources == null) { - pluginDirectoryResources = getImplicitPluginDirectories(); - - // Also add any explicit plugin locations specified by the - // BuildConfig setting "grails.plugin.location." - Collection inlinePlugins = getInlinePluginsFromConfiguration(config); - cache.put(KEY_INLINE_PLUGIN_LOCATIONS, inlinePlugins); - ArrayList list = new ArrayList(pluginDirectoryResources); - list.addAll(inlinePlugins); - Collections.reverse(list); - pluginDirectoryResources = new ConcurrentLinkedQueue(list); - - cache.put(KEY_PLUGIN_DIRECTORY_RESOURCES, pluginDirectoryResources); - } - return pluginDirectoryResources; - } - - /** - * Extracts the inline plugin dirs relative to the base dir of this project. - * - * @see #getInlinePluginsFromConfiguration(Map, File) - */ - @SuppressWarnings({ "rawtypes" }) - protected Collection getInlinePluginsFromConfiguration(Map config) { - return getInlinePluginsFromConfiguration(config, getBaseDir()); - } - - /** - * Extracts the inline plugin dirs from the given config, relative to the given baseDir. - * - * TODO: consider trowing an error here if an plugin does not exists at the location. - */ - @SuppressWarnings("rawtypes") - protected Collection getInlinePluginsFromConfiguration(Map config, File baseDir) { - Collection inlinePlugins = new ConcurrentLinkedQueue(); - if (config != null) { - Map pluginLocations = lookupPluginLocationConfig(config); - if (pluginLocations != null) { - for (Object value : pluginLocations.values()) { - if (value != null) { - File resource; - try { - // GRAILS-7045: Check whether the plugin location is absolute - // before resolving against the project's base dir. - resource = new File(value.toString()); - if (!resource.isAbsolute()) { - resource = new File(baseDir, resource.getPath()); - } - - resource = resource.getCanonicalFile(); - inlinePlugins.add(resource); - } - catch (IOException e) { - System.err.println("Cannot add location ["+value+"] as an inline plugin dependencies due to I/O error: " + e.getMessage()); - } - } - } - } - } - return inlinePlugins; - } - - @SuppressWarnings("rawtypes") - private Map lookupPluginLocationConfig(Map config) { - return getIfMap(getIfMap(getIfMap(config, "grails"), "plugin"), "location"); - } - - @SuppressWarnings("rawtypes") - private Map getIfMap(Map config, String name) { - if (config != null) { - Object o = config.get(name); - if (o instanceof Map) { - return ((Map) o); - } - } - return Collections.emptyMap(); - } - - /** - * Returns a list of all plugin directories in both the given path - * and the global "plugins" directory together. - * - * @return A list of plugin directories as File objects - */ - public Collection getImplicitPluginDirectories() { - ConcurrentLinkedQueue dirList = new ConcurrentLinkedQueue(); - - for (String pluginBase : getPluginBaseDirectories()) { - File[] pluginDirs = new File(pluginBase).listFiles(new FileFilter() { - public boolean accept(File pathname) { - final String fileName = pathname.getName(); - return pathname.isDirectory() && (!fileName.startsWith(".") && fileName.indexOf('-') >- 1); - } - }); - if (pluginDirs != null) { - dirList.addAll(Arrays.asList(pluginDirs)); - } - } - - return dirList; - } - - /** - * Gets a list of all the known plugin base directories (directories where plugins are installed to). - * @return Returns the base location where plugins are kept - */ - @SuppressWarnings("unchecked") - public Collection getPluginBaseDirectories() { - List dirs = (List) cache.get(KEY_PLUGIN_BASE_DIRECTORIES); - if (dirs == null) { - dirs = new ArrayList(); - if (projectPluginsDir != null) try { - dirs.add(projectPluginsDir.getCanonicalPath()); - } - catch (IOException e) { - System.err.println("Cannot read project plugins directory ["+projectPluginsDir+"] due to I/O error: " + e.getMessage()); - } - - if (globalPluginsDir != null) try { - dirs.add(globalPluginsDir.getCanonicalPath()); - } - catch (IOException e) { - System.err.println("Cannot read global plugins directory ["+globalPluginsDir+"] due to I/O error: " + e.getMessage()); - } - cache.put(KEY_PLUGIN_BASE_DIRECTORIES, dirs); - } - return dirs; - } - - /** - * Returns true if the specified plugin location is an inline location. - */ - @SuppressWarnings("unchecked") - public boolean isInlinePluginLocation(File pluginLocation) { - if (pluginLocation == null) return false; - getPluginDirectories(); // initialize the cache - ConcurrentLinkedQueue locations = (ConcurrentLinkedQueue) cache.get(KEY_INLINE_PLUGIN_LOCATIONS); - try { - return locations != null && (locations.contains(pluginLocation) || locations.contains(pluginLocation.getCanonicalFile())); - } - catch (IOException e) { - return false; - } - } - - /** - * Returns an array of the inplace plugin locations. - */ - @SuppressWarnings("unchecked") - public Collection getInlinePluginDirectories() { - getPluginDirectories(); // initailize the cache - Collection locations = (ConcurrentLinkedQueue) cache.get(KEY_INLINE_PLUGIN_LOCATIONS); - if (locations == null) { - locations = new ConcurrentLinkedQueue(); - cache.put(KEY_INLINE_PLUGIN_LOCATIONS, locations); - } - return locations; - } -} diff --git a/grails-bootstrap/src/main/groovy/grails/util/BuildScope.java b/grails-bootstrap/src/main/groovy/grails/util/BuildScope.java index 5ab7957b441..2b86da7bdd3 100644 --- a/grails-bootstrap/src/main/groovy/grails/util/BuildScope.java +++ b/grails-bootstrap/src/main/groovy/grails/util/BuildScope.java @@ -46,7 +46,7 @@ public String toString() { public static BuildScope getCurrent() { String key = System.getProperty(KEY); if (key == null) { - key = (String) Metadata.getCurrent().get(KEY); + key = Metadata.getCurrent().getProperty(KEY, String.class); } if (key != null) { diff --git a/grails-bootstrap/src/main/groovy/grails/util/BuildSettings.groovy b/grails-bootstrap/src/main/groovy/grails/util/BuildSettings.groovy index 6e39ff87ce3..e57b578c297 100644 --- a/grails-bootstrap/src/main/groovy/grails/util/BuildSettings.groovy +++ b/grails-bootstrap/src/main/groovy/grails/util/BuildSettings.groovy @@ -15,37 +15,14 @@ */ package grails.util -import grails.build.logging.GrailsConsole -import org.codehaus.groovy.grails.cli.fork.ForkedGrailsProcess - -import static grails.build.logging.GrailsConsole.instance as CONSOLE -import groovy.transform.CompileStatic - -import java.util.concurrent.ConcurrentHashMap import java.util.regex.Pattern -import org.codehaus.groovy.grails.cli.support.ClasspathConfigurer -import org.codehaus.groovy.grails.cli.support.OwnerlessClosure -import org.grails.io.support.SpringIOUtils -import org.grails.dependency.resolution.DependencyManager -import org.grails.dependency.resolution.DependencyManagerConfigurer -import org.grails.dependency.resolution.DependencyReport -import org.grails.dependency.resolution.ivy.EnhancedDefaultDependencyDescriptor -import org.grails.dependency.resolution.GrailsCoreDependencies -import org.grails.dependency.resolution.ivy.IvyDependencyManager - /** - *

Represents the project paths and other build settings - * that the user can change when running the Grails commands. Defaults - * are provided for all settings, but the user can override those by - * setting the appropriate system property or specifying a value for - * it in the BuildConfig.groovy file.

- *

Warning The behaviour is poorly defined if you explicitly - * set some of the project paths (such as {@link BuildSettings#projectWorkDir}), - * but not others. If you set one of them explicitly, set all of them - * to ensure consistent behaviour.

+ * Build time settings and configuration + * + * @author Graeme Rocher */ -class BuildSettings extends AbstractBuildSettings { +class BuildSettings { static final String BUILD_SCOPE = "build" static final String COMPILE_SCOPE = "compile" @@ -60,11 +37,11 @@ class BuildSettings extends AbstractBuildSettings { static final String PROVIDED_SCOPE_DESC = "Dependencies needed at development time, but not during deployment" static final Map SCOPE_TO_DESC = [ - (BUILD_SCOPE): BUILD_SCOPE_DESC, - (PROVIDED_SCOPE): PROVIDED_SCOPE_DESC, - (COMPILE_SCOPE): COMPILE_SCOPE_DESC, - (RUNTIME_SCOPE): RUNTIME_SCOPE_DESC, - (TEST_SCOPE): TEST_SCOPE_DESC + (BUILD_SCOPE): BUILD_SCOPE_DESC, + (PROVIDED_SCOPE): PROVIDED_SCOPE_DESC, + (COMPILE_SCOPE): COMPILE_SCOPE_DESC, + (RUNTIME_SCOPE): RUNTIME_SCOPE_DESC, + (TEST_SCOPE): TEST_SCOPE_DESC ] static final Pattern JAR_PATTERN = ~/^\S+\.jar$/ @@ -232,1451 +209,4 @@ class BuildSettings extends AbstractBuildSettings { */ public static final String LOG_SCRIPT_TIMING_KEY = 'grails.script.logTiming' - /** - * The base directory for the build, which is normally the root - * directory of the current project. If a command is run outside - * of a project, then this will be the current working directory - * that the command was launched from. - */ - File baseDir - - /** Location of the current user's home directory - equivalent to "user.home" system property. */ - File userHome - - /** - * Location of the Grails distribution as usually identified by - * the GRAILS_HOME environment variable. This value may be - * null if GRAILS_HOME is not set, for example if a - * project uses the Grails JAR files directly. - */ - File grailsHome - - /** The version of Grails being used for the current script. */ - String grailsVersion - - /** The environment for the current script. */ - String grailsEnv - - /** - * The compiler source level to use - */ - String compilerSourceLevel - - /** - * The compiler target level to use - */ - String compilerTargetLevel = "1.6" - - /** - * The dependency resolution engine to use (aether or ivy) - */ - String dependencyResolver = "ivy" - - /** true if the default environment for a script should be used. */ - boolean defaultEnv - - /** - * whether to include source attachments in a resolve - */ - boolean includeSource - /** - * whether to include javadoc attachments in a resolve - */ - boolean includeJavadoc - - /** - * Whether the project required build dependencies are externally configured (by Maven for example) or not - */ - boolean dependenciesExternallyConfigured = false - - /** - * Whether to enable resolving dependencies - */ - boolean enableResolve = true - - /** The location of the Grails working directory where non-project-specific temporary files are stored. */ - File grailsWorkDir - - /** The location of the project working directory for project-specific temporary files. */ - File projectWorkDir - - /** The location of the project target directory where reports, artifacts and so on are output. */ - File projectTargetDir - - /** The location of the Grails WAR directory where exploded WAR is built. */ - File projectWarExplodedDir - - /** The location of the temporary directory where plugins are staged before being bundled into a ZIP or JAR file. */ - File pluginStagingDir - - /** Whether to include the source in binary plugin JAR files. */ - Boolean pluginIncludeSource - - /** - * The WAR file of the project - */ - File projectWarFile - - /** - * Directory where additional war files to be autodeployed are located - */ - File autodeployDir - - /** - * Setting for whether or not to enable OSGI headers in the WAR Manifest, can be overridden via -verboseCompile(=[true|false])? - */ - boolean projectWarOsgiHeaders = false - - /** The location to which Grails compiles a project's classes. */ - File classesDir - - /** The location to which Grails compiles a project's test classes and any test scoped plugin classes. */ - File testClassesDir - - /** The location to which Grails compiles a project's plugin classes. Plugin classes that are compile or runtime scoped will be compiled to this directory */ - File pluginClassesDir - - /** - * The location to which Grails compiles build scoped plugins classes. - */ - File pluginBuildClassesDir - - /** - * The location to which Grails compiles provided scoped plugins classes. - */ - File pluginProvidedClassesDir - - /** The location where Grails keeps temporary copies of a project's resources. */ - File resourcesDir - - /** The location of the plain source. */ - File sourceDir - - /** The location of the test reports. */ - File testReportsDir - - /** The location of the documentation output. */ - File docsOutputDir - - /** The location of the test source. */ - File testSourceDir - - /** - * The version of the servlet API used - */ - String servletVersion = "2.5" - - /** The root loader for the build. This has the required libraries on the classpath. */ - URLClassLoader rootLoader - - /** - * The settings used to establish the HTTP proxy to use for dependency resolution etc. - */ - ConfigObject proxySettings = new ConfigObject() - - /** - * The file containing the proxy settings - */ - File proxySettingsFile - - /** - * Fork Settings. These are the default settings used to control forked mode, and what - */ - Map forkSettings = [run:false, test:false, console:false, shell:false, compile:false] - - /** Implementation of the "grailsScript()" method used in Grails scripts. */ - private boolean useMavenDependencyResolver - - Closure getGrailsScriptClosure() { - return new OwnerlessClosure() { - Object doCall(String name) { - if(grailsHome != null) { - - def potentialScript = new File(grailsHome, "grails-scripts/src/main/scripts/${name}.groovy") - potentialScript = potentialScript.exists() ? potentialScript : new File(grailsHome, "grails-scripts/src/main/scripts/${name}_.groovy") - - if (potentialScript.exists()) { - return potentialScript - } - } - try { - return classLoader.loadClass("${name}_") - } - catch (e) { - return classLoader.loadClass(name) - } - } - } - } - - /** - * A Set of plugin names that represent the default set of plugins installed when creating Grails applications - */ - Set defaultPluginSet - - /** - * A Set of plugin names and versions that represent the default set of plugins installed when creating Grails applications - */ - Map defaultPluginMap - - /** - * Location of the generated web.xml file - */ - File webXmlLocation - - /** - * List of jars provided in the applications 'lib' directory - */ - List applicationJars = [] - - List buildListeners = [] - - List pluginDependencies = [] - - boolean convertClosuresArtefacts = false - - /** - * Setting for whether or not to enable verbose compilation, can be overridden via -verboseCompile(=[true|false])? - */ - boolean verboseCompile = false - - /** - * Return whether the BuildConfig has been modified - */ - boolean modified = false - - /** - * Whether the build is allowed to connect to remote servers to resolve dependencies - */ - boolean offline = false - - boolean logScriptTiming = false - - GrailsCoreDependencies coreDependencies - - private List compileDependencies = [] - private boolean defaultCompileDepsAdded = false - - private List internalPluginCompileDependencies = [] - private List internalPluginTestDependencies = [] - private List internalPluginBuildDependencies = [] - private List internalPluginRuntimeDependencies = [] - private List internalPluginProvidedDependencies = [] - - /** List containing the compile-time dependencies of the app as File instances. */ - @CompileStatic - List getCompileDependencies() { - if (!defaultCompileDepsAdded) { - compileDependencies += defaultCompileDependencies - defaultCompileDepsAdded = true - } - return compileDependencies - } - - /** - * Sets the compile time dependencies for the project - */ - @CompileStatic - void setCompileDependencies(List deps) { - def jarFiles = findAndRemovePluginDependencies("compile", deps, internalPluginCompileDependencies) - compileDependencies = jarFiles - } - - DependencyReport buildResolveReport - DependencyReport compileResolveReport - DependencyReport testResolveReport - DependencyReport runtimeResolveReport - DependencyReport providedResolveReport - - /** List containing the default (resolved via the dependencyManager) compile-time dependencies of the app as File instances. */ - private List internalCompileDependencies - @Lazy List defaultCompileDependencies = { - if (dependenciesExternallyConfigured) { - return [] - } - - if (internalCompileDependencies) return internalCompileDependencies - List jarFiles - if (shouldResolve()) { - jarFiles = doResolve("compile", internalPluginCompileDependencies) - } - else { - jarFiles = [] - } - return jarFiles - }() - - @CompileStatic - List doResolve(String scope, List pluginZips, boolean includeAppJars = true) { - final resolveReport = dependencyManager.resolve(scope) - if (resolveReport.hasError()) { - final console = GrailsConsole.getInstance() - final error = resolveReport.getResolveError() - console.error("Resolve error obtaining dependencies: ${error.message}", error) - } - ((GroovyObject)this).setProperty("${scope}ResolveReport".toString(), resolveReport ) - List jarFiles - if (includeAppJars) { - jarFiles = [] - jarFiles.addAll(resolveReport.jarFiles) - jarFiles.addAll(applicationJars) - } else { - jarFiles = resolveReport.jarFiles - } - pluginZips.addAll(resolveReport.pluginZips) - this.pluginDependencies.addAll(resolveReport.pluginZips) - pluginDependencies.unique(true) - resolveCache[scope] = resolveReport.allArtifacts - jarFiles - } - - @CompileStatic - boolean isGrailsProject() { - return new File(getBaseDir(), "grails-app").exists() - } - - @CompileStatic - private List findAndRemovePluginDependencies(String scope, Collection jarFiles, List scopePluginDependencies) { - jarFiles = jarFiles?.findAll { File it -> it != null} ?: new ArrayList() - def pluginZips = jarFiles.findAll { File it -> it.name.endsWith(".zip") } - for (z in pluginZips) { - if (!pluginDependencies.contains(z)) { - pluginDependencies.add(z) - } - } - scopePluginDependencies.addAll(pluginZips) - resolveCache[scope] = jarFiles - jarFiles = jarFiles.findAll { File it -> !it.name.endsWith(".zip") } - return jarFiles as List - } - - private List testDependencies = [] - private boolean defaultTestDepsAdded = false - - /** List containing the test-time dependencies of the app as File instances. */ - @CompileStatic - List getTestDependencies() { - if (!defaultTestDepsAdded) { - testDependencies += defaultTestDependencies - defaultTestDepsAdded = true - } - return testDependencies - } - - /** - * Sets the test time dependencies for the project - */ - @CompileStatic - void setTestDependencies(List deps) { - def jarFiles = findAndRemovePluginDependencies("test", deps, internalPluginTestDependencies) - - testDependencies = jarFiles - } - - /** List containing the default test-time dependencies of the app as File instances. */ - private List internalTestDependencies - @Lazy List defaultTestDependencies = { - if (dependenciesExternallyConfigured) { - return [] - } - - if (internalTestDependencies) return internalTestDependencies - if (shouldResolve()) { - return doResolve("test", internalPluginTestDependencies) - } - else { - return [] - } - }() - - private List runtimeDependencies = [] - private boolean defaultRuntimeDepsAdded = false - - /** List containing the runtime dependencies of the app as File instances. */ - @CompileStatic - List getRuntimeDependencies() { - if (!defaultRuntimeDepsAdded) { - runtimeDependencies += defaultRuntimeDependencies - defaultRuntimeDepsAdded = true - } - return runtimeDependencies - } - - /** - * Sets the runtime dependencies for the project - */ - @CompileStatic - void setRuntimeDependencies(List deps) { - def jarFiles = findAndRemovePluginDependencies("runtime", deps, internalPluginRuntimeDependencies) - runtimeDependencies = jarFiles - } - - /** List containing the default runtime-time dependencies of the app as File instances. */ - private List internalRuntimeDependencies - @Lazy List defaultRuntimeDependencies = { - if (dependenciesExternallyConfigured) { - return [] - } - - if (internalRuntimeDependencies) return internalRuntimeDependencies - if (shouldResolve()) { - return doResolve("runtime", internalPluginRuntimeDependencies) - } - return [] - }() - - private List providedDependencies = [] - private boolean defaultProvidedDepsAdded = false - - /** List containing the runtime dependencies of the app as File instances. */ - @CompileStatic - List getProvidedDependencies() { - if (!defaultProvidedDepsAdded) { - providedDependencies += defaultProvidedDependencies - defaultProvidedDepsAdded = true - } - return providedDependencies - } - - /** - * Sets the runtime dependencies for the project - */ - @CompileStatic - void setProvidedDependencies(List deps) { - def jarFiles = findAndRemovePluginDependencies("provided", deps, internalPluginProvidedDependencies) - providedDependencies = jarFiles - } - - /** List containing the dependencies needed at development time, but provided by the container at runtime **/ - private List internalProvidedDependencies - @Lazy List defaultProvidedDependencies = { - if (dependenciesExternallyConfigured) { - return [] - } - if (internalProvidedDependencies) return internalProvidedDependencies - - if (shouldResolve()) { - return doResolve("provided", internalPluginProvidedDependencies, false) - } - return [] - }() - - private List buildDependencies = [] - private boolean defaultBuildDepsAdded = false - - /** List containing the runtime dependencies of the app as File instances. */ - @CompileStatic - List getBuildDependencies() { - if (!defaultBuildDepsAdded) { - buildDependencies += defaultBuildDependencies - defaultBuildDepsAdded = true - } - return buildDependencies - } - - /** - * Obtains a list of source plugins that are provided time dependencies - * - * @return A list of the source zips - */ - @CompileStatic - List getPluginCompileDependencies() { - // ensure initialization - if (!internalPluginCompileDependencies) { - getCompileDependencies() - } - - return internalPluginCompileDependencies - } - - /** - * Obtains a list of source plugins that are provided time dependencies - * - * @return A list of the source zips - */ - @CompileStatic - List getPluginProvidedDependencies() { - // ensure initialization - if (!internalPluginProvidedDependencies) { - getProvidedDependencies() - } - - return internalPluginProvidedDependencies - } - - /** - * Obtains a list of source plugins that are runtime time dependencies - * - * @return A list of the source zips - */ - @CompileStatic - List getPluginRuntimeDependencies() { - // ensure initialization - if (!internalPluginRuntimeDependencies) { - getRuntimeDependencies() - } - - return internalPluginRuntimeDependencies - } - - /** - * Obtains a list of source plugins that are test time dependencies - * - * @return A list of the source zips - */ - @CompileStatic - List getPluginTestDependencies() { - // ensure initialization - if (!internalPluginTestDependencies) { - getTestDependencies() - } - - return internalPluginTestDependencies - } - - /** - * Obtains a list of source plugins that are build time dependencies - * - * @return A list of the source zips - */ - @CompileStatic - List getPluginBuildDependencies() { - // ensure initialization - if (!internalPluginBuildDependencies) { - getBuildDependencies() - } - - return internalPluginBuildDependencies - } - - /** - * Sets the runtime dependencies for the project - */ - @CompileStatic - void setBuildDependencies(List deps) { - def jarFiles = findAndRemovePluginDependencies("build", deps, internalPluginBuildDependencies) - buildDependencies = jarFiles - } - - /** - * List containing the dependencies required for the build system only - */ - private List internalBuildDependencies - @Lazy List defaultBuildDependencies = { - if (dependenciesExternallyConfigured) { - return [] - } - if (internalBuildDependencies) return internalBuildDependencies - - if (shouldResolve()) { - return doResolve("build", internalPluginBuildDependencies) - } - return [] - }() - - protected boolean shouldResolve() { - return dependencyManager != null && enableResolve - } - - /** - * Manages dependencies and dependency resolution in a Grails application - */ - DependencyManager dependencyManager - - /* - * This is an unclever solution for handling "sticky" values in the - * project paths, but trying to be clever so far has failed. So, if - * the values of properties such as "grailsWorkDir" are set explicitly - * (from outside the class), then they are not overridden by system - * properties/build config. - * - * TODO Sort out this mess. Must decide on what can set this properties, - * when, and how. Also when and how values can be overridden. This - * is critically important for the Maven and Ant support. - */ - private boolean grailsWorkDirSet - private boolean projectWorkDirSet - private boolean projectTargetDirSet - private boolean projectWarExplodedDirSet - private boolean pluginStagingDirSet - private boolean pluginIncludeSourceSet - private boolean classesDirSet - private boolean testClassesDirSet - private boolean pluginClassesDirSet - private boolean pluginBuildClassesDirSet - private boolean pluginProvidedClassesDirSet - private boolean resourcesDirSet - private boolean sourceDirSet - private boolean webXmlFileSet - private boolean testReportsDirSet - private boolean docsOutputDirSet - private boolean testSourceDirSet - private boolean projectWarFileSet - private boolean autodeployDirSet - private boolean projectWarOsgiHeadersSet - private boolean buildListenersSet - private boolean verboseCompileSet - private boolean convertClosuresArtefactsSet - private boolean logScriptTimingSet - private String resolveChecksum - private Map resolveCache = new ConcurrentHashMap() - private boolean readFromCache = false - - BuildSettings() { - this(null) - } - - BuildSettings(File grailsHome) { - this(grailsHome, null) - } - - BuildSettings(File grailsHome, File baseDir) { - userHome = new File(System.getProperty("user.home")) - - if (grailsHome) this.grailsHome = grailsHome - - // Load the 'build.properties' file from the classpath and - // retrieve the Grails version from it. - Properties buildProps = new Properties() - try { - loadBuildPropertiesFromClasspath(buildProps) - grailsVersion = buildProps.'grails.version' - } - catch (IOException ex) { - throw new IOException("Unable to find 'build.properties' - make " + - "that sure the 'grails-core-*.jar' file is on the classpath.") - } - - // If 'grailsHome' is set, add the JAR file dependencies. - defaultPluginMap = [:] - defaultPluginSet = defaultPluginMap.keySet() - - // Update the base directory. This triggers some extra config. - setBaseDir(baseDir) - - if (![Environment.DEVELOPMENT, Environment.TEST].contains(Environment.current)) { - modified = true - } - - // The "grailsScript" closure definition. Returns the location - // of the corresponding script file if GRAILS_HOME is set, - // otherwise it loads the script class using the Gant classloader. - } - - boolean isDependenciesExternallyConfigured() { - return dependenciesExternallyConfigured - } - - void setDependenciesExternallyConfigured(boolean dependenciesExternallyConfigured) { - if(dependenciesExternallyConfigured) { - setForkSettings([run:false, test:false, console:false, shell:false, compile:false]) - } - this.dependenciesExternallyConfigured = dependenciesExternallyConfigured - } - - @CompileStatic - void storeDependencyCache() { - projectWorkDir.mkdirs() - if (resolveChecksum) { - try { - if (resolveCache.size() == 5 && !readFromCache) { - def cachedResolve = new File(projectWorkDir, "${resolveChecksum}.resolve") - cachedResolve.withOutputStream { OutputStream output -> - new ObjectOutputStream(output).writeObject(resolveCache) - } - } - } - catch (e) { - ClasspathConfigurer.cleanResolveCache(this) - } - } - } - - @CompileStatic - protected void loadBuildPropertiesFromClasspath(Properties buildProps) { - InputStream stream = getClass().classLoader.getResourceAsStream("grails.build.properties") - if (stream == null) { - stream = getClass().classLoader.getResourceAsStream("build.properties") - } - if (stream) { - buildProps.load(stream) - } - } - - /** - *

Changes the base directory, making sure that everything that - * depends on it gets refreshed too. If you have have previously - * loaded a configuration file, you should load it again after - * calling this method.

- *

Warning This method resets the project paths, so if - * they have been set manually by the caller, then that information - * will be lost!

- */ - @CompileStatic - void setBaseDir(File newBaseDir) { - baseDir = newBaseDir ?: establishBaseDir() - // Initialize Metadata - Metadata.getInstance(new File(baseDir, "application.properties")) - - // Set up the project paths, using an empty config for now. The - // paths will be updated if and when a BuildConfig configuration - // file is loaded. - config = new ConfigObject() - establishProjectStructure() - - if (baseDir) { - // Add the application's libraries. - def appLibDir = new File(baseDir, "lib") - if (appLibDir.exists()) { - appLibDir.eachFileMatch(JAR_PATTERN) { File it -> - applicationJars << it - } - } - } - } - - void setGrailsWorkDir(File dir) { - grailsWorkDir = dir - grailsWorkDirSet = true - } - - void setProjectWorkDir(File dir) { - projectWorkDir = dir - projectWorkDirSet = true - } - - void setProjectTargetDir(File dir) { - projectTargetDir = dir - projectTargetDirSet = true - } - - void setProjectWarFile(File file) { - projectWarFile = file - projectWarFileSet = true - } - - void setProjectWarExplodedDir(File dir) { - projectWarExplodedDir = dir - projectWarExplodedDirSet = true - } - - void setPluginStagingDir(File dir) { - pluginStagingDir = dir - pluginStagingDirSet = true - } - - void setPluginIncludeSource(boolean include) { - pluginIncludeSource = include - pluginIncludeSourceSet = true - } - - void setConvertClosuresArtefacts(boolean convert) { - convertClosuresArtefacts = convert - convertClosuresArtefactsSet = true - } - - void setLogScriptTiming(boolean b) { - logScriptTiming = b - logScriptTimingSet = true - } - - void setProjectWarOsgiHeaders(boolean flag) { - projectWarOsgiHeaders = flag - projectWarOsgiHeadersSet = true - } - - void setClassesDir(File dir) { - classesDir = dir - classesDirSet = true - } - - void setTestClassesDir(File dir) { - testClassesDir = dir - testClassesDirSet = true - } - - void setPluginClassesDir(File dir) { - pluginClassesDir = dir - pluginClassesDirSet = true - } - - void setPluginBuildClassesDir(File dir) { - pluginBuildClassesDir = dir - pluginBuildClassesDirSet = true - } - - void setPluginProvidedClassesDir(File dir) { - pluginProvidedClassesDir = dir - pluginProvidedClassesDirSet = true - } - - void setResourcesDir(File dir) { - resourcesDir = dir - resourcesDirSet = true - } - - void setSourceDir(File dir) { - sourceDir = dir - sourceDirSet = true - } - - void setTestReportsDir(File dir) { - testReportsDir = dir - testReportsDirSet = true - } - - void setTestSourceDir(File dir) { - testSourceDir = dir - testSourceDirSet = true - } - - void setBuildListeners(buildListeners) { - this.buildListeners = buildListeners.toList() - buildListenersSet = true - } - - Object[] getBuildListeners() { buildListeners.toArray() } - - void setVerboseCompile(boolean flag) { - verboseCompile = flag - verboseCompileSet = true - } - - /** - * Loads the application's BuildSettings.groovy file if it exists - * and returns the corresponding config object. If the file does - * not exist, this returns an empty config. - */ - ConfigObject loadConfig(String environment = null) { - loadConfig(new File(baseDir, "grails-app/conf/BuildConfig.groovy")) - } - - /** - * Loads the given configuration file if it exists and returns the - * corresponding config object. If the file does not exist, this - * returns an empty config. - */ - @CompileStatic - ConfigObject loadConfig(File configFile, String environment = null) { - loadSettingsFile() - if (configFile.exists()) { - // To avoid class loader issues, we make sure that the Groovy class loader used to parse the config file has - // the root loader as its parent. Otherwise we get something like NoClassDefFoundError for Script. - GroovyClassLoader gcl = obtainGroovyClassLoader() - - URL configUrl = configFile.toURI().toURL() - Script script = (Script)gcl.parseClass(configFile)?.newInstance() - - config.setConfigFile(configUrl) - return loadConfig(script) - } else { - postLoadConfig() - } - } - - /** - * Loads the given script and returns corresponding config object. If the file does not exist, this - * returns an empty config. - */ - @CompileStatic - public ConfigObject loadConfig(Script script, String environment = null) { - ConfigSlurper slurper = createConfigSlurper() - slurper.setEnvironment(environment) - return loadConfig(slurper.parse(script)) - } - - @CompileStatic - static void initialiseDefaultLog4j(ClassLoader classLoader) { - def defaultLog4j = new Properties() - defaultLog4j."log4j.rootLogger"="error, stdout" - defaultLog4j."log4j.appender.stdout"="org.apache.log4j.ConsoleAppender" - defaultLog4j."log4j.appender.stdout.layout"="org.apache.log4j.PatternLayout" - - configureDefaultLog4j(classLoader, defaultLog4j) - } - - private static void configureDefaultLog4j(ClassLoader classLoader, Properties defaultLog4j) { - try { - classLoader.loadClass("org.apache.log4j.PropertyConfigurator").configure(defaultLog4j) - } catch (e) { - // ignore - } - } - - @CompileStatic - ConfigObject loadConfig(ConfigObject config) { - try { - this.config.merge(config) - return config - } - finally { - postLoadConfig() - } - } - - protected void postLoadConfig() { - establishProjectStructure() - useMavenDependencyResolver = dependencyResolver?.equalsIgnoreCase("aether") || dependencyResolver?.equalsIgnoreCase("maven") - - parseGrailsBuildListeners() - if (config.grails.default.plugin.set instanceof List) { - defaultPluginSet = config.grails.default.plugin.set - } - flatConfig = config.flatten() - - def configURL = config.getConfigFile() - def configFile = configURL ? new File(configURL.getFile()) : null - - def metadataFile = Metadata.current.getMetadataFile() - - if (!modified && !useMavenDependencyResolver) { - - if (configFile?.exists() && metadataFile?.exists()) { - resolveChecksum = SpringIOUtils.computeChecksum(configFile, "md5") + - SpringIOUtils.computeChecksum(metadataFile, "md5") - } - - def cachedResolve = new File(projectWorkDir, "${resolveChecksum}.resolve") - if (cachedResolve.exists()) { - - cachedResolve.withInputStream { input -> - Map dependencyMap = [:] - try { - def ois = new ObjectInputStream(input) - dependencyMap = ois.readObject() - } catch (e) { - modified = true - return - } - - if (dependencyMap?.isEmpty()) { - modified = true - } - else { - def compileDeps = dependencyMap.compile - def runtimeDeps = dependencyMap.runtime - def testDeps = dependencyMap.test - def buildDeps = dependencyMap.build - def providedDeps = dependencyMap.provided - - if (compileDeps) { - compileDeps = findAndRemovePluginDependencies("compile", compileDeps, internalPluginCompileDependencies) - if (compileDeps.any({ File f -> !f.exists() })) modified = true - internalCompileDependencies = compileDeps + applicationJars - } else { - modified = true - } - - if (runtimeDeps) { - runtimeDeps = findAndRemovePluginDependencies("runtime", runtimeDeps, internalPluginRuntimeDependencies) - if (runtimeDeps.any({ File f -> !f.exists() })) modified = true - internalRuntimeDependencies = runtimeDeps - } else { - modified = true - } - - if (testDeps) { - testDeps = findAndRemovePluginDependencies("test", testDeps, internalPluginTestDependencies) - if (testDeps.any({ File f -> !f.exists() })) modified = true - internalTestDependencies = testDeps - } else { - modified = true - } - - if (buildDeps) { - buildDeps = findAndRemovePluginDependencies("build", buildDeps, internalPluginBuildDependencies) - if (buildDeps.any({ File f -> !f.exists() })) modified = true - internalBuildDependencies = buildDeps - } else { - modified = true - } - - if (providedDeps) { - providedDeps = findAndRemovePluginDependencies("provided", providedDeps, internalPluginProvidedDependencies) - if (providedDeps.any({ File f -> !f.exists() })) modified = true - internalProvidedDependencies = providedDeps - } else { - modified = true - } - - if (!modified) { - readFromCache = true - } - } - } - } - else { - modified = true - } - if (modified) { - ClasspathConfigurer.cleanResolveCache(this) - [internalBuildDependencies, internalCompileDependencies, internalProvidedDependencies, internalRuntimeDependencies, internalTestDependencies].each { it?.clear() } - } - } - - dependencyManager = configureDependencyManager() - def pluginDirs = getPluginDirectories() - for (dir in pluginDirs) { - handleInlinePlugin(dir.name, dir, dependencyManager) - } - } - - @CompileStatic - void handleInlinePlugin(String pluginName, File dir, DependencyManager dependencyManager) { - - if (!isInlinePluginLocation(dir)) { - return - } - - // Try BuildConfig.groovy first, which should work work for in-place plugins. - def path = dir.absolutePath - def pluginDependencyDescriptor = new File(path, "grails-app/conf/BuildConfig.groovy") - - if (!pluginDependencyDescriptor.exists()) { - // OK, that doesn't exist, so try dependencies.groovy. - pluginDependencyDescriptor = new File(path, "dependencies.groovy") - } - - if (pluginDependencyDescriptor.exists()) { - def gcl = obtainGroovyClassLoader() - - try { - Script script = (Script)gcl.parseClass(pluginDependencyDescriptor)?.newInstance() - def pluginSlurper = createConfigSlurper() - def pluginConfig = pluginSlurper.parse(script) - def pluginDependencyConfig = getInlinePluginDependencyConfig(pluginConfig) - if (pluginDependencyConfig instanceof Closure) { - dependencyManager.parseDependencies(pluginDependencyConfig) - } - def inlinePlugins = getInlinePluginsFromConfiguration(pluginConfig, dir) - if (inlinePlugins) { - for (File inlinePlugin in inlinePlugins) { - addPluginDirectory inlinePlugin, true - // recurse - handleInlinePlugin(inlinePlugin.name, inlinePlugin, dependencyManager) - } - } - } - catch (Throwable e) { - CONSOLE.error "WARNING: Inline plugins for [$pluginName] cannot be read due to error: ${e.message}", e - } - } - } - - protected Object getInlinePluginDependencyConfig(ConfigObject pluginConfig) { - pluginConfig.grails.project.dependency.resolution - } - - protected boolean settingsFileLoaded = false - - @CompileStatic - DependencyManager configureDependencyManager() { - DependencyManagerConfigurer configurer = new DependencyManagerConfigurer() - - if (useMavenDependencyResolver && !isDependenciesExternallyConfigured()) { - return configurer.configureAether(this) - } - return configurer.configureIvy(this) - } - - @CompileStatic - DependencyManager createNewDependencyManager() { - - if (useMavenDependencyResolver) { - return DependencyManagerConfigurer.createAetherDependencyManager(this) - } - return DependencyManagerConfigurer.createIvyDependencyManager(this) - } - - @CompileStatic - protected ConfigObject loadSettingsFile() { - if (!settingsFileLoaded) { - def settingsFile = new File("$userHome/.grails/settings.groovy") - def gcl = obtainGroovyClassLoader() - def slurper = createConfigSlurper() - if (settingsFile.exists()) { - Script script = (Script)gcl.parseClass(settingsFile)?.newInstance() - if (script) { - config = slurper.parse(script) - } - } - - proxySettingsFile = new File("$userHome/.grails/ProxySettings.groovy") - if (proxySettingsFile.exists()) { - slurper = createConfigSlurper() - try { - Script script = (Script)gcl.parseClass(proxySettingsFile)?.newInstance() - if (script) { - proxySettings = slurper.parse(script) - def current = proxySettings.currentProxy - if (current) { - proxySettings[current]?.each { Map.Entry entry -> - System.setProperty(entry.key as String, entry.value as String) - } - } - } - } - catch (Throwable e) { - CONSOLE.error "WARNING: Error configuring proxy settings: ${e.message}", e - } - } - - settingsFileLoaded = true - } - config - } - - private GroovyClassLoader gcl - - GroovyClassLoader obtainGroovyClassLoader() { - if (gcl == null) { - gcl = rootLoader != null ? new GroovyClassLoader(rootLoader) : new GroovyClassLoader(ClassLoader.getSystemClassLoader()) - } - return gcl - } - - boolean isRegisteredInMetadata(String pluginName) { - if (dependencyManager instanceof IvyDependencyManager) { - return dependencyManager.metadataRegisteredPluginNames?.contains(pluginName) - } - return true - } - - @Deprecated - boolean notDefinedInBuildConfig(String pluginName) { - if (!(dependencyManager instanceof IvyDependencyManager)) { - return true - } - - def descriptors = dependencyManager.pluginDependencyDescriptors.findAll {EnhancedDefaultDependencyDescriptor desc -> - def nonTransitive = !desc.plugin - def exported = desc.exportedToApplication - nonTransitive || exported - } - - def defined = descriptors*.dependencyId*.name.contains(pluginName) - return !defined - } - - @CompileStatic - ConfigSlurper createConfigSlurper() { - def slurper = new ConfigSlurper() - slurper.setBinding( - basedir: baseDir.path, - baseFile: baseDir, - baseName: baseDir.name, - grailsHome: grailsHome?.path, - grailsVersion: grailsVersion, - userHome: userHome, - grailsSettings: this, - groovyVersion: "${->coreDependencies?.groovyVersion}", - springVersion: "${->coreDependencies?.springVersion}", - appName: Metadata.getCurrent().getApplicationName(), - appVersion: Metadata.getCurrent().getApplicationVersion()) - return slurper - } - - @CompileStatic - private void establishProjectStructure() { - // The third argument to "getPropertyValue()" is either the existing value of the corresponding - // field, or if that's null, a default value. This ensures that we don't override settings - // provided by, for example, the Maven plugin. - def props = config.toProperties() - - final forkConfig = getForkConfig() - if ((forkConfig instanceof Map) && forkConfig && !isDependenciesExternallyConfigured()) { - forkSettings = (Map)forkConfig - } - Metadata metadata = Metadata.getCurrent() - - offline = Boolean.valueOf(getPropertyValue(OFFLINE_MODE, props, String.valueOf(offline))) - - if (!grailsWorkDirSet) { - grailsWorkDir = new File(getPropertyValue(WORK_DIR, props, "${userHome}/.grails/${grailsVersion}")) - } - - servletVersion = getPropertyValue(SERVLET_VERSION, props, "2.5") - metadata.setServletVersion(servletVersion) - compilerSourceLevel = getPropertyValue(COMPILER_SOURCE_LEVEL, props, "1.6") - compilerTargetLevel = getPropertyValue(COMPILER_TARGET_LEVEL, props, "1.6") - dependencyResolver = getPropertyValue(DEPENDENCY_RESOLVER, props, "ivy") - - if (!projectWorkDirSet) { - def workingDirName = metadata.getApplicationName() ?: CORE_WORKING_DIR_NAME - projectWorkDir = new File(getPropertyValue(PROJECT_WORK_DIR, props, "$grailsWorkDir/projects/${workingDirName}")) - } - - if (!projectTargetDirSet) { - projectTargetDir = makeAbsolute(new File(getPropertyValue(PROJECT_TARGET_DIR, props, "$baseDir/target"))) - } - - if (!projectWarFileSet) { - def version = metadata.getApplicationVersion() - def appName = metadata.getApplicationName() ?: baseDir.name - def warName = version ? "$baseDir/target/${appName}-${version}.war" : "$baseDir/target/${appName}.war" - - projectWarFile = makeAbsolute(new File(getPropertyValue(PROJECT_WAR_FILE, props, warName))) - } - - if (!autodeployDirSet) { - autodeployDir = makeAbsolute(new File(getPropertyValue(PROJECT_AUTODEPLOY_DIR, props, "$baseDir/src/autodeploy"))) - } - - if (!projectWarExplodedDirSet) { - projectWarExplodedDir = new File(getPropertyValue(PROJECT_WAR_EXPLODED_DIR, props, "${projectWorkDir}/stage")) - } - - if (!pluginStagingDirSet) { - pluginStagingDir = new File(getPropertyValue(PLUGIN_STAGING_DIR, props, "${projectWorkDir}/plugin_stage")) - } - - if (!pluginIncludeSourceSet) { - pluginIncludeSource = getPropertyValue(PLUGIN_INCLUDE_SOURCE, props, 'true').toBoolean() - } - - if (!convertClosuresArtefactsSet) { - convertClosuresArtefacts = getPropertyValue(CONVERT_CLOSURES_KEY, props, 'false').toBoolean() - } - - if (!logScriptTimingSet) { - logScriptTiming = getPropertyValue(LOG_SCRIPT_TIMING_KEY, props, 'false').toBoolean() - } - - if (!projectWarOsgiHeadersSet) { - projectWarOsgiHeaders = getPropertyValue(PROJECT_WAR_OSGI_HEADERS, props, 'false').toBoolean() - } - - if (!classesDirSet) { - classesDir = makeAbsolute(new File(getPropertyValue(PROJECT_CLASSES_DIR, props, "$projectWorkDir/classes"))) - } - - if (!testClassesDirSet) { - testClassesDir = makeAbsolute(new File(getPropertyValue(PROJECT_TEST_CLASSES_DIR, props, "$projectWorkDir/test-classes"))) - } - - if (!pluginClassesDirSet) { - pluginClassesDir = makeAbsolute(new File(getPropertyValue(PROJECT_PLUGIN_CLASSES_DIR, props, "$projectWorkDir/plugin-classes"))) - } - - if (!pluginBuildClassesDirSet) { - pluginBuildClassesDir = makeAbsolute(new File(getPropertyValue(PROJECT_PLUGIN_BUILD_CLASSES_DIR, props, "$projectWorkDir/plugin-build-classes"))) - } - - if (!pluginProvidedClassesDirSet) { - pluginProvidedClassesDir = makeAbsolute(new File(getPropertyValue(PROJECT_PLUGIN_PROVIDED_CLASSES_DIR, props, "$projectWorkDir/plugin-provided-classes"))) - } - - if (!resourcesDirSet) { - resourcesDir = new File(getPropertyValue(PROJECT_RESOURCES_DIR, props, "$projectWorkDir/resources")) - } - - if (!sourceDirSet) { - sourceDir = new File(getPropertyValue(PROJECT_SOURCE_DIR, props, "$baseDir/src")) - } - - if (!webXmlFileSet) { - webXmlLocation = new File(getPropertyValue(PROJECT_WEB_XML_FILE, props, "$resourcesDir/web.xml")) - } - - if (!projectPluginsDirSet) { - this.@projectPluginsDir = new File(getPropertyValue(PLUGINS_DIR, props, "$projectWorkDir/plugins")) - } - - if (!globalPluginsDirSet) { - this.@globalPluginsDir = new File(getPropertyValue(GLOBAL_PLUGINS_DIR, props, "$grailsWorkDir/global-plugins")) - } - - if (!testReportsDirSet) { - testReportsDir = makeAbsolute(new File(getPropertyValue(PROJECT_TEST_REPORTS_DIR, props, "${projectTargetDir}/test-reports"))) - } - - if (!docsOutputDirSet) { - docsOutputDir = makeAbsolute(new File(getPropertyValue(PROJECT_DOCS_OUTPUT_DIR, props, "${projectTargetDir}/docs"))) - } - - if (!testSourceDirSet) { - testSourceDir = new File(getPropertyValue(PROJECT_TEST_SOURCE_DIR, props, "${baseDir}/test")) - } - - if (!verboseCompileSet) { - verboseCompile = getPropertyValue(VERBOSE_COMPILE, props, '').toBoolean() - } - } - - private getForkConfig() { - def result = config.grails.project.fork - String syspropDebugArgs = System.getProperty("grails.project.fork.run.debugArgs") - boolean debugFork = Boolean.getBoolean(ForkedGrailsProcess.DEBUG_FORK) - if (syspropDebugArgs || debugFork) { - if (!(result.run instanceof Map)) { - result.run = [:] - } - result.run.debug = true - if (syspropDebugArgs != "true") { - result.run.debugArgs = syspropDebugArgs - } - } - syspropDebugArgs = System.getProperty("grails.project.fork.test.debugArgs") - if (syspropDebugArgs || debugFork) { - if (!(result.test instanceof Map)) { - result.test = [:] - } - result.test.debug = true - if (syspropDebugArgs != "true") { - result.test.debugArgs = syspropDebugArgs - } - } - return result - } - - protected File makeAbsolute(File dir) { - if (!dir.absolute) { - dir = new File(baseDir, dir.path) - } - dir - } - - protected void parseGrailsBuildListeners() { - if (buildListenersSet) { - return - } - - def listenersValue = System.getProperty(BUILD_LISTENERS) ?: config.grails.build.listeners // Anyway to use the constant to do this? - if (listenersValue) { - def add = { - if (it instanceof String) { - it.split(',').each { this.@buildListeners << it } - } else if (it instanceof Class) { - this.@buildListeners << it - } else { - throw new IllegalArgumentException("$it is not a valid value for $BUILD_LISTENERS") - } - } - - (listenersValue instanceof Collection) ? listenersValue.each(add) : add(listenersValue) - } - buildListenersSet = true - } - - @CompileStatic - private String getPropertyValue(String propertyName, Properties props, String defaultValue) { - // First check whether we have a system property with the given name. - def value = getValueFromSystemOrBuild(propertyName, props) - - // Return the BuildSettings value if there is one, otherwise - // use the default. - return value != null ? value : defaultValue - } - - @CompileStatic - private getValueFromSystemOrBuild(String propertyName, Properties props) { - def value = System.getProperty(propertyName) - if (value != null) return value - - // Now try the BuildSettings config. - value = props[propertyName] - return value - } - - @CompileStatic - private File establishBaseDir() { - def sysProp = System.getProperty(APP_BASE_DIR) - def baseDir - if (sysProp) { - baseDir = sysProp == '.' ? new File("") : new File(sysProp) - } - else { - baseDir = new File("") - if (!new File(baseDir, "grails-app").exists()) { - // be careful with this next step... - // baseDir.parentFile will return null since baseDir is new File("") - // baseDir.absoluteFile needs to happen before retrieving the parentFile - def parentDir = baseDir.absoluteFile.parentFile - - // keep moving up one directory until we find - // one that contains the grails-app dir or get - // to the top of the filesystem... - while (parentDir != null && !new File(parentDir, "grails-app").exists()) { - parentDir = parentDir.parentFile - } - - if (parentDir != null) { - // if we found the project root, use it - baseDir = parentDir - } - } - } - return baseDir.canonicalFile - } - - File getWebXmlLocation() { webXmlLocation } - - void setWebXmlLocation(File location) { - webXmlLocation = location - webXmlFileSet = true - } - - String getFunctionalTestBaseUrl() { - System.getProperty(FUNCTIONAL_BASE_URL_PROPERTY) - } - - File getBasePluginDescriptor() { - File basePluginFile = baseDir?.listFiles()?.find { it.name.endsWith("GrailsPlugin.groovy")} - - if (basePluginFile?.exists()) { - return basePluginFile - } - return null - } - - boolean isPluginProject() { - getBasePluginDescriptor() != null - } - - /** - * @return The path to the Config.groovy file (not to be confused with BuildConfig.groovy) - */ - @CompileStatic - String getConfigFilePath() { - configFile.absolutePath - } - - @CompileStatic - File getConfigFile() { - new File(baseDir, "grails-app/conf/Config.groovy") - } - - @CompileStatic - void initializeResourcesDir() { - def targetPath = resourcesDir.path - def dir = new File(baseDir, "grails-app/conf") - resourcesDir.mkdirs() - if (dir.exists()) { - try { - copyDirectoryContentsToTarget(dir, targetPath) - } catch (e) { - GrailsConsole.getInstance().error("Error initializing resources from grails-app/conf: ${e.message}", e) - } - } - - } - - @CompileStatic - protected void copyDirectoryContentsToTarget(File dir, String targetPath) { - dir.eachFile { File f -> - final isFile = !f.isDirectory() - final isHidden = f.isHidden() - if (isFile && !isHidden && !f.name.endsWith('.groovy')) { - SpringIOUtils.copy(f, new File(targetPath, f.name)) - } - else if (!isFile && !isHidden) { - final fileName = f.name - if (fileName != 'hibernate' && fileName != 'spring') { - final newDir = new File(targetPath, fileName) - newDir.mkdirs() - copyDirectoryContentsToTarget(f, newDir.path) - } - } - } - } } diff --git a/grails-bootstrap/src/main/groovy/grails/util/BuildSettingsHolder.java b/grails-bootstrap/src/main/groovy/grails/util/BuildSettingsHolder.java deleted file mode 100644 index 550aba998b0..00000000000 --- a/grails-bootstrap/src/main/groovy/grails/util/BuildSettingsHolder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * 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 grails.util; - -import org.grails.build.plugins.GrailsPluginUtils; - -/** - * Static singleton holder for the BuildSettings instance. Should only - * be initialised once (in {@link org.codehaus.groovy.grails.cli.GrailsScriptRunner}. - */ -public final class BuildSettingsHolder { - - private static BuildSettings settings; - - public static BuildSettings getSettings() { - return settings; - } - - public static void setSettings(BuildSettings newSettings) { - settings = newSettings; - try { - // test if classpath has been initialized already - Class.forName("org.springframework.core.io.Resource"); - if (settings != null) { - GrailsPluginUtils.getPluginBuildSettings(settings); - } else { - GrailsPluginUtils.setPluginBuildSettings(null); - } - } catch (ClassNotFoundException e) { - // ignore error that comes in Grails startup before the classpath has been initialized - } - } - - private BuildSettingsHolder() { - // static only - } -} diff --git a/grails-bootstrap/src/main/groovy/grails/util/Environment.java b/grails-bootstrap/src/main/groovy/grails/util/Environment.java index 2dfa84176fc..4a52ac17f3b 100644 --- a/grails-bootstrap/src/main/groovy/grails/util/Environment.java +++ b/grails-bootstrap/src/main/groovy/grails/util/Environment.java @@ -233,7 +233,13 @@ public static Environment getEnvironment(String shortName) { if (envName != null) { return Environment.valueOf(envName.toUpperCase()); } - return null; + else { + try { + return Environment.valueOf(shortName.toUpperCase()); + } catch ( IllegalArgumentException ise ) { + return null; + } + } } /** @@ -478,12 +484,8 @@ public boolean hasReloadLocation() { private String getReloadLocationInternal() { String location = System.getProperty(RELOAD_LOCATION); - if (!hasLocation(location)) location = System.getProperty(BuildSettings.APP_BASE_DIR); - if (!hasLocation(location)) { - BuildSettings settings = BuildSettingsHolder.getSettings(); - if (settings != null) { - location = settings.getBaseDir().getAbsolutePath(); - } + if(!hasLocation(location)) { + location = System.getProperty(BuildSettings.APP_BASE_DIR); } if(!hasLocation(location)) { File current = new File(".", "grails-app"); diff --git a/grails-bootstrap/src/main/groovy/grails/util/GrailsMain.groovy b/grails-bootstrap/src/main/groovy/grails/util/GrailsMain.groovy deleted file mode 100644 index 18ad36fc7fa..00000000000 --- a/grails-bootstrap/src/main/groovy/grails/util/GrailsMain.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2011 SpringSource. - * - * 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 grails.util - -import org.codehaus.groovy.grails.cli.support.GrailsStarter - -// First check for a system property called "grails.home". If that -// exists, we use its value as the location of Grails. Otherwise, we -// use the environment variable GRAILS_HOME. -def grailsHome = System.getProperty("grails.home") -if (!grailsHome) { - grailsHome = System.getenv("GRAILS_HOME") - - if (!grailsHome) { - println "Either the system property \"grails.home\" or the " + - "environment variable GRAILS_HOME must be set to the " + - "location of your Grails installation." - return - } - - System.setProperty("grails.home", grailsHome) -} - -// Load the build properties so that we can read the Grails version. -def props = new Properties() -props.load(getClass().getClassLoader().getResourceAsStream("grails.build.properties")) - -// We need JAVA_HOME so that we can get hold of the "tools.jar" file. -def javaHome = new File(System.getenv("JAVA_HOME")) - -System.setProperty("grails.version", props["grails.version"]) -System.setProperty("tools.jar", new File(javaHome, "lib/tools.jar").absolutePath) -GrailsStarter.main(["--conf", "${grailsHome}/conf/groovy-starter.conf", "--main", "org.codehaus.groovy.grails.cli.GrailsScriptRunner", "run-app"] as String[]) diff --git a/grails-bootstrap/src/main/groovy/grails/util/Metadata.java b/grails-bootstrap/src/main/groovy/grails/util/Metadata.groovy similarity index 66% rename from grails-bootstrap/src/main/groovy/grails/util/Metadata.java rename to grails-bootstrap/src/main/groovy/grails/util/Metadata.groovy index da132ca6e29..5c74dfadfa8 100644 --- a/grails-bootstrap/src/main/groovy/grails/util/Metadata.java +++ b/grails-bootstrap/src/main/groovy/grails/util/Metadata.groovy @@ -15,6 +15,9 @@ */ package grails.util; +import grails.config.GrailsConfig +import groovy.transform.CompileStatic; + import java.io.Closeable; import java.io.File; import java.io.FileInputStream; @@ -23,12 +26,7 @@ import java.io.InputStream; import java.lang.ref.Reference; import java.lang.ref.SoftReference; -import java.util.Collections; -import java.util.Enumeration; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Properties; -import java.util.Vector; +import java.util.*; /** * Represents the application Metadata and loading mechanics. @@ -36,9 +34,10 @@ * @author Graeme Rocher * @since 1.1 */ -public class Metadata extends Properties { +@CompileStatic +public class Metadata extends GrailsConfig { private static final long serialVersionUID = -582452926111226898L; - public static final String FILE = "application.properties"; + public static final String FILE = "application.yml"; public static final String APPLICATION_VERSION = "app.version"; public static final String APPLICATION_NAME = "app.name"; public static final String APPLICATION_GRAILS_VERSION = "app.grails.version"; @@ -51,6 +50,7 @@ public class Metadata extends Properties { private File metadataFile; private boolean warDeployed; private String servletVersion = DEFAULT_SERVLET_VERSION; + private GrailsConfig config; private Metadata() { loadFromDefault(); @@ -65,8 +65,8 @@ private Metadata(InputStream inputStream) { loadFromInputStream(inputStream); } - private Metadata(Map properties) { - putAll(properties); + private Metadata(Map properties) { + getConfigMap().putAll(properties); afterLoading(); } @@ -80,13 +80,13 @@ public File getMetadataFile() { public static void reset() { Metadata m = getFromMap(); if (m != null) { - m.clear(); + m.getConfigMap().clear(); m.afterLoading(); } } private void afterLoading() { - warDeployed = "true".equals(get(WAR_DEPLOYED)); + warDeployed = getProperty(WAR_DEPLOYED, Boolean) } /** @@ -109,7 +109,7 @@ private void loadFromDefault() { input = Metadata.class.getClassLoader().getResourceAsStream(FILE); } if (input != null) { - load(input); + loadYml(input); } afterLoading(); } @@ -122,13 +122,8 @@ private void loadFromDefault() { } private void loadFromInputStream(InputStream inputStream) { - try { - load(inputStream); - afterLoading(); - } - catch (IOException e) { - throw new RuntimeException("Cannot load application metadata:" + e.getMessage(), e); - } + loadYml(inputStream); + afterLoading(); } private void loadFromFile(File file) { @@ -136,7 +131,7 @@ private void loadFromFile(File file) { FileInputStream input = null; try { input = new FileInputStream(file); - load(input); + loadYml(input); afterLoading(); } catch (Exception e) { @@ -199,55 +194,36 @@ public static Metadata reload() { * @return The application version */ public String getApplicationVersion() { - return (String) get(APPLICATION_VERSION); + return getProperty(APPLICATION_VERSION, String.class); } /** * @return The Grails version used to build the application */ public String getGrailsVersion() { - return (String) get(APPLICATION_GRAILS_VERSION); - } - public void setGrailsVersion(String version) { - put(APPLICATION_GRAILS_VERSION, version); + return getProperty(APPLICATION_GRAILS_VERSION, String.class); } /** * @return The environment the application expects to run in */ public String getEnvironment() { - return (String) get(Environment.KEY); + return getProperty(Environment.KEY, String.class); } /** * @return The application name */ public String getApplicationName() { - return (String) get(APPLICATION_NAME); + return getProperty(APPLICATION_NAME, String.class); } - /** - * Obtains a map (name->version) of installed plugins specified in the project metadata - * @return A map of installed plugins - */ - public Map getInstalledPlugins() { - Map newMap = new LinkedHashMap(); - - for (Map.Entry entry : entrySet()) { - String key = entry.getKey().toString(); - Object val = entry.getValue(); - if (key.startsWith("plugins.") && val != null) { - newMap.put(key.substring(8), val.toString()); - } - } - return newMap; - } /** * @return The version of the servlet spec the application was created for */ public String getServletVersion() { - String servletVersion = (String) get(SERVLET_VERSION); + String servletVersion = getProperty(SERVLET_VERSION, String.class); if (servletVersion == null) { servletVersion = System.getProperty(SERVLET_VERSION) != null ? System.getProperty(SERVLET_VERSION) : this.servletVersion; return servletVersion; @@ -260,56 +236,6 @@ public void setServletVersion(String servletVersion) { this.servletVersion = servletVersion; } - /** - * Saves the current state of the Metadata object. - */ - public void persist() { - - if (propertiesHaveNotChanged() || metadataFile == null) { - return; - } - - FileOutputStream out = null; - try { - out = new FileOutputStream(metadataFile); - store(out, "Grails Metadata file"); - } - catch (Exception e) { - throw new RuntimeException("Error persisting metadata to file [" + metadataFile + "]: " + e.getMessage(), e); - } - finally { - closeQuietly(out); - } - } - - /** - * @return Returns true if these properties have not changed since they were loaded - */ - public boolean propertiesHaveNotChanged() { - Metadata allStringValuesMetadata = new Metadata(); - for (Map.Entry entry : entrySet()) { - if (entry.getValue() != null) { - allStringValuesMetadata.put(entry.getKey().toString(), entry.getValue().toString()); - } - } - - return allStringValuesMetadata.equals(new Metadata(metadataFile)); - } - - /** - * Overrides, called by the store method. - */ - @Override - @SuppressWarnings({"unchecked","rawtypes"}) - public synchronized Enumeration keys() { - Enumeration keysEnum = super.keys(); - Vector keyList = new Vector(); - while (keysEnum.hasMoreElements()) { - keyList.add(keysEnum.nextElement()); - } - Collections.sort(keyList); - return keyList.elements(); - } /** * @return true if this application is deployed as a WAR @@ -318,14 +244,6 @@ public boolean isWarDeployed() { return warDeployed; } - @Override - public synchronized Object put(Object key, Object o2) { - try { - return super.put(key, o2); - } finally { - afterLoading(); - } - } private static void closeQuietly(Closeable c) { if (c != null) { @@ -343,6 +261,8 @@ private static Metadata getFromMap() { return metadata == null ? null : metadata.get(); } + + static class FinalReference extends SoftReference { private T ref; public FinalReference(T t) { diff --git a/grails-bootstrap/src/main/groovy/grails/util/PluginBuildSettings.groovy b/grails-bootstrap/src/main/groovy/grails/util/PluginBuildSettings.groovy deleted file mode 100644 index 05b1bdcd127..00000000000 --- a/grails-bootstrap/src/main/groovy/grails/util/PluginBuildSettings.groovy +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Copyright 2004-2005 Graeme Rocher - * - * 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 grails.util - -import groovy.transform.CompileStatic -import groovy.util.slurpersupport.GPathResult - -import java.util.concurrent.ConcurrentHashMap -import java.util.zip.ZipEntry -import java.util.zip.ZipFile - -import org.grails.io.support.AntPathMatcher -import org.grails.io.support.FileSystemResource -import org.grails.io.support.SpringIOUtils -import org.grails.io.support.PathMatchingResourcePatternResolver -import org.grails.io.support.Resource -import org.grails.build.plugins.BasicGrailsPluginInfo -import org.grails.build.plugins.CompositePluginDescriptorReader -import grails.plugins.GrailsPluginInfo -import org.grails.build.plugins.XmlDescriptorPluginInfo -import org.grails.build.plugins.scopes.PluginScopeInfo - -/** - * Uses the project BuildSettings object to discover information about the installed plugin - * such as the jar files they provide, the plugin descriptors and so on. - * - * @author Graeme Rocher - * @since 1.2 - */ -class PluginBuildSettings { - - private static final List PLUGIN_EXCLUDE_PATHS = ["views", "i18n"] // conf gets special handling - - /** - * Resources to be excluded from the final packaged plugin. Defined as Ant paths. - */ - public static final EXCLUDED_RESOURCES = [ - "web-app/WEB-INF/**", - "web-app/plugins/**", - "grails-app/conf/spring/resources.groovy", - "grails-app/conf/*DataSource.groovy", - "grails-app/conf/DataSource.groovy", - "grails-app/conf/BootStrap.groovy", - "grails-app/conf/Config.groovy", - "grails-app/conf/BuildConfig.groovy", - "grails-app/conf/UrlMappings.groovy", - "**/.svn/**", - "test/**", - "**/CVS/**" - ] - - private static final PathMatchingResourcePatternResolver RESOLVER = new PathMatchingResourcePatternResolver() - - /** - * A default resolver used if none is specified to the resource resolving methods in this class. - */ - Closure resourceResolver = { pattern -> - try { - return RESOLVER.getResources(pattern) - } - catch(Throwable e) { - return [] as Resource[] - } - } - - BuildSettings buildSettings - def pluginManager - String pluginDirPath - private Map cache = new ConcurrentHashMap() - private Map pluginToDirNameMap = new ConcurrentHashMap() - private Map pluginMetaDataMap = new ConcurrentHashMap() - private Map pluginInfosMap = new ConcurrentHashMap() - private Map pluginInfoToSourceMap = new ConcurrentHashMap() - - private pluginLocations - - PluginScopeInfo compileScopePluginInfo = new PluginScopeInfo("compile") - PluginScopeInfo buildScopePluginInfo = new PluginScopeInfo("build") - PluginScopeInfo providedScopePluginInfo = new PluginScopeInfo("provided") - PluginScopeInfo testScopePluginInfo = new PluginScopeInfo("test") - - private Map pluginScopeInfoMap = [ - compile: compileScopePluginInfo, - build: buildScopePluginInfo, - provided: providedScopePluginInfo, - test: testScopePluginInfo] - - PluginBuildSettings(BuildSettings buildSettings) { - this(buildSettings, null) - } - - PluginBuildSettings(BuildSettings buildSettings, pluginManager) { - // We use null-safe navigation on buildSettings because otherwise lots of unit tests will fail - this.buildSettings = buildSettings - this.pluginManager = pluginManager - pluginDirPath = buildSettings?.projectPluginsDir?.absolutePath - pluginLocations = buildSettings?.config?.grails?.plugin?.location - - if (buildSettings == null) { - return - } - - populateSourceDirectories(compileScopePluginInfo, buildSettings.pluginRuntimeDependencies) - - for (pluginDir in getInlinePluginDirectories()) { - final pluginInfo = getPluginInfo(pluginDir.file.absolutePath) - if (pluginInfo != null) { - addPluginScopeInfoForDirAndInfo(compileScopePluginInfo, pluginInfo, pluginDir) - } - } - - populateSourceDirectories(buildScopePluginInfo, buildSettings.pluginBuildDependencies) - populateSourceDirectories(providedScopePluginInfo, buildSettings.pluginProvidedDependencies) - populateSourceDirectories(testScopePluginInfo, buildSettings.pluginTestDependencies) - testScopePluginInfo = testScopePluginInfo - compileScopePluginInfo - } - - @CompileStatic - void registerNewPluginInstall(File zip) { - switch(zip) { - case buildSettings.pluginBuildDependencies: - registerPluginZipWithScope(zip, buildScopePluginInfo) - // fall through in case defined in compile scope too - case buildSettings.pluginCompileDependencies: - registerPluginZipWithScope(zip, compileScopePluginInfo) - // we break here because if the plugin is in compile scope then it will be in runtime and test - break - case buildSettings.pluginRuntimeDependencies: - registerPluginZipWithScope(zip, compileScopePluginInfo) - // we break here because if the plugin is in runtime scope then it will be in test scope - break - case buildSettings.pluginTestDependencies: - registerPluginZipWithScope(zip, testScopePluginInfo) - // fall through to check provided - case buildSettings.pluginProvidedDependencies: - registerPluginZipWithScope(zip, providedScopePluginInfo) - } - } - - @CompileStatic - private populateSourceDirectories(PluginScopeInfo compileInfo, List pluginDependencies) { - if(pluginDependencies) { - for (zip in pluginDependencies) { - registerPluginZipWithScope(zip, compileInfo) - } - } - } - - protected void registerPluginZipWithScope(File pluginZip, PluginScopeInfo scopeInfo) { - def info = readPluginInfoFromZip(pluginZip.absolutePath) - if (info == null) { - return - } - - def existingInfo = getPluginInfoForName(info.name) - if (existingInfo != null && existingInfo.version == info.version) { - addPluginScopeInfoForDirAndInfo(scopeInfo, info, existingInfo.pluginDir) - } - } - - @CompileStatic - protected void addPluginScopeInfoForDirAndInfo(PluginScopeInfo compileInfo, GrailsPluginInfo info, Resource dir) { - def excludedPaths = PLUGIN_EXCLUDE_PATHS // conf gets special handling - compileInfo.pluginInfos << info - compileInfo.pluginNames << info.name - compileInfo.sourceDirectories.addAll( - getPluginSourceDirectories(dir.file.canonicalFile).findAll { Resource it -> - !excludedPaths.contains(it.file.name) && it.file.isDirectory() - }) - compileInfo.pluginDescriptors << getPluginDescriptor(dir) - compileInfo.artefactResources.addAll(getArtefactResourcesForOne(dir.file.absolutePath)) - } - - /** - * Clears any cached entries. - */ - void clearCache() { - cache.clear() - buildSettings?.clearCache() - pluginToDirNameMap.clear() - pluginMetaDataMap.clear() - pluginInfosMap.clear() - pluginInfoToSourceMap.clear() - } - - /** - * Returns an array of PluginInfo objects - */ - GrailsPluginInfo[] getPluginInfos() { - getPluginInfos(this.pluginDirPath) - } - GrailsPluginInfo[] getPluginInfos(String pluginDirPath) { - if (pluginInfosMap) { - return cache.pluginInfoList - } - - def pluginInfos = [] - Resource[] pluginDescriptors = getPluginDescriptors() - CompositePluginDescriptorReader pluginDescriptorReader = new CompositePluginDescriptorReader(this) - for (desc in pluginDescriptors) { - try { - GrailsPluginInfo info = pluginDescriptorReader.readPluginInfo(desc) - if (info != null) { - pluginInfos << info - pluginInfosMap.put(info.name, info) - pluginInfosMap.put(info.fullName, info) - } - } - catch (e) { - // ignore, not a valid plugin directory - } - } - cache.pluginInfoList = pluginInfos as GrailsPluginInfo[] - return pluginInfos as GrailsPluginInfo[] - } - - /** - * Returns true if the specified plugin location is an inline location. - */ - boolean isInlinePluginLocation(Resource pluginLocation) { - pluginLocation in getInlinePluginDirectories() || buildSettings?.isInlinePluginLocation(pluginLocation?.getFile()) - } - - /** - * Returns an array of the inplace plugin locations. - */ - //@CompileStatic - Resource[] getInlinePluginDirectories() { - Resource[] locations = (Resource[])cache['inlinePluginLocations'] - if (locations == null) { - - if (buildSettings) { - locations = buildSettings.getInlinePluginDirectories().collect { File it -> new FileSystemResource(it) } - } - else { - locations = [] as Resource[] - } - - cache['inlinePluginLocations'] = locations - } - return locations - } - - /** - * Obtains a PluginInfo for the installed plugin directory. - */ - @CompileStatic - GrailsPluginInfo getPluginInfo(String pluginBaseDir) { - if (!pluginInfosMap) getPluginInfos() // initialize the infos - def dir = new FileSystemResource(pluginBaseDir) - def descLocation = getDescriptorForPlugin(dir) - if (descLocation) { - def pluginName = GrailsNameUtils.getPluginName(descLocation.filename) - return (GrailsPluginInfo)pluginInfosMap[pluginName] - } - return null - } - - /** - * Obtains a PluginInfo for the installed plugin directory. - */ - @CompileStatic - GrailsPluginInfo getPluginInfoForName(String pluginName) { - if (!pluginInfosMap) getPluginInfos() // initialize the infos - return (GrailsPluginInfo)pluginInfosMap[pluginName] - } - - /** - * Gets a PluginInfo for a particular source file if its contained within that plugin - */ - GrailsPluginInfo getPluginInfoForSource(String sourceFile) { - if (pluginInfoToSourceMap[sourceFile]) { - return pluginInfoToSourceMap[sourceFile] - } - - for (Resource pluginDir in getPluginDirectories()) { - def pluginPath = pluginDir.file.canonicalPath + File.separator - def sourcePath = new File(sourceFile).canonicalPath - if (sourcePath.startsWith(pluginPath)) { - // Check the path of the source file relative to the - // plugin directory. If the source file is in the - // plugin's "test" directory, we ignore it. It's a - // bit of a HACK, but not much else we can do without - // a refactor of the plugin management. - sourcePath = sourcePath.substring(pluginPath.length()) - if (!sourcePath.startsWith("test" + File.separator)) { - GrailsPluginInfo info = getPluginInfo(pluginPath) - if (info) { - pluginInfoToSourceMap[sourceFile] = info - } - return info - } - } - } - - def baseDir = buildSettings?.getBaseDir()?.getCanonicalPath() - if (baseDir != null && sourceFile.startsWith(baseDir)) { - GrailsPluginInfo basePluginInfo = getPluginInfo(baseDir) - if (basePluginInfo != null) { - pluginInfoToSourceMap[sourceFile] = basePluginInfo - return basePluginInfo - } - } - - return null - } - - /** - * Obtains a Resource array of the Plugin metadata XML files used to describe the plugins provided resources - */ - Resource[] getPluginXmlMetadata() { - resolveResources 'allPluginXmlMetadata', false, { pluginDir -> - resourceResolver("file:${pluginDir}/plugin.xml") - } - } - - /** - * Returns XML about the plugin. - */ - GPathResult getMetadataForPlugin(String pluginName) { - if (pluginMetaDataMap[pluginName]) return pluginMetaDataMap[pluginName] - - Resource pluginDir = getPluginDirForName(pluginName) - GPathResult result = getMetadataForPlugin(pluginDir) - if (result != null) { - pluginMetaDataMap[pluginName] = result - } - return result - } - - /** - * Returns XML metadata for the plugin. - */ - GPathResult getMetadataForPlugin(Resource pluginDir) { - try { - return SpringIOUtils.createXmlSlurper().parse(new File("$pluginDir.file.absolutePath/plugin.xml")) - } - catch (e) { - return null - } - } - - /** - * Obtains an array of all Gant scripts that are availabe for execution in a Grails application. - */ - Resource[] getAvailableScripts() { - - def availableScripts = cache.availableScripts - if (!availableScripts) { - - def scripts = [] - def userHome = System.getProperty("user.home") - def grailsHome = buildSettings.grailsHome?.absolutePath - def basedir = buildSettings.baseDir.absolutePath - if (grailsHome != null) { - resourceResolver("file:${grailsHome}/scripts/**.groovy").each { if (!it.file.name.startsWith('_')) scripts << it } - resourceResolver("file:${grailsHome}/grails-scripts/src/main/scripts/**.groovy").each { if (!it.file.name.startsWith('_')) scripts << it } - } - resourceResolver("file:${basedir}/scripts/*.groovy").each { if (!it.file.name.startsWith('_')) scripts << it } - pluginScripts.each { if (!it.file.name.startsWith('_')) scripts << it } - resourceResolver("file:${userHome}/.grails/scripts/*.groovy").each { if (!it.file.name.startsWith('_')) scripts << it } - availableScripts = scripts as Resource[] - cache.availableScripts = availableScripts - } - return availableScripts - } - - /** - * Obtains an array of plugin provided Gant scripts available to a Grails application. - */ - Resource[] getPluginScripts() { - resolveResources 'pluginScripts', false, { pluginDir -> - resourceResolver("file:${pluginDir}/scripts/*.groovy") - } - } - - /** - * Obtains an array of all plugin provided resource bundles. - */ - Resource[] getPluginResourceBundles() { - resolveResources 'pluginResourceBundles', false, { pluginDir -> - resourceResolver("file:${pluginDir}/grails-app/i18n/**/*.properties") - } - } - - /** - * Obtains an array of all plugin provided source directories - * - * @deprecated Use getPluginSourceDirectories - */ - Resource[] getPluginSourceFiles() { - return getPluginSourceDirectories() - } - - /** - * Obtains an array of all plugin provided source directories - * - */ - //@CompileStatic - Resource[] getPluginSourceDirectories() { - def sourceFiles = cache.sourceFiles - if (!sourceFiles) { - cache.sourceFilesPerPlugin = [:] - sourceFiles = new Resource[0] - sourceFiles = resolvePluginResourcesAndAdd(sourceFiles, true) { pluginDir -> - Resource[] pluginSourceFiles = resourceResolver("file:${pluginDir}/grails-app/*") - pluginSourceFiles = (Resource[])SpringIOUtils.addAll(pluginSourceFiles, resourceResolver("file:${pluginDir}/src/java")) - pluginSourceFiles = (Resource[])SpringIOUtils.addAll(pluginSourceFiles, resourceResolver("file:${pluginDir}/src/groovy")) - cache['sourceFilesPerPlugin'][pluginDir] = pluginSourceFiles - return pluginSourceFiles - } - cache.sourceFiles = sourceFiles - } - return (Resource[])sourceFiles - } - - /** - * Gets all the plugin source directories for the given plugin directory - */ - Resource[] getPluginSourceDirectories(File pluginDir) { - getPluginSourceDirectories() // initialize cache - - cache['sourceFilesPerPlugin'][pluginDir.absolutePath] - } - - /** - * @deprecated Use getPluginSourceDirectories - */ - Resource[] getPluginSourceFiles(File pluginDir) { - return getPluginSourceDirectories(pluginDir) - } - - /** - * Obtains an array of all plugin provided JAR files - */ - Resource[] getPluginJarFiles() { - resolveResources 'jarFiles', false, { pluginDir -> - resourceResolver("file:${pluginDir}/lib/*.jar") - } - } - - /** - * Obtains an array of all plugin provided JAR files for plugins that don't define - * a dependencies.groovy. - */ - Resource[] getUnmanagedPluginJarFiles() { - resolveResources 'unmanagedPluginJars', false, { pluginDir -> - if (!new File("${pluginDir}/dependencies.groovy").exists()) { - return resourceResolver("file:${pluginDir}/lib/*.jar") - } - } - } - - /** - * Obtains a list of plugin directories for the application - */ - Resource[] getPluginDirectories() { - def pluginDirectoryResources = cache.pluginDirectoryResources - if (!pluginDirectoryResources) { - if (buildSettings) { - pluginDirectoryResources = buildSettings.getPluginDirectories().collect { new FileSystemResource(it) } as Resource[] - } - else { - pluginDirectoryResources = [] as Resource[] - } - cache.pluginDirectoryResources = pluginDirectoryResources - } - return pluginDirectoryResources - } - - /** - * Returns only the PluginInfo objects that support the current Environment and BuildScope. - * - * @see grails.util.Environment - * @see grails.util.BuildScope - */ - GrailsPluginInfo[] getSupportedPluginInfos() { - if (pluginManager == null) return getPluginInfos() - - def pluginInfos = getPluginInfos().findAll {GrailsPluginInfo info -> - def plugin = pluginManager.getGrailsPlugin(info.getName()) - return plugin?.supportsCurrentScopeAndEnvironment() - } - return pluginInfos as GrailsPluginInfo[] - } - - /** - * Returns a list of all plugin directories in both the given path - * and the global "plugins" directory together. - */ - List getImplicitPluginDirectories() { - def implicitPluginDirectories = cache.implicitPluginDirectories - if (implicitPluginDirectories == null) { - if (buildSettings) { - implicitPluginDirectories = buildSettings.getImplicitPluginDirectories().collect { new FileSystemResource(it) } - } - else { - implicitPluginDirectories = [] as Resource[] - } - cache.implicitPluginDirectories = implicitPluginDirectories - } - return implicitPluginDirectories - } - - /** - * Gets a list of all the known plugin base directories (directories where plugins are installed to). - */ - List getPluginBaseDirectories() { - return buildSettings?.getPluginBaseDirectories() ?: [] - } - - /** - * Returns true if the specified plugin directory is a global plugin. - */ - boolean isGlobalPluginLocation(Resource pluginDir) { - def globalPluginsDir = buildSettings?.globalPluginsDir?.canonicalFile - def containingDir = pluginDir?.file?.parentFile?.canonicalFile - if (globalPluginsDir || containingDir) { - return globalPluginsDir == containingDir - } - return false - } - - /** - * Obtains a reference to all artefact resources (all Groovy files contained within the - * grails-app directory of plugins or applications). - */ - Resource[] getArtefactResources() { - def basedir = buildSettings.baseDir.absolutePath - def allArtefactResources = cache.allArtefactResources - if (!allArtefactResources) { - def resources = [] as Resource[] - - // first scan plugin sources. These need to be loaded first - resources = resolvePluginResourcesAndAdd(resources, true) { String pluginDir -> - getArtefactResourcesForOne(pluginDir) - } - - // now build of application resources so that these can override plugin resources - resources = SpringIOUtils.addAll(resources, getArtefactResourcesForOne(new File(basedir).canonicalFile.absolutePath)) - - allArtefactResources = resources - cache.allArtefactResources = resources - } - return allArtefactResources - } - - /** - * @return A list of plugin infos that are supported and scoped for compile or runtime - */ - @CompileStatic - List getCompileScopedArtefactResources() { - List artefactResources = (List)cache['compileScopedArtefactResources'] - if (artefactResources == null) { - artefactResources = [] - artefactResources.addAll compileScopePluginInfo.artefactResources - artefactResources.addAll getArtefactResourcesForOne(buildSettings.baseDir.path) - cache['compileScopedArtefactResources'] = artefactResources - } - return artefactResources - } - - /** - * - * @return A list of plugin infos that are supported and scoped for compile or runtime - */ -// @CompileStatic - List getCompileScopedSupportedPluginInfos() { - Collection compileScopePluginInfos = (Collection)cache.compileScopePluginInfos - if (compileScopePluginInfos == null) { - def pluginInfos = supportedPluginInfos - compileScopePluginInfos = [] - compileScopePluginInfos.addAll compileScopePluginInfo.pluginInfos - compileScopePluginInfos = compileScopePluginInfos.findAll { GrailsPluginInfo info -> pluginInfos.any { GrailsPluginInfo it -> it.name == info.name } } - cache.compileScopePluginInfos = compileScopePluginInfos - } - return compileScopePluginInfos - } - - /** - * Returns all the artefact resources for the current environment where the environment is to be executed using the embedded container (not WAR deployed) - * - * @return An array of all artefact resources - */ - //@CompileStatic - Resource[] getArtefactResourcesForCurrentEnvironment() { - Resource[] artefactResources = (Resource[])cache['allArtefactResourcesForEnvironment'] - if (artefactResources == null) { - - List artefactResourcesList = [] - artefactResourcesList.addAll compileScopePluginInfo.getArtefactResources() - artefactResourcesList.addAll providedScopePluginInfo.getArtefactResources() - artefactResourcesList.addAll getArtefactResourcesForOne(buildSettings.baseDir.path) - if (Environment.getCurrent() == Environment.TEST) { - artefactResourcesList.addAll testScopePluginInfo.getArtefactResources() - } - def inlineDirectories = getInlinePluginDirectories() - for (Resource dir in inlineDirectories) { - artefactResourcesList.addAll getArtefactResourcesForOne(dir.file.absolutePath) - } - - artefactResources = artefactResourcesList as Resource[] - cache['allArtefactResourcesForEnvironment'] = artefactResources - } - return artefactResources - } - - /** - * Returns an array of all artefacts in the given application or - * plugin directory as Spring resources. - */ - Resource[] getArtefactResourcesForOne(String projectDir) { - return resourceResolver("file:${projectDir}/grails-app/**/*.groovy") - } - - Resource[] getPluginDescriptorsForCurrentEnvironment() { - def descriptorList = cache.pluginDescriptorsForCurrentEnvironment - if (descriptorList == null) { - if (Environment.current == Environment.TEST) { - descriptorList = pluginScopeInfoMap.values()*.pluginDescriptors.flatten() - } - else { - descriptorList = pluginScopeInfoMap.values().findAll { PluginScopeInfo scopeInfo -> scopeInfo.scopeName != "test" }*.pluginDescriptors.flatten() - } - - def baseDescriptor = getBasePluginDescriptor() - if (baseDescriptor != null) { - descriptorList << baseDescriptor - } - for (inlinePluginDir in getInlinePluginDirectories()) { - descriptorList << getPluginDescriptor(inlinePluginDir) - } - - descriptorList = descriptorList.unique() - - cache.pluginDescriptorsForCurrentEnvironment = descriptorList - } - return descriptorList as Resource[] - } - /** - * Obtains an array of all plugin descriptors (the root classes that end with *GrailsPlugin.groovy). - */ - Resource[] getPluginDescriptors() { - def pluginDescriptors = cache.pluginDescriptors - if (!pluginDescriptors) { - def pluginDirs = getPluginDirectories().toList() - if (buildSettings?.baseDir) { - pluginDirs << new FileSystemResource(buildSettings.baseDir) - } - def descriptors = [] - for (Resource dir in pluginDirs) { - def desc = getPluginDescriptor(dir) - if (desc) { - descriptors << desc - } - } - - pluginDescriptors = descriptors as Resource[] - cache.pluginDescriptors = pluginDescriptors - } - return pluginDescriptors - } - - /** - * Returns the plugin descriptor for the Given plugin directory. - * - * @param pluginDir The plugin directory - * @return The plugin descriptor - */ - Resource getPluginDescriptor(Resource pluginDir) { - File f = pluginDir?.file.listFiles()?.find { it.name.endsWith("GrailsPlugin.groovy") } - if (f) return new FileSystemResource(f) - } - - /** - * Obtains an array of all plugin lib directories. - */ - Resource[] getPluginLibDirectories() { - resolveResources 'pluginLibs', false, { pluginDir -> - resourceResolver("file:${pluginDir}/lib") - } - } - - /** - * Obtains an array of all plugin i18n directories. - */ - Resource[] getPluginI18nDirectories() { - resolveResources 'plugin18nDirectories', false, { pluginDir -> - resourceResolver("file:${pluginDir}/grails-app/i18n") - } - } - - /** - * Obtains the path to the global plugins directory. - */ - String getGlobalPluginsPath() { buildSettings?.globalPluginsDir?.path } - - /** - * Obtains a plugin directory for the given name. - */ - Resource getPluginDirForName(String pluginName) { - Resource pluginResource = (Resource)pluginToDirNameMap[pluginName] - if (!pluginResource) { - try { - GrailsPluginInfo pluginInfo = getPluginInfoForName(pluginName) - File pluginFile = pluginInfo?.pluginDir?.file - - // If the plugin can't be found in one of the standard - // locations, check whether it's an in-place plugin. - - if (!pluginFile && pluginLocations) { - Map.Entry pluginLoc = (Map.Entry)pluginLocations.find { String key, value -> pluginName == key } - if (pluginLoc?.value) pluginFile = new File(pluginLoc.value.toString()) - } - - if (pluginFile != null) { - pluginResource = new FileSystemResource(pluginFile) - } - if (pluginResource) { - pluginToDirNameMap[pluginName] = pluginResource - } - } - catch (IOException ignore) { - return null - } - } - return pluginResource - } - - /** - * Reads plugin metadata from a plugin zip file and returns a list containing the plugin name, version and - * XML metadata. Designed for use with Groovy's multiple assignment operator - * - * @param zipLocation The zip location - * @return A list - */ - List readMetadataFromZip(String zipLocation) { - def zipFile = null - try { - zipFile = new ZipFile(zipLocation) - ZipEntry entry = zipFile.entries().find {ZipEntry entry -> entry.name == 'plugin.xml'} - if (entry) { - def pluginXml = SpringIOUtils.createXmlSlurper().parse(zipFile.getInputStream(entry)) - def name = pluginXml.'@name'.text() - def release = pluginXml.'@version'.text() - return [name, release, pluginXml] - } - } - catch (e) { - // ignore - } finally { - try { zipFile?.close() } catch (e) { } - } - return null - } - - - /** - * Reads plugin info from the zip file location - * - * @param zipLocation The zip location - * @return - */ - GrailsPluginInfo readPluginInfoFromZip(String zipLocation) { - String key = 'pluginInfo:' + zipLocation - GrailsPluginInfo info = cache[key] - if (info == null) { - - def result = readMetadataFromZip(zipLocation) - if (result != null) { - - def (name, version, xml) = result - - if (name == null || version == null) return null - - def pluginInfo = getPluginInfoForName(name) - if (pluginInfo != null) { - info = new BasicGrailsPluginInfo(pluginInfo.descriptor) - info.name = name - info.version = version - cache[key] = info - } - } - } - return info - } - /** - * Obtains the 'base' plugin descriptor, which is the plugin descriptor of the current plugin project. - */ - @CompileStatic - Resource getBasePluginDescriptor() { - Resource basePluginDescriptor = (Resource)cache['basePluginDescriptor'] - if (!basePluginDescriptor) { - basePluginDescriptor = getDescriptorForPlugin( - new FileSystemResource(buildSettings.baseDir.absolutePath)) - if (basePluginDescriptor) { - cache['basePluginDescriptor'] = basePluginDescriptor - } - } - return basePluginDescriptor - } - - /** - * Returns the descriptor location for the given plugin directory. The descriptor is the Groovy - * file that ends with *GrailsPlugin.groovy - */ -// @CompileStatic - Resource getDescriptorForPlugin(Resource pluginDir) { - FileSystemResource descriptor = null - File baseFile = pluginDir.file.canonicalFile - File basePluginFile = (File)baseFile.listFiles().find { File it -> it.name.endsWith("GrailsPlugin.groovy")} - - if (basePluginFile?.exists()) { - descriptor = new FileSystemResource(basePluginFile) - } - return descriptor - } - - //@CompileStatic - private Resource[] resolveResources(String key, boolean processExcludes, Closure c) { - Resource[] resources = (Resource[])cache[key] - if (!resources) { - resources = new Resource[0] - resources = resolvePluginResourcesAndAdd(resources, processExcludes, c) - cache[key] = resources - } - return resources - } - - /** - * Takes a Resource[] and optional pluginsDirPath and goes through each plugin directory. - * It will then used the provided resolving resolving closures to attempt to resolve a new - * set of resources to add to the original passed array. - * - * A new array is then returned that contains any additiona plugin resources that were - * resolved by the expression passed in the closure. - */ - @CompileStatic - private resolvePluginResourcesAndAdd(Resource[] originalResources, boolean processExcludes, Closure resolver) { - - Resource[] pluginDirs = getPluginDirectories() - AntPathMatcher pathMatcher = new AntPathMatcher() - for (Resource dir in pluginDirs) { - def newResources = dir ? resolver(dir.file.absolutePath) : null - if (newResources) { - if (processExcludes) { - def excludes = EXCLUDED_RESOURCES - newResources = newResources.findAll { Resource r -> - def relPath = relativePath(dir.file, r.file) - !excludes.any { String it -> - pathMatcher.match(it, relPath) - } - } - } - originalResources = (Resource[])SpringIOUtils.addAll(originalResources, newResources as Resource[]) - } - } - return originalResources - } - - @CompileStatic - private String relativePath(File relbase, File file) { - def pathParts = [] - def currentFile = file - while (currentFile != null && currentFile != relbase) { - pathParts += currentFile.name - currentFile = currentFile.parentFile - } - pathParts.reverse().join('/') - } -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CachedScript.java b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CachedScript.java deleted file mode 100644 index 380d0bc5dce..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CachedScript.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2004-2005 the original author or authors. - * - * 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 org.codehaus.groovy.grails.cli; - -import org.codehaus.gant.GantBinding; -import org.grails.io.support.Resource; - -import java.util.List; - -/** - * Represents a script that has been cached with a specific binding. - * - * @since 1.1 - * @author Peter Ledbrook - */ -class CachedScript { - - GantBinding binding; - List potentialScripts; -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CommandLineHelper.java b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CommandLineHelper.java deleted file mode 100644 index 063c0282f7b..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CommandLineHelper.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2004-2005 the original author or authors. - * - * 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 org.codehaus.groovy.grails.cli; - -import grails.build.logging.GrailsConsole; - -import java.io.InputStream; -import java.io.PrintStream; - -/** - * Utility methods for use on the command line, including method to accept user input etc. - * - * @author Graeme Rocher - * @since 1.2 - */ -public class CommandLineHelper { - - // Use static variables so that feature uses of CommandLineHelper use those provided by the constructor - // bit of a hack, but don't see many other options - - public CommandLineHelper() { - // default - } - - /** - * @deprecated Use no-args constructor - */ - @Deprecated - public CommandLineHelper(PrintStream out) { - } - - /** - * @deprecated Use no-args constructor - */ - @Deprecated - public CommandLineHelper(InputStream input, PrintStream out) { - } - - /** - * Replacement for AntBuilder.input() to eliminate dependency of - * GrailsScriptRunner on the Ant libraries. Prints a message and - * returns whatever the user enters (once they press <return>). - * @param message The message/question to display. - * @return The line of text entered by the user. May be a blank - * string. - */ - public String userInput(String message) { - return GrailsConsole.getInstance().userInput(message); - } - - /** - * Replacement for AntBuilder.input() to eliminate dependency of - * GrailsScriptRunner on the Ant libraries. Prints a message and - * list of valid responses, then returns whatever the user enters - * (once they press <return>). If the user enters something - * that is not in the array of valid responses, the message is - * displayed again and the method waits for more input. It will - * display the message a maximum of three times before it gives up - * and returns null. - * @param message The message/question to display. - * @param validResponses An array of responses that the user is - * allowed to enter. Displayed after the message. - * @return The line of text entered by the user, or null - * if the user never entered a valid string. - */ - public String userInput(String message, String[] validResponses) { - return GrailsConsole.getInstance().userInput(message, validResponses); - } -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CommandLineInputHandler.java b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CommandLineInputHandler.java deleted file mode 100644 index a172c220a43..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/CommandLineInputHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2011 SpringSource - * - * 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 org.codehaus.groovy.grails.cli; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.input.InputHandler; -import org.apache.tools.ant.input.InputRequest; -import org.apache.tools.ant.input.MultipleChoiceInputRequest; -import grails.build.logging.GrailsConsole; - -import java.util.List; - -/** - * Custom input handler mechanism for Ant that ignores case of input. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class CommandLineInputHandler implements InputHandler { - - public void handleInput(InputRequest inputRequest) throws BuildException { - String[] validInputs = null; - if (inputRequest instanceof MultipleChoiceInputRequest) { - @SuppressWarnings("unchecked") - List choices = ((MultipleChoiceInputRequest) inputRequest).getChoices(); - validInputs = choices.toArray(new String[choices.size()]); - } - String result = GrailsConsole.getInstance().userInput(inputRequest.getPrompt(), validInputs); - if (result == null || result.length() == 0) { - result = inputRequest.getDefaultValue(); - } - inputRequest.setInput(result); - } -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/GenerateStubsTask.java b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/GenerateStubsTask.java deleted file mode 100644 index 3dd6ee17910..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/GenerateStubsTask.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2004-2005 Graeme Rocher - * - * 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 org.codehaus.groovy.grails.cli; - -import groovy.lang.GroovyClassLoader; - -import java.io.File; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.DirectoryScanner; -import org.codehaus.groovy.ant.CompileTaskSupport; -import org.codehaus.groovy.control.Phases; -import org.codehaus.groovy.tools.javac.JavaStubCompilationUnit; - -/** - * Need to spin our own GenerateStubsTask because Groovy's one stupidly tries to compile properties - * files and anything that doesn't end with Java. - * - * @author Graeme Rocher - * @since 1.1 - */ -public class GenerateStubsTask extends CompileTaskSupport { - - @Override - protected void compile() throws Exception { - GroovyClassLoader gcl = createClassLoader(); - JavaStubCompilationUnit compilation = new JavaStubCompilationUnit(config, gcl, destdir); - - int count = 0; - - for (String fileName : src.list()) { - File basedir = getProject().resolveFile(fileName); - if (!basedir.exists()) { - throw new BuildException("Source directory does not exist: " + basedir, getLocation()); - } - - DirectoryScanner scanner = getDirectoryScanner(basedir); - String[] includes = scanner.getIncludedFiles(); - - log.debug("Including files from: " + basedir); - - for (String currentInclude : includes) { - log.debug(" " + currentInclude); - - File file = new File(basedir, currentInclude); - if (isSource(currentInclude)) { - compilation.addSource(file); - } - - // Increment the count for each non/java src we found - if (currentInclude.endsWith(".groovy")) { - count++; - } - } - } - - if (count > 0) { - log.info("Generating " + count + " Java stub" + (count > 1 ? "s" : "") + " to " + destdir); - - // Generate the stubs - compilation.compile(Phases.CONVERSION); - } - else { - log.info("No sources found for stub generation"); - } - } - - private boolean isSource(String currentInclude) { - return currentInclude.endsWith(".groovy") || currentInclude.endsWith(".java"); - } -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/GrailsScriptRunner.java b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/GrailsScriptRunner.java deleted file mode 100644 index 0b858bcae39..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/GrailsScriptRunner.java +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Copyright 2004-2005 the original author or authors. - * - * 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 org.codehaus.groovy.grails.cli; - -import gant.Gant; -import grails.build.logging.GrailsConsole; -import grails.util.BuildSettings; -import grails.util.BuildSettingsHolder; -import grails.util.CosineSimilarity; -import grails.util.Environment; -import grails.util.GrailsNameUtils; -import grails.util.PluginBuildSettings; -import groovy.lang.Closure; -import groovy.lang.ExpandoMetaClass; -import groovy.lang.GroovyObject; -import groovy.lang.GroovySystem; -import groovy.util.AntBuilder; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.*; -import java.util.regex.Pattern; - -import org.apache.tools.ant.Project; -import org.codehaus.gant.GantBinding; -import org.codehaus.gant.GantMetaClass; -import org.codehaus.groovy.grails.cli.fork.ForkedGrailsProcess; -import org.codehaus.groovy.grails.cli.interactive.InteractiveMode; -import org.codehaus.groovy.grails.cli.parsing.CommandLine; -import org.codehaus.groovy.grails.cli.parsing.CommandLineParser; -import org.codehaus.groovy.grails.cli.parsing.DefaultCommandLine; -import org.codehaus.groovy.grails.cli.parsing.ParseException; -import org.codehaus.groovy.grails.cli.support.ClasspathConfigurer; -import org.codehaus.groovy.grails.cli.support.PluginPathDiscoverySupport; -import org.codehaus.groovy.grails.cli.support.ScriptBindingInitializer; -import org.grails.io.support.PathMatchingResourcePatternResolver; -import org.grails.io.support.Resource; -import org.grails.build.plugins.GrailsPluginUtils; -import org.codehaus.groovy.runtime.DefaultGroovyMethods; - -/** - * Handles Grails command line interface for running scripts. - * - * @author Graeme Rocher - * - * @since 0.4 - */ -public class GrailsScriptRunner { - - private static final Pattern scriptFilePattern = Pattern.compile("^[^_]\\w+\\.groovy$"); - - private static InputStream originalIn; - - private static PrintStream originalOut; - @SuppressWarnings("rawtypes") - public static final Closure DO_NOTHING_CLOSURE = new Closure(GrailsScriptRunner.class) { - private static final long serialVersionUID = 1L; - @Override public Object call(Object arguments) { return null; } - @Override public Object call() { return null; } - @Override public Object call(Object... args) { return null; } - }; - private PluginPathDiscoverySupport pluginPathSupport; - private BuildSettings settings; - - private PrintStream out = System.out; - private GrailsConsole console = GrailsConsole.getInstance(); - private boolean isInteractive = System.getProperty(GrailsConsole.ENABLE_INTERACTIVE) != null ? Boolean.getBoolean(GrailsConsole.ENABLE_INTERACTIVE) : true; - private URLClassLoader classLoader; - - private File scriptCacheDir; - private final List scriptsAllowedOutsideOfProject = new ArrayList(); - - public GrailsScriptRunner() { - this(new BuildSettings()); - } - - public GrailsScriptRunner(String grailsHome) { - this(new BuildSettings(new File(grailsHome))); - } - - public GrailsScriptRunner(BuildSettings settings) { - if (originalIn == null) { - originalIn = System.in; - originalOut = System.out; - } - this.settings = settings; - pluginPathSupport = new PluginPathDiscoverySupport(settings); - } - - public void setInteractive(boolean interactive) { - isInteractive = interactive; - } - - /** - * Evaluate the arguments to get the name of the script to execute, which environment - * to run it in, and the arguments to pass to the script. This also evaluates arguments - * of the form "-Dprop=value" and creates system properties from each one. - * - * @param args Command line arguments - */ - public static void main(String[] args) { - System.setProperty("net.sf.ehcache.skipUpdateCheck", "true"); - ExpandoMetaClass.enableGlobally(); - originalIn = System.in; - originalOut = System.out; - - CommandLineParser parser = getCommandLineParser(); - - GrailsConsole console = GrailsConsole.getInstance(); - - CommandLine commandLine; - try { - if (args.length == 0) { - commandLine = new DefaultCommandLine(); - } - else { - commandLine = parser.parseString(args[0]); - if (commandLine.hasOption(CommandLine.NOANSI_ARGUMENT)) { - console.setAnsiEnabled(false); - } - } - } catch (ParseException e) { - console.error("Error processing command line arguments: " + e.getMessage()); - System.exit(1); - return; - } - - ScriptAndArgs script = processArgumentsAndReturnScriptName(commandLine); - - // Get hold of the GRAILS_HOME environment variable if it is available. - String grailsHome = System.getProperty("grails.home"); - - // Now we can pick up the Grails version from the Ant project properties. - BuildSettings build = null; - try { - build = new BuildSettings(new File(grailsHome)); - build.setModified(commandLine.hasOption(CommandLine.REFRESH_DEPENDENCIES_ARGUMENT)); - build.setOffline(commandLine.hasOption(CommandLine.OFFLINE_ARGUMENT)); - if(commandLine.hasOption(CommandLine.DEBUG_FORK)) { - System.setProperty(ForkedGrailsProcess.DEBUG_FORK, "true"); - } - if (build.getRootLoader() == null) { - build.setRootLoader((URLClassLoader) GrailsScriptRunner.class.getClassLoader()); - } - } - catch (Exception e) { - exitWithError("An error occurred loading the grails-app/conf/BuildConfig.groovy file: " + e.getMessage(), null); - } - - // Check that Grails' home actually exists. - final File grailsHomeInSettings = build.getGrailsHome(); - if (grailsHomeInSettings == null || !grailsHomeInSettings.exists()) { - exitWithError("Grails' installation directory not found: " + build.getGrailsHome(), null); - } - - if (commandLine.hasOption(CommandLine.VERSION_ARGUMENT)) { - console.log("Grails version: " + build.getGrailsVersion()); - System.exit(0); - } - - if (commandLine.hasOption(CommandLine.HELP_ARGUMENT)) { - if (commandLine.getCommandName() != null) { - console.log("The '-help' option is deprecated; use 'grails help [target]'"); - } else { - console.log("The '-help' option is deprecated; use 'grails help'"); - } - System.exit(0); - } - - boolean resolveDeps = commandLine.hasOption(CommandLine.REFRESH_DEPENDENCIES_ARGUMENT); - if (resolveDeps) { - if (commandLine.hasOption("include-source")) { - build.setIncludeSource(true); - } - if (commandLine.hasOption("include-javadoc")) { - build.setIncludeJavadoc(true); - } - } - GrailsScriptRunner scriptRunner = new GrailsScriptRunner(build); - scriptRunner.setInteractive(!commandLine.hasOption(CommandLine.NON_INTERACTIVE_ARGUMENT)); - if ("Interactive".equals(script.name)) { - console.error("The 'interactive' script is deprecated; to run in interactive mode just omit the script name"); - script.name = null; - } - - if (script.name == null) { - String version = System.getProperty("grails.version"); - console.updateStatus("Loading Grails " + (version == null ? build.getGrailsVersion() : version)); - - loadConfigEnvironment(commandLine, build); - if (resolveDeps) { - ClasspathConfigurer.cleanResolveCache(build); - } - scriptRunner.initializeState(); - try { - new InteractiveMode(build, scriptRunner).run(); - } catch (Throwable e) { - console.error("Interactive mode exited with error: " + e.getMessage(), e); - } - } - else { - console.getCategory().push(script.inputName); - console.verbose("Base Directory: " + build.getBaseDir().getPath()); - - try { - int exitCode = scriptRunner.executeCommand(commandLine, script.name, script.env); - GrailsConsole.getInstance().flush(); - System.exit(exitCode); - } - catch (ScriptNotFoundException ex) { - console.error("Script not found: " + ex.getScriptName()); - } - catch (Throwable t) { - String msg = "Error executing script " + script.name + ": " + t.getMessage(); - exitWithError(msg, t); - } - } - } - - private static void loadConfigEnvironment(CommandLine commandLine, BuildSettings build) { - String env; - if(commandLine.isEnvironmentSet()) { - env = commandLine.getEnvironment(); - } - else { - env = commandLine.lookupEnvironmentForCommand(); - } - build.setGrailsEnv(env); - build.loadConfig(env); - } - - public static CommandLineParser getCommandLineParser() { - CommandLineParser parser = new CommandLineParser(); - parser.addOption(CommandLine.REFRESH_DEPENDENCIES_ARGUMENT, "Whether to force a resolve of dependencies (skipping any caching)"); - parser.addOption(CommandLine.VERBOSE_ARGUMENT, "Enable verbose output"); - parser.addOption(CommandLine.OFFLINE_ARGUMENT, "Indicates that Grails should not connect to any remote servers during processing of the build"); - parser.addOption(CommandLine.STACKTRACE_ARGUMENT, "Enable stack traces in output"); - parser.addOption(CommandLine.AGENT_ARGUMENT, "Enable the reloading agent"); - parser.addOption(CommandLine.NON_INTERACTIVE_ARGUMENT, "Whether to allow the command line to request input"); - parser.addOption(CommandLine.VERSION_ARGUMENT, "Current Grails version"); - parser.addOption(CommandLine.NOANSI_ARGUMENT, "Disables ANSI output"); - parser.addOption(CommandLine.DEBUG_FORK, "Whether to debug the forked JVM if using forked mode"); - return parser; - } - - private static void exitWithError(String error, Throwable t) { - GrailsConsole grailsConsole = GrailsConsole.getInstance(); - if (t == null) { - grailsConsole.error(error); - } - else { - grailsConsole.error(error, t); - } - grailsConsole.flush(); - System.exit(1); - } - - private static ScriptAndArgs processArgumentsAndReturnScriptName(CommandLine commandLine) { - - if (commandLine.hasOption(CommandLine.VERBOSE_ARGUMENT)) { - GrailsConsole.getInstance().setVerbose(true); - } - if (commandLine.hasOption(CommandLine.STACKTRACE_ARGUMENT)) { - GrailsConsole.getInstance().setStacktrace(true); - } - - processSystemArguments(commandLine); - return processAndReturnArguments(commandLine); - } - - private static ScriptAndArgs processAndReturnArguments(CommandLine commandLine) { - ScriptAndArgs info = new ScriptAndArgs(); - if (Environment.isSystemSet()) { - info.env = Environment.getCurrent().getName(); - } - else if (commandLine.getEnvironment() != null) { - info.env = commandLine.getEnvironment(); - } - - info.inputName = commandLine.getCommandName(); - info.name = GrailsNameUtils.getNameFromScript(commandLine.getCommandName()); - return info; - } - - private static void processSystemArguments(CommandLine allArgs) { - Properties systemProps = allArgs.getSystemProperties(); - if (systemProps != null) { - for (Map.Entry entry : systemProps.entrySet()) { - System.setProperty(entry.getKey().toString(), entry.getValue().toString()); - } - } - } - - public PrintStream getOut() { - return out; - } - - public void setOut(PrintStream outputStream) { - out = outputStream; - } - - public int executeCommand(String scriptName, String args) { - return executeCommand(scriptName, args, null); - } - - public int executeCommand(String scriptName, String args, String env) { - // Populate the root loader with all libraries that this app - // depends on. If a root loader doesn't exist yet, create it now. - - if (args != null) { - System.setProperty("grails.cli.args", args.replace(' ', '\n')); - } - else { - // If GrailsScriptRunner is executed more than once in a - // single JVM, we have to make sure that the CLI args are reset. - System.setProperty("grails.cli.args", ""); - } - - CommandLineParser parser = getCommandLineParser(); - DefaultCommandLine commandLine = (DefaultCommandLine) parser.parseString(scriptName,args); - setInteractive(!commandLine.hasOption(CommandLine.NON_INTERACTIVE_ARGUMENT)); - if (env != null) { - commandLine.setEnvironment(env); - } - - return executeCommand(commandLine, scriptName, env); - } - - private int executeCommand(CommandLine commandLine, String scriptName, String env) { - GrailsConsole console = getConsole(commandLine); - - // Load the BuildSettings file for this project if it exists. Note - // that this does not load any environment-specific settings. - try { - System.setProperty("disable.grails.plugin.transform", "true"); - - console.updateStatus("Loading Grails " + settings.getGrailsVersion()); - loadConfigEnvironment(commandLine, settings); - settings.initializeResourcesDir(); - - System.setProperty("springloaded.directoriesContainingReloadableCode", - settings.getClassesDir().getAbsolutePath() + ',' + - settings.getPluginClassesDir().getAbsolutePath()); - } - catch (Exception e) { - console.error("There was an error loading the BuildConfig: " + e.getMessage(), e); - System.exit(1); - } - finally { - System.setProperty("disable.grails.plugin.transform", "false"); - } - - // Add some extra binding variables that are now available. - // settings.setGrailsEnv(env); - // settings.setDefaultEnv(useDefaultEnv); - - try { - BuildSettingsHolder.setSettings(settings); - return callPluginOrGrailsScript(commandLine, scriptName, env); - } finally { - GrailsConsole.getInstance().flush(); - BuildSettingsHolder.setSettings(null); - } - } - - private GrailsConsole getConsole(CommandLine commandLine) { - GrailsConsole console = GrailsConsole.getInstance(); - - // Set the console display properties - console.setAnsiEnabled(!commandLine.hasOption(CommandLine.NOANSI_ARGUMENT)); - console.setStacktrace(commandLine.hasOption(CommandLine.STACKTRACE_ARGUMENT)); - console.setVerbose(commandLine.hasOption(CommandLine.VERBOSE_ARGUMENT)); - - return console; - } - - private void setRunningEnvironment(CommandLine commandLine, String env) { - // Get the default environment if one hasn't been set. - System.setProperty("base.dir", settings.getBaseDir().getPath()); - - if (env != null) { - // Add some extra binding variables that are now available. - settings.setGrailsEnv(env); - settings.setDefaultEnv(false); - } - else { - // Add some extra binding variables that are now available. - settings.setGrailsEnv(commandLine.getEnvironment()); - settings.setDefaultEnv(!commandLine.isEnvironmentSet()); - } - } - - private int callPluginOrGrailsScript(CommandLine commandLine, String scriptName, String env) { - initializeState(scriptName); - return executeScriptWithCaching(commandLine,scriptName, env); - } - - public int executeScriptWithCaching(CommandLine commandLine) { - processSystemArguments(commandLine); - - System.setProperty("grails.cli.args", commandLine.getRemainingArgsLineSeparated()); - return executeScriptWithCaching(commandLine, GrailsNameUtils.getNameFromScript(commandLine.getCommandName()), commandLine.getEnvironment()); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private int executeScriptWithCaching(CommandLine commandLine, String scriptName, String env) { - List potentialScripts; - List allScripts = getAvailableScripts(); - GantBinding binding = new GantBinding(); - binding.setVariable("scriptName", scriptName); - - setDefaultInputStream(binding); - - // Now find what scripts match the one requested by the user. - potentialScripts = getPotentialScripts(scriptName, allScripts); - - if (potentialScripts.size() == 0) { - try { - File aliasFile = new File(settings.getUserHome(), ".grails/.aliases"); - if (aliasFile.exists()) { - Properties aliasProperties = new Properties(); - aliasProperties.load(new FileReader(aliasFile)); - if (aliasProperties.containsKey(commandLine.getCommandName())) { - String aliasValue = (String) aliasProperties.get(commandLine.getCommandName()); - String[] aliasPieces = aliasValue.split(" "); - String commandName = aliasPieces[0]; - String correspondingScriptName = GrailsNameUtils.getNameFromScript(commandName); - potentialScripts = getPotentialScripts(correspondingScriptName, allScripts); - - if (potentialScripts.size() > 0) { - String[] additionalArgs = new String[aliasPieces.length - 1]; - System.arraycopy(aliasPieces, 1, additionalArgs, 0, additionalArgs.length); - insertArgumentsInFrontOfExistingArguments(commandLine, additionalArgs); - } - } - } - } catch (Exception e) { - console.error(e); - } - } - - // First try to load the script from its file. If there is no - // file, then attempt to load it as a pre-compiled script. If - // that fails, then let the user know and then exit. - if (potentialScripts.size() > 0) { - potentialScripts = (List) DefaultGroovyMethods.unique(potentialScripts); - final File scriptFile = potentialScripts.get(0); - if (!isGrailsProject() && !isExternalScript(scriptFile)) { - return handleScriptExecutedOutsideProjectError(); - } - return executeScriptFile(commandLine, scriptName, env, binding, scriptFile); - } - - return attemptPrecompiledScriptExecute(commandLine, scriptName, env, binding, allScripts); - } - - private List getPotentialScripts(String scriptName, List allScripts) { - List potentialScripts; - boolean exactMatchFound = false; - potentialScripts = new ArrayList(); - for (File scriptPath : allScripts) { - String fileName = scriptPath.getName(); - String scriptFileName = fileName.substring(0, fileName.length() - 7); // trim .groovy extension - if (scriptFileName.endsWith("_")) { - scriptsAllowedOutsideOfProject.add(scriptPath); - scriptFileName = scriptFileName.substring(0, scriptFileName.length()-1); - } - - if (scriptFileName.equals(scriptName)) { - potentialScripts.add(scriptPath); - exactMatchFound = true; - continue; - } - - if (!exactMatchFound && ScriptNameResolver.resolvesTo(scriptName, scriptFileName)) { - potentialScripts.add(scriptPath); - } - } - return potentialScripts; - } - - private void insertArgumentsInFrontOfExistingArguments(CommandLine commandLine, String[] argumentsToInsert) { - List remainingArgs = commandLine.getRemainingArgs(); - for (int i = argumentsToInsert.length - 1; i >= 0; i-- ) { - remainingArgs.add(0, argumentsToInsert[i]); - } - } - - private int attemptPrecompiledScriptExecute(CommandLine commandLine, String scriptName, String env, GantBinding binding, List allScripts) { - console.updateStatus("Running pre-compiled script"); - - // Must be called before the binding is initialised. - setRunningEnvironment(commandLine, env); - - // Get Gant to load the class by name using our class loader. - ScriptBindingInitializer bindingInitializer = new ScriptBindingInitializer(commandLine, - classLoader, settings, pluginPathSupport, isInteractive); - Gant gant = new Gant(bindingInitializer.initBinding(binding, scriptName), classLoader); - - try { - loadScriptClass(gant, scriptName); - } - catch (ScriptNotFoundException e) { - if (!isInteractive || InteractiveMode.isActive()) { - throw e; - } - scriptName = fixScriptName(scriptName, allScripts); - if (scriptName == null) { - throw e; - } - - try { - loadScriptClass(gant, scriptName); - } - catch (ScriptNotFoundException ce) { - return executeScriptWithCaching(commandLine, scriptName, env); - } - - // at this point if they were calling a script that has a non-default - // env (e.g. war or test-app) it wouldn't have been correctly set, so - // set it now, but only if they didn't specify the env (e.g. "grails test war" -> "grails test war") - - if (Boolean.TRUE.toString().equals(System.getProperty(Environment.DEFAULT))) { - commandLine.setCommand(GrailsNameUtils.getScriptName(scriptName)); - env = commandLine.lookupEnvironmentForCommand(); - binding.setVariable("grailsEnv", env); - settings.setGrailsEnv(env); - System.setProperty(Environment.KEY, env); - settings.setDefaultEnv(false); - System.setProperty(Environment.DEFAULT, Boolean.FALSE.toString()); - } - } - - return executeWithGantInstance(gant, DO_NOTHING_CLOSURE, binding).exitCode; - } - - private int executeScriptFile(CommandLine commandLine, String scriptName, String env, GantBinding binding, File scriptFile) { - // We can now safely set the default environment - String scriptFileName = getScriptNameFromFile(scriptFile); - setRunningEnvironment(commandLine, env); - binding.setVariable("scriptName", scriptFileName); - - // Setup the script to call. - ScriptBindingInitializer bindingInitializer = new ScriptBindingInitializer( - commandLine, classLoader,settings, pluginPathSupport, isInteractive); - Gant gant = new Gant(bindingInitializer.initBinding(binding, scriptName), classLoader); - gant.setUseCache(true); - gant.setCacheDirectory(scriptCacheDir); - GantResult result = null; - try { - gant.loadScript(scriptFile.toURI().toURL()); - result = executeWithGantInstance(gant, DO_NOTHING_CLOSURE, binding); - return result.exitCode; - } catch (IOException e) { - console.error("I/O exception loading script [" + e.getMessage() + "]: " + e.getMessage()); - return 1; - } - finally { - cleanup(result, binding); - } - } - - @SuppressWarnings("rawtypes") - private void cleanup(GantResult result, GantBinding binding) { - if (result != null) { - Class cls = GantMetaClass.class; - try { - Field methodsInvoked = cls.getDeclaredField("methodsInvoked"); - methodsInvoked.setAccessible(true); - Set methodsInvokedSet = (Set) methodsInvoked.get(cls); - if (methodsInvokedSet != null) { - methodsInvokedSet.clear(); - } - } catch (NoSuchFieldException e) { - // ignore - } catch (IllegalAccessException e) { - // ignore - } - } - System.setIn(originalIn); - System.setOut(originalOut); - GrailsPluginUtils.clearCaches(); - Map variables = binding.getVariables(); - Object pluginsSettingsObject = variables.get("pluginsSettings"); - if (pluginsSettingsObject instanceof PluginBuildSettings) { - ((PluginBuildSettings)pluginsSettingsObject).clearCache(); - } - GroovySystem.getMetaClassRegistry().removeMetaClass(GantBinding.class); - GroovySystem.getMetaClassRegistry().removeMetaClass(Gant.class); - } - - public void initializeState() { - initializeState(null); - } - - private void initializeState(String scriptName) { - // The directory where scripts are cached. - scriptCacheDir = new File(settings.getProjectWorkDir(), "scriptCache"); - console = GrailsConsole.getInstance(); - // Add the remaining JARs (from 'grailsHome', the app, and - // the plugins) to the root loader. - - boolean skipPlugins = scriptName != null && ("UninstallPlugin".equals(scriptName) || "InstallPlugin".equals(scriptName)); - - console.updateStatus("Configuring classpath"); - ClasspathConfigurer configurer = new ClasspathConfigurer(pluginPathSupport, settings, skipPlugins); - if ("DependencyReport".equals(scriptName) || "Upgrade".equals(scriptName) || "SetProxy".equals(scriptName) || "AddProxy".equals(scriptName)) { - configurer.setExitOnResolveError(false); - } - classLoader = configurer.configuredClassLoader(); - initializeLogging(); - } - - private int handleScriptExecutedOutsideProjectError() { - console.error(settings.getBaseDir().getPath() + " does not appear to be part of a Grails application."); - console.error("The following commands are supported outside of a project:"); - Collections.sort(scriptsAllowedOutsideOfProject, new Comparator() { - public int compare(File resource, File resource1) { - return resource.getName().compareTo(resource1.getName()); - } - }); - for (File file : scriptsAllowedOutsideOfProject) { - console.log("\t" + GrailsNameUtils.getScriptName(file.getName())); - } - console.addStatus("Run 'grails help' for a complete list of available scripts."); - return -1; - } - - protected void initializeLogging() { - if (settings.getGrailsHome() == null) { - return; - } - - try { - Class cls = Thread.currentThread().getContextClassLoader().loadClass("org.apache.log4j.PropertyConfigurator"); - Method configure = cls.getMethod("configure", URL.class); - configure.setAccessible(true); - File f = new File(settings.getGrailsHome() + "/grails-scripts/src/main/scripts/log4j.properties"); - if(f.exists()) { - configure.invoke(cls, f.toURI().toURL()); - } - else { - f = new File(settings.getGrailsHome() + "/scripts/log4j.properties"); - configure.invoke(cls, f.toURI().toURL()); - } - } catch (Throwable e) { - console.verbose("Log4j was not found on the classpath and will not be used for command line logging. Cause "+e.getClass().getName()+": " + e.getMessage()); - } - } - - private void setDefaultInputStream(GantBinding binding) { - - // Gant does not initialise the default input stream for - // the Ant project, so we manually do it here. - AntBuilder antBuilder = (AntBuilder) binding.getVariable("ant"); - Project p = antBuilder.getAntProject(); - - try { - System.setIn(originalIn); - p.setInputHandler(new CommandLineInputHandler()); - p.setDefaultInputStream(originalIn); - } - catch (NoSuchMethodError nsme) { - // will only happen due to a bug in JRockit - // note - the only approach that works is to loop through the public methods - for (Method m : p.getClass().getMethods()) { - if ("setDefaultInputStream".equals(m.getName()) && m.getParameterTypes().length == 1 && - InputStream.class.equals(m.getParameterTypes()[0])) { - try { - m.invoke(p, originalIn); - break; - } - catch (Exception e) { - // shouldn't happen, but let it bubble up to the catch(Throwable) - throw new RuntimeException(e); - } - } - } - } - } - - private void loadScriptClass(Gant gant, String scriptName) { - try { - // try externalized script first - gant.loadScriptClass(scriptName + "_"); - } - catch (Exception e) { - try { - gant.loadScriptClass(scriptName); - } - catch (Exception ex) { - if (ex instanceof ClassNotFoundException && - ex.getMessage() != null && - ex.getMessage().contains(scriptName)) { - throw new ScriptNotFoundException(scriptName); - } - } - } - } - - private String fixScriptName(String scriptName, List allScripts) { - try { - Set names = new HashSet(); - for (File script : allScripts) { - String fileName = script.getName(); - names.add(fileName.substring(0, fileName.length() - 7)); - } - List mostSimilar = CosineSimilarity.mostSimilar(scriptName, names); - if (mostSimilar.isEmpty()) { - return null; - } - List topMatches = mostSimilar.subList(0, Math.min(5, mostSimilar.size())); - return askUserForBestMatch(scriptName, topMatches); - } - catch (Exception e) { - return null; - } - } - - private String askUserForBestMatch(String scriptName, List topMatches) { - GrailsConsole console = GrailsConsole.getInstance(); - console.addStatus("Script '" + scriptName + "' not found, did you mean:"); - int i = 0; - for (String s : topMatches) { - console.log(" " + ++i + ") " + s); - } - - int attempts = 0; - while (true) { - String selection = console.userInput("Please make a selection or enter Q to quit: "); - - if ("Q".equalsIgnoreCase(selection)) { - System.exit(0); - } - - try { - int number = Integer.parseInt(selection); - if (number > 0 && number <= topMatches.size()) { - return topMatches.get(number - 1); - } - } - catch (NumberFormatException ignored) { - // ignored - } - - attempts++; - if (attempts > 4) { - exitWithError("Selection not found.", null); - } - } - } - - private GantResult executeWithGantInstance(Gant gant, final Closure doNothingClosure, GantBinding binding) { - GantResult result = new GantResult(); - try { - result.script = gant.prepareTargets(); - gant.setAllPerTargetPostHooks(doNothingClosure); - gant.setAllPerTargetPreHooks(doNothingClosure); - // Invoke the default target. - result.exitCode = gant.executeTargets(); - return result; - } finally { - cleanup(result, binding); - } - } - - class GantResult { - int exitCode; - GroovyObject script; - } - - private boolean isGrailsProject() { - return new File(settings.getBaseDir(), "grails-app").exists(); - } - - private boolean isExternalScript(File scriptFile) { - return scriptsAllowedOutsideOfProject.contains(scriptFile); - } - - private String getScriptNameFromFile(File scriptPath) { - String fileName = scriptPath.getName(); - String scriptFileName = fileName.substring(0, fileName.length() - 7); // trim .groovy extension - if (scriptFileName.endsWith("_")) { - scriptFileName = scriptFileName.substring(0, scriptFileName.length()-1); - } - return scriptFileName; - } - - /** - * Returns a list of all the executable Gant scripts available to this application. - */ - public List getAvailableScripts() { - List scripts = new ArrayList(); - if (settings.getGrailsHome() != null) { - addCommandScripts(new File(settings.getGrailsHome(), "scripts"), scripts); - addCommandScripts(new File(settings.getGrailsHome(), "grails-scripts/src/main/scripts"), scripts); - } - addCommandScripts(new File(settings.getBaseDir(), "scripts"), scripts); - addCommandScripts(new File(settings.getUserHome(), ".grails/scripts"), scripts); - - for (File dir : pluginPathSupport.listKnownPluginDirs()) { - addPluginScripts(dir, scripts); - } - - PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(settings.getRootLoader()); - try { - final Resource[] resources = resolver.getResources("classpath*:META-INF/scripts/*.groovy"); - for (Resource resource : resources) { - scripts.add(resource.getFile()); - } - } catch (IOException e) { - // ignore - } - return scripts; - } - - /** - * Collects all the command scripts provided by the plugin contained - * in the given directory and adds them to the given list. - */ - private static void addPluginScripts(File pluginDir, List scripts) { - if (!pluginDir.exists()) return; - - File scriptDir = new File(pluginDir, "scripts"); - if (scriptDir.exists()) addCommandScripts(scriptDir, scripts); - } - - /** - * Adds all the command scripts (i.e. those whose name does *not* start with an - * underscore, '_') found in the given directory to the given list. - */ - private static void addCommandScripts(File dir, List scripts) { - if (!dir.exists()) { - return; - } - - for (File file : dir.listFiles()) { - if (scriptFilePattern.matcher(file.getName()).matches()) { - scripts.add(file); - } - } - } - - /** - * Contains details about a Grails command invocation such as the - * name of the corresponding script, the environment (if specified), - * and the arguments to the command. - */ - private static class ScriptAndArgs { - public String inputName; - public String name; - public String env; - } -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/api/BaseSettingsApi.java b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/api/BaseSettingsApi.java deleted file mode 100644 index 88745ca987e..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/api/BaseSettingsApi.java +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright 2010 the original author or authors. - * - * 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 org.codehaus.groovy.grails.cli.api; - -import grails.build.logging.GrailsConsole; -import grails.util.BuildSettings; -import grails.util.GrailsNameUtils; -import grails.util.Metadata; -import grails.util.PluginBuildSettings; -import groovy.lang.Binding; -import groovy.lang.Closure; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.util.ConfigSlurper; -import groovy.util.XmlSlurper; -import groovy.util.slurpersupport.GPathResult; - -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import javax.xml.parsers.ParserConfigurationException; - -import org.codehaus.groovy.grails.cli.ScriptExitException; -import org.codehaus.groovy.grails.cli.support.GrailsBuildEventListener; -import org.grails.io.support.*; -import org.grails.io.support.SpringIOUtils; -import org.grails.build.plugins.GrailsPluginUtils; -import org.codehaus.groovy.runtime.MethodClosure; -import org.xml.sax.SAXException; - -/** - * Utility methods used on the command line. - * - * @author Graeme Rocher - */ -public class BaseSettingsApi { - - private static final Resource[] NO_RESOURCES = new Resource[0]; - protected BuildSettings buildSettings; - protected Properties buildProps; - protected PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); - protected File grailsHome; - protected Metadata metadata; - protected File metadataFile; - protected boolean enableProfile; - protected boolean isInteractive; - protected String pluginsHome; - protected PluginBuildSettings pluginSettings; - protected String grailsAppName; - protected Object appClassName; - protected ConfigSlurper configSlurper; - protected GrailsBuildEventListener buildEventListener; - - public BaseSettingsApi(final BuildSettings buildSettings, boolean interactive) { - this(buildSettings, null, interactive); - } - - public BaseSettingsApi(BuildSettings settings, GrailsBuildEventListener buildEventListener, boolean interactive) { - buildSettings = settings; - buildProps = buildSettings.getConfig().toProperties(); - grailsHome = buildSettings.getGrailsHome(); - - metadataFile = new File(buildSettings.getBaseDir(), "application.properties"); - - metadata = metadataFile.exists() ? Metadata.getInstance(metadataFile) : Metadata.getCurrent(); - metadata.setServletVersion(buildSettings.getServletVersion()); - - metadataFile = metadata.getMetadataFile(); - enableProfile = Boolean.valueOf(getPropertyValue("grails.script.profile", false).toString()); - pluginsHome = buildSettings.getProjectPluginsDir().getPath(); - pluginSettings = GrailsPluginUtils.getPluginBuildSettings(settings); - grailsAppName = metadata.getApplicationName(); - isInteractive = interactive; - - // If no app name property (upgraded/new/edited project) default to basedir. - if (grailsAppName == null) { - grailsAppName = buildSettings.getBaseDir().getName(); - } - - if (grailsAppName.indexOf('/') >-1) { - appClassName = grailsAppName.substring(grailsAppName.lastIndexOf('/'), grailsAppName.length()); - } - else { - appClassName = GrailsNameUtils.getClassNameRepresentation(grailsAppName); - } - configSlurper = buildSettings.createConfigSlurper(); - configSlurper.setEnvironment(buildSettings.getGrailsEnv()); - this.buildEventListener = buildEventListener; - } - - public GrailsBuildEventListener getBuildEventListener() { - return buildEventListener; - } - - public void enableUaa() { - try { - Class uaaClass = BaseSettingsApi.class.getClassLoader().loadClass("org.codehaus.groovy.grails.cli.support.UaaEnabler"); - Object instance = uaaClass.getConstructor(new Class[]{BuildSettings.class, PluginBuildSettings.class}).newInstance(buildSettings, pluginSettings); - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(uaaClass); - metaClass.invokeMethod(instance, "enable", new Object[]{isInteractive}); - } catch (Exception e) { - // UAA not present, ignore - } - } - - public ConfigSlurper getConfigSlurper() { - return configSlurper; - } - - public Object getAppClassName() { - return appClassName; - } - - // server port options - // these are legacy settings - public int getServerPort() { - int serverPort = Integer.valueOf(getPropertyValue("server.port", 8080).toString()); - serverPort = Integer.valueOf(getPropertyValue("grails.server.port.http", serverPort).toString()); - return serverPort; - } - - public int getServerPortHttps() { - int serverPortHttps = Integer.valueOf(getPropertyValue("server.port.https", 8443).toString()); - serverPortHttps = Integer.valueOf(getPropertyValue("grails.server.port.https", serverPortHttps).toString()); - return serverPortHttps; - } - - public String getServerHost() { - return (String)getPropertyValue("grails.server.host", null); - } - - public String getGrailsAppName() { return grailsAppName; } - public String getGrailsAppVersion() { return metadata.getApplicationVersion(); } - public String getAppGrailsVersion() { return metadata.getGrailsVersion(); } - public String getServletVersion() { return buildSettings.getServletVersion(); } - - public String getPluginsHome() { - return pluginsHome; - } - - public PluginBuildSettings getPluginBuildSettings() { - return pluginSettings; - } - - public PluginBuildSettings getPluginSettings() { - return pluginSettings; - } - - public BuildSettings getBuildSettings() { - return buildSettings; - } - - public Properties getBuildProps() { - return buildProps; - } - - public PathMatchingResourcePatternResolver getResolver() { - return resolver; - } - - public File getGrailsHome() { - return grailsHome; - } - - public Metadata getMetadata() { - return metadata; - } - - public File getMetadataFile() { - return metadataFile; - } - - public boolean isEnableProfile() { - return enableProfile; - } - - public boolean getIsInteractive() { - return isInteractive; - } - - public Resource[] resolveResources(String pattern) { - try { - return resolver.getResources(pattern); - } - catch (Exception e) { - return NO_RESOURCES; - } - } - - /** Closure that returns a Spring Resource - either from $GRAILS_HOME - if that is set, or from the classpath.*/ - public Resource grailsResource(String path) { - if (grailsHome != null) { - FileSystemResource resource = new FileSystemResource(grailsHome + "/" + path); - if (!resource.exists()) { - resource = new FileSystemResource(grailsHome + "/grails-resources/" + path); - } - return resource; - } - return new ClassPathResource(path); - } - - /** Copies a Spring resource to the file system.*/ - public void copyGrailsResource(Object targetFile, Resource resource) throws FileNotFoundException, IOException { - copyGrailsResource(targetFile, resource, true); - } - - public void copyGrailsResource(Object targetFile, Resource resource, boolean overwrite) throws FileNotFoundException, IOException { - File file = new File(targetFile.toString()); - if (overwrite || !file.exists()) { - SpringIOUtils.copy(resource.getInputStream(), new FileOutputStream(file)); - } - } - - public void copyGrailsResources(Object destDir, Object pattern) throws FileNotFoundException, IOException { - copyGrailsResources(destDir, pattern, true); - } - // Copies a set of resources to a given directory. The set is specified - // by an Ant-style path-matching pattern. - public void copyGrailsResources(Object destDir, Object pattern, boolean overwrite) throws FileNotFoundException, IOException { - new File(destDir.toString()).mkdirs(); - Resource[] resources = resolveResources("classpath:"+pattern); - for (Resource resource : resources) { - if (resource.isReadable()) { - copyGrailsResource(destDir+"/"+resource.getFilename(),resource, overwrite); - } - } - } - - /** - * Resolves the value for a given property name. It first looks for a - * system property, then in the BuildSettings configuration, and finally - * uses the given default value if other options are exhausted. - */ - public Object getPropertyValue(String propName, Object defaultValue) { - // First check whether we have a system property with the given name. - Object value = System.getProperty(propName); - if (value != null) return value; - - // Now try the BuildSettings settings. - value = buildProps.get(propName); - - // Return the BuildSettings value if there is one, otherwise use the default. - return value != null ? value : defaultValue; - } - - public void updateMetadata(Metadata metadata, @SuppressWarnings("rawtypes") Map entries) { - for (Object key : entries.keySet()) { - final Object value = entries.get(key); - if (value != null) { - metadata.put(key, value.toString()); - } - } - - metadata.persist(); - } - - /** - * Modifies the application's metadata, as stored in the "application.properties" - * file. If it doesn't exist, the file is created. - */ - public void updateMetadata(@SuppressWarnings("rawtypes") Map entries) { - updateMetadata(Metadata.getCurrent(), entries); - } - - /** - * Reads a plugin.xml descriptor for the given plugin name - */ - public GPathResult readPluginXmlMetadata(String pluginName) throws Exception { - Resource pluginResource = pluginSettings.getPluginDirForName(pluginName); - if (pluginResource != null) { - File pluginDir = pluginResource.getFile(); - return createXmlSlurper().parse(new File(pluginDir, "plugin.xml")); - } - return null; - } - - /** - * Reads all installed plugin descriptors returning a list - */ - public List readAllPluginXmlMetadata() throws Exception{ - Resource[] allFiles = pluginSettings.getPluginXmlMetadata(); - List results = new ArrayList(); - for (Resource resource : allFiles) { - if (resource.exists()) { - results.add(createXmlSlurper().parse(resource.getFile())); - } - } - return results; - } - - public XmlSlurper createXmlSlurper() throws ParserConfigurationException, SAXException { - return SpringIOUtils.createXmlSlurper(); - } - /** - * Times the execution of a closure, which can include a target. For - * example, - * - * profile("compile", compile) - * - * where 'compile' is the target. - */ - public void profile(String name, Closure callable) { - if (enableProfile) { - long now = System.currentTimeMillis(); - GrailsConsole console = GrailsConsole.getInstance(); - console.addStatus("Profiling ["+name+"] start"); - - callable.call(); - long then = System.currentTimeMillis() - now; - console.addStatus("Profiling ["+name+"] finish. Took "+then+" ms"); - } - else { - callable.call(); - } - } - - public String makeRelative(String path) { - if (buildSettings != null && path != null) { - String absolutePath = buildSettings.getBaseDir().getAbsolutePath(); - if (path.startsWith(absolutePath)) { - return path.substring(absolutePath.length()+1); - } - } - return path; - } - - public String makeRelative(File file) { - return makeRelative(file.getAbsolutePath()); - } - - /** - * Exits the build immediately with a given exit code. - */ - public void exit(int code) { - if (buildEventListener != null) { - buildEventListener.triggerEvent("Exiting", code); - } - - // Prevent system.exit during unit/integration testing - if (System.getProperty("grails.cli.testing") != null || System.getProperty("grails.disable.exit") != null) { - throw new ScriptExitException(code); - } - GrailsConsole.getInstance().flush(); - System.exit(code); - } - - /** - * Interactive prompt that can be used by any part of the build. Echos - * the given message to the console and waits for user input that matches - * either 'y' or 'n'. Returns true if the user enters 'y', - * false otherwise. - */ - public boolean confirmInput(String message, String code ) { - if (code == null) code = "confirm.message"; - GrailsConsole grailsConsole = GrailsConsole.getInstance(); - if (!isInteractive) { - grailsConsole.error("Cannot ask for input when --non-interactive flag is passed. Please switch back to interactive mode."); - exit(1); - } - return "y".equalsIgnoreCase(grailsConsole.userInput(message, new String[] { "y","n" })); - } - - public boolean confirmInput(String message ) { - return confirmInput(message, "confirm.message"); - } - - // Note: the following only work if you also include _GrailsEvents. - public void logError( String message, Throwable t ) { - GrailsConsole.getInstance().error(message, t); - } - - public void logErrorAndExit( String message, Throwable t ) { - logError(message, t); - exit(1); - } - - public void makeApiAvailableToScripts(final Binding binding, final Object cla) { - final Method[] declaredMethods = cla.getClass().getDeclaredMethods(); - for (Method method : declaredMethods) { - final String name = method.getName(); - - final int modifiers = method.getModifiers(); - if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) { - binding.setVariable(name, new MethodClosure(cla, name)); - } - } - - PropertyDescriptor[] propertyDescriptors; - try { - propertyDescriptors = Introspector.getBeanInfo(cla.getClass()).getPropertyDescriptors(); - for (PropertyDescriptor pd : propertyDescriptors) { - final Method readMethod = pd.getReadMethod(); - if (readMethod != null) { - if (isDeclared(cla, readMethod)) { - binding.setVariable(pd.getName(), invokeMethod(readMethod, cla)); - } - } - } - } - catch (IntrospectionException e1) { - // ignore - } - } - - private Object invokeMethod(Method readMethod, Object cla) { - try { - return readMethod.invoke(cla); - } catch (IllegalAccessException e) { - return null; - } catch (InvocationTargetException e) { - return null; - } - } - - protected boolean isDeclared(final Object cla, final Method readMethod) { - try { - return cla.getClass().getDeclaredMethod(readMethod.getName(), - readMethod.getParameterTypes()) != null; - } - catch (Exception e) { - return false; - } - } -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProcess.groovy b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProcess.groovy deleted file mode 100644 index aff8bb580e4..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProcess.groovy +++ /dev/null @@ -1,973 +0,0 @@ -/* - * Copyright 2012 SpringSource - * - * 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 org.codehaus.groovy.grails.cli.fork - -import gant.Gant -import grails.build.logging.GrailsConsole -import grails.util.BuildSettings -import grails.util.BuildSettingsHolder -import grails.util.Environment -import grails.util.PluginBuildSettings -import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.cli.logging.GrailsConsoleErrorPrintStream -import org.codehaus.groovy.grails.cli.logging.GrailsConsolePrintStream -import org.codehaus.groovy.grails.cli.parsing.CommandLineParser -import grails.io.IOUtils - -import java.lang.reflect.Method - -import org.apache.commons.logging.Log -import org.codehaus.groovy.grails.cli.interactive.InteractiveMode -import org.codehaus.groovy.grails.cli.support.PluginPathDiscoverySupport - -/** - * Helper class for kicking off forked JVM processes, helpful in managing the setup and - * execution of the forked process. Subclasses should provided a static void main method. - * - * @author Graeme Rocher - * @since 2.2 - */ -abstract class ForkedGrailsProcess { - - public static final String DEBUG_FORK = "grails.debug.fork" - public static final String PARENT_PROCESS_PORT = "grails.fork.parent.process.port" - public static final int DEFAULT_DAEMON_PORT = 8091 - public static final String DEFAULT_DEBUG_ARGS = "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" - - int maxMemory = 1024 - int minMemory = 64 - int maxPerm = 256 - boolean debug = false - String debugArgs = DEFAULT_DEBUG_ARGS - boolean reloading = true - boolean forkReserve - boolean daemon - int daemonPort = DEFAULT_DAEMON_PORT - File reloadingAgent - List jvmArgs - URLClassLoader forkedClassLoader - ExecutionContext executionContext - String encoding = "UTF-8" - - private String resumeIndicatorName - - ForkedGrailsProcess() { - resumeIndicatorName = "${getClass().simpleName}-process-resume" - } - - @CompileStatic - void configure(Map forkConfig) { - final Map runSettings = (Map) forkConfig - runSettings.each { Map.Entry entry -> - try { - GroovyObject go = (GroovyObject) this - if (go.hasProperty(entry.key)) - go.setProperty(entry.getKey(),entry.getValue()) - } catch (MissingPropertyException e) { - // ignore - } - } - - executionContext.daemonPort = this.daemonPort - } - - - @CompileStatic - void startDaemon(Closure callable) { - - if (!isDaemonRunning()) { - def serverSocket = new ServerSocket(daemonPort) - try { - - Thread.start { - killAfterTimeout() - } - final currentOut = System.out - final currentErr = System.err - final grailsConsole = GrailsConsole.instance - final consoleOut = grailsConsole.out - final consoleErr = grailsConsole.err - - - while(true) { - final clientSocket = serverSocket.accept() - try { - try { - clientSocket.withStreams { InputStream sockIn, OutputStream sockOut -> - final outStream = new GrailsConsolePrintStream(sockOut) - final errStream = new GrailsConsoleErrorPrintStream(sockOut) - System.out = outStream - System.err = errStream - grailsConsole.out = new PrintStream(sockOut) - grailsConsole.err = new PrintStream(sockOut) - - - final contextFile = readLine(sockIn) - if (contextFile) { - if ("exit" == contextFile) { - System.exit(0) - } - else { - def loadedContext = readExecutionContext(contextFile) - if (loadedContext) { - this.executionContext = loadedContext - } else { - // Forked daemon is regarded as command when contextFile cannot be loaded. - executionContext.argsMap["params"] = contextFile.split(/\s/) - } - - callable.call(clientSocket) - } - } - } - } catch (Throwable e) { - GrailsConsole.instance.error("Error executing daemon: ${e.message}") - } - } - finally { - clientSocket.close() - System.out = currentOut - System.err = currentErr - grailsConsole.out = consoleOut - grailsConsole.err = consoleErr - - } - } - } catch (SocketException se) { - // ignore - } - } - - } - - boolean isDaemonRunning() { - try { - def clientSocket = new Socket("localhost", daemonPort) - clientSocket.withStreams { InputStream sockIn, OutputStream sockOut -> - sockOut << '\n' - sockOut.flush() - } - return true - } catch (SocketException e) { - return false - } - - } - - @CompileStatic - static String readLine(InputStream inputStream) { - def out = new ByteArrayOutputStream() - int ch - while ((ch = inputStream.read()) != -1) { - if (ch == '\n') { - break - } - out.write(ch) - } - return out.toString().trim() - } - - /** - * @return Whether this process is a reserve process. A reserve process is an additional JVM, bootstrapped and idle that can resume execution at a later date - */ - protected boolean isReserveProcess() { - System.getProperty("grails.fork.reserve")!=null - } - - /** - * @return Whether this process should be launched using a running daemon process. - */ - protected boolean isDaemonProcess() { - System.getProperty("grails.fork.daemon")!=null - } - - @CompileStatic - protected void discoverAndSetAgent(ExecutionContext executionContext) { - final jarFromContext = executionContext.agentJar - if (jarFromContext) { - setReloadingAgent(jarFromContext) - } - else { - try { - final agentClass = Thread.currentThread().contextClassLoader.loadClass('org.springsource.loaded.ReloadEventProcessorPlugin') - setReloadingAgent(findJarFile(agentClass)) - } catch (e) { - final grailsHome = executionContext.grailsHome - if (grailsHome && grailsHome.exists()) { - def agentHome = new File(grailsHome, "lib/org.springframework/springloaded/jars") - final agentJar = agentHome.listFiles().find { File f -> f.name.endsWith(".jar") && !f.name.contains('sources') && !f.name.contains('javadoc')} - if (agentJar) { - setReloadingAgent(agentJar) - } - } - } - } - } - - @CompileStatic - protected void waitForResume() { - // wait for resume indicator - def resumeDir = getResumeDir() - resumeDir.mkdirs() - startIdleKiller() - while (resumeDir.exists()) { - sleep(100) - } - } - - protected File getResumeDir() { - new File(executionContext.projectWorkDir, resumeIndicatorName) - } - - @CompileStatic - void killAfterTimeout() { - int idleTime = 1 * 60 // one hour - - try { - Thread.sleep(idleTime * 60 * 1000) // convert minutes to ms - } catch (e) { - return - } - - def lockDir = new File(executionContext.projectWorkDir, "process-lock") - if (lockDir.mkdir()) { - System.exit 0 - } else { - // someone is already connected; let the process finish - } - } - - @CompileStatic - private void startIdleKiller() { - def idleKiller = new Thread({ - killAfterTimeout() - } as Runnable) - - idleKiller.daemon = true - idleKiller.start() - } - - @CompileStatic - Process fork(Map argsMap = new LinkedHashMap()) { - ExecutionContext executionContext = getExecutionContext() - executionContext.argsMap = argsMap - if (reloading) { - discoverAndSetAgent(executionContext) - } - - final resumeDir = getResumeDir() - if (isForkingReserveEnabled() && resumeDir.exists()) { - resumeDir.delete() - sleep(100) - storeExecutionContext(executionContext) - forkReserve(executionContext) - } - else { - - boolean connectedToDaemon = false - if (shouldRunWithDaemon()) { - try { - final contextFile = storeExecutionContext(executionContext) - final daemonCmd = contextFile.absolutePath - runDaemonCommand(daemonCmd) - connectedToDaemon = true - } catch (SocketException e) { - connectedToDaemon = false - } - - } - if (!connectedToDaemon) { - if (daemon && !connectedToDaemon) { - GrailsConsole.instance.updateStatus("Running without daemon...") - } - - startParentAvailabilityServer() - - String classpathString = getBoostrapClasspath(executionContext) - List cmd = buildProcessCommand(executionContext, classpathString) - - - def processBuilder = new ProcessBuilder() - processBuilder - .directory(executionContext.getBaseDir()) - .redirectErrorStream(false) - .command(cmd) - - def process = processBuilder.start() - - if (isForkingReserveEnabled()) { - List reserveCmd = buildProcessCommand(executionContext, classpathString, true) - forkReserveProcess(reserveCmd, executionContext) - } - else if(shouldRunWithDaemon()) { - GrailsConsole.instance.updateStatus("Starting daemon...") - forkDaemon(executionContext) - } - - return attachOutputListener(process) - } - else { - return null - } - - } - } - - protected void startParentAvailabilityServer() { - if(System.getProperty(PARENT_PROCESS_PORT)) return - - ServerSocket parentAvailabilityServer = new ServerSocket(0) - def parentPort = parentAvailabilityServer.localPort - System.setProperty(PARENT_PROCESS_PORT, String.valueOf(parentPort)) - - - Thread.start { - while(!parentAvailabilityServer.isClosed()) { - try { - // simply accept and close the socket - parentAvailabilityServer.accept().close() - } catch (e) { - // ignore - } - } - } - Runtime.addShutdownHook { - try { - parentAvailabilityServer?.close() - } catch (e) { - // ignore - } - } - } - - @CompileStatic - protected void runDaemonCommand(String daemonCmd) { - def clientSocket = new Socket("localhost", daemonPort) - clientSocket.withStreams { InputStream sockIn, OutputStream sockOut -> - - sockOut << daemonCmd << '\n' - sockOut.flush() - - new TextDumper(sockIn).run() - } - } - - @CompileStatic - protected boolean shouldRunWithDaemon() { - // Whether the test runner daemon should be used. On Windows this is disabled as there are issues with regards to reading process output on Windows - daemon && InteractiveMode.active && !isDebugForkEnabled() && !isWindows() - } - - @CompileStatic - protected boolean isDebugForkEnabled() { - debug || Boolean.getBoolean(DEBUG_FORK) - } - - @CompileStatic - void forkReserve(ExecutionContext executionContext = getExecutionContext()) { - if (reloading) { - discoverAndSetAgent(executionContext) - } - - String classpathString = getBoostrapClasspath(executionContext) - List cmd = buildProcessCommand(executionContext, classpathString, true) - - forkReserveProcess(cmd, executionContext) - } - - @CompileStatic - void forkDaemon(ExecutionContext executionContext = getExecutionContext()) { - if (reloading) { - discoverAndSetAgent(executionContext) - } - - executionContext.daemonPort = daemonPort - String classpathString = getBoostrapClasspath(executionContext) - List cmd = buildProcessCommand(executionContext, classpathString, false, true) - - forkReserveProcess(cmd, executionContext) - } - - @CompileStatic - void restartDaemon(ExecutionContext executionContext = getExecutionContext()) { - if (reloading) { - discoverAndSetAgent(executionContext) - } - - startParentPortMonitor() - - final console = GrailsConsole.instance - console.updateStatus("Stopping daemon...") - while(isDaemonRunning()) { - runDaemonCommand("exit") - } - console.updateStatus("Starting daemon...") - forkDaemon(executionContext) - while(!isDaemonRunning()) { - console.indicateProgress() - } - console.updateStatus("Daemon Started") - } - - @CompileStatic - boolean isForkingReserveEnabled() { - return forkReserve && InteractiveMode.isActive() && !isDebugForkEnabled() && !daemon - } - - @CompileStatic - protected void forkReserveProcess(List cmd, ExecutionContext executionContext, boolean attachListener =true) { - final builder = new ProcessBuilder() - .directory(executionContext.getBaseDir()) - .redirectErrorStream(false) - .command(cmd) - - Thread.start { - - sleep 2000 - final p2 = builder.start() - - if (attachListener) { - attachOutputListener(p2) - } else { - ForkedProcessShutdownHooks.add(p2) - } - } - } - - @CompileStatic - protected Process attachOutputListener(Process process, boolean async = false) { - - ForkedProcessShutdownHooks.add(process) - - def is = process.inputStream - def es = process.errorStream - def t1 = new Thread(new TextDumper(is)) - def t2 = new Thread(new TextDumper(es)) - t1.start() - t2.start() - - def callable = { - int result = process.waitFor() - ForkedProcessShutdownHooks.remove(process) - if (result == 1) { - try { t1.join() } catch (InterruptedException ignore) {} - try { t2.join() } catch (InterruptedException ignore) {} - try { es.close() } catch (IOException ignore) {} - try { is.close() } catch (IOException ignore) {} - - GrailsConsole.instance.error("Forked Grails VM exited with error") - if(!InteractiveMode.active) { - System.exit(1) - } - } - } - - if (async) { - Thread.start callable - } - else { - callable.call() - } - - return process - } - - @CompileStatic - protected String getBoostrapClasspath(ExecutionContext executionContext) { - def cp = new StringBuilder() - def isWindows = isWindows() - for (File file : executionContext.getBuildDependencies()) { - if(isWindows) { - cp << URLDecoder.decode(file.canonicalPath, "UTF-8") << File.pathSeparator - } - else { - cp << file << File.pathSeparator - } - } - - cp.toString() - } - - @CompileStatic - protected boolean isWindows() { - return System.getProperty("os.name").toLowerCase().indexOf("windows") != -1 - } - - @CompileStatic - protected List buildProcessCommand(ExecutionContext executionContext, String classpathString, boolean isReserve = false, boolean isDaemon = false) { - String additionalClasspath = System.getProperty('GRAILS_ADDITIONAL_CLASSPATH') - if(additionalClasspath) { - classpathString = classpathString + File.pathSeparator + additionalClasspath - } - - File tempFile = storeExecutionContext(executionContext) - final javaHomeEnv = System.getenv("JAVA_HOME") - - def javaCommand - if (javaHomeEnv && !isWindows()) { - javaCommand = new File(javaHomeEnv, "bin/java").canonicalPath - } - else { - javaCommand = "java" // assume it is correctly configured using PATH - } - - List cmd = [javaCommand] - - if(encoding) { - cmd.add("-Dfile.encoding=${encoding}".toString()) - } - if (jvmArgs) { - cmd.addAll(jvmArgs) - } - - cmd.addAll(["-Xmx${maxMemory}M".toString(), "-Xms${minMemory}M".toString()]) - if(!(System.getProperty("java.version") =~ /1.[89]./)) { - cmd.add("-XX:MaxPermSize=${maxPerm}m".toString()) - } - def parentPort = System.getProperty(PARENT_PROCESS_PORT) - if(parentPort) { - cmd << "-D${PARENT_PROCESS_PORT}=${parentPort}".toString() - } - - cmd.addAll(["-Dgrails.fork.active=true", - "-Dgrails.build.execution.context=${tempFile.canonicalPath}".toString(), "-cp", classpathString]) - - if (isDebugForkEnabled() && !isReserve) { - cmd.addAll(["-Xdebug", "-Xnoagent", "-Dgrails.full.stacktrace=true", "-Djava.compiler=NONE"]) - cmd << (debugArgs ?: DEFAULT_DEBUG_ARGS) - } - final console = GrailsConsole.getInstance() - if (isReserve) { - cmd.add "-Dgrails.fork.reserve=true" - } - else if (isDaemon) { - cmd.add "-Dgrails.fork.daemon=true" - } - if (console.isVerbose()) { - cmd.add("-Dgrails.verbose=true") - cmd.add("-Dgrails.full.stacktrace=true") - } - if (console.isStacktrace()) { - cmd.add("-Dgrails.show.stacktrace=true") - } - cmd.add("-Dgrails.home=${executionContext.grailsHome.canonicalPath}".toString()) - if (reloadingAgent != null) { - cmd.addAll(["-javaagent:" + reloadingAgent.getCanonicalPath(), "-Xverify:none", "-Dspringloaded.synchronize=true", "-Djdk.reflect.allowGetCallerClass=true"]) - def cacheDir=System.getenv("GRAILS_AGENT_CACHE_DIR") ?: BuildSettingsHolder.settings.grailsWorkDir.canonicalPath - cmd.add("-Dspringloaded=profile=grails;cacheDir=${cacheDir}".toString()) - } - - cmd << getClass().name - - return cmd - } - - protected File storeExecutionContext(ExecutionContext executionContext) { - def baseName = executionContext.getBaseDir().canonicalFile.name - if (baseName.length() < 3) { - baseName+='ec' - } - File tempFile = File.createTempFile(baseName, "grails-execution-context") - - tempFile.deleteOnExit() - tempFile.delete() - - tempFile.withOutputStream { OutputStream fos -> - new ObjectOutputStream(fos).writeObject(executionContext) - } - tempFile - } - - @CompileStatic - ExecutionContext readExecutionContext() { - String location = System.getProperty("grails.build.execution.context") - - return readExecutionContext(location) - } - - @CompileStatic - protected ExecutionContext readExecutionContext(String location) { - if (location != null) { - final file = new File(location) - if (file.exists()) { - return (ExecutionContext) file.withInputStream { InputStream fis -> - def ois = new ObjectInputStream(fis) - ExecutionContext executionContext = (ExecutionContext) ois.readObject() - executionContext.process = this - this.daemonPort = executionContext.daemonPort - return executionContext - } - } - } - return null - } - - @CompileStatic - protected List buildMinimalIsolatedClasspath(BuildSettings buildSettings) { - List buildDependencies = [] - - File groovyJar = buildSettings.compileDependencies.find { File f -> f.name.contains "groovy-all" } - File toolsJar = findToolsJar() - - if (toolsJar?.exists()) { - buildDependencies.add(toolsJar) - } - - if (!groovyJar) { - groovyJar = findJarFile(GroovySystem) - } - - buildDependencies.add groovyJar - buildDependencies.add findJarFile(Log) - buildDependencies.add findJarFile(Gant) - - List bootstrapJars = [] - for (File f in buildSettings.runtimeDependencies) { - final fileName = f.name - if (fileName.contains('log4j') ) { - bootstrapJars.add(f) - } - } - for (File f in buildSettings.buildDependencies) { - final fileName = f.name - if (fileName.contains('grails-bootstrap') || - fileName.contains('slf4j-api') || - fileName.contains('ivy') || - fileName.matches(/^ant-.+$/) || - fileName.contains('ant-junit') || - fileName.contains('jline') || - fileName.contains('jansi') ) { - bootstrapJars.add(f) - } - } - - buildDependencies.addAll bootstrapJars - buildDependencies - } - - @CompileStatic - protected File findToolsJar() { - final javaHome = System.getenv("JAVA_HOME") - File toolsJar = javaHome ? new File(javaHome, "lib/tools.jar") : null - if (!toolsJar?.exists()) { - try { - final toolsClass = Thread.currentThread().getContextClassLoader().loadClass('sun.tools.native2ascii.Main') - toolsJar = findJarFile(toolsClass) - } catch (e) { - // ignore - } - } - toolsJar - } - - @CompileStatic - protected File findJarFile(Class targetClass) { - IOUtils.findJarFile(targetClass) - } - - @CompileStatic - Collection findSystemClasspathJars(BuildSettings buildSettings) { - return buildSettings.buildDependencies.findAll { File it -> it.name.contains("tomcat") } + - buildSettings.providedDependencies.findAll { File it -> it.name.contains("tomcat") } - } - - @CompileStatic - protected GroovyClassLoader createClassLoader(BuildSettings buildSettings) { - def classLoader = new GroovyClassLoader() - - if(Environment.current == Environment.TEST) { - for (File f in buildSettings.testDependencies) { - classLoader.addURL(f.toURI().toURL()) - } - - } - else { - for (File f in buildSettings.runtimeDependencies) { - classLoader.addURL(f.toURI().toURL()) - } - } - - - for (File f in buildSettings.providedDependencies) { - classLoader.addURL(f.toURI().toURL()) - } - - classLoader.addURL(buildSettings.classesDir.toURI().toURL()) - classLoader.addURL(buildSettings.pluginClassesDir.toURI().toURL()) - classLoader.addURL(buildSettings.pluginBuildClassesDir.toURI().toURL()) - classLoader.addURL(buildSettings.pluginProvidedClassesDir.toURI().toURL()) - if(Environment.current == Environment.TEST) { - classLoader.addURL(buildSettings.testClassesDir.toURI().toURL()) - } - classLoader.addURL(buildSettings.resourcesDir.toURI().toURL()) - - def pluginSupport = new PluginPathDiscoverySupport(buildSettings) - - for (File f in pluginSupport.listJarsInPluginLibs()) { - classLoader.addURL(f.toURI().toURL()) - } - - return classLoader - } - - /** - * - * @param classLoader - * @param buildSettings - */ - protected void setupReloading(URLClassLoader classLoader, BuildSettings buildSettings) { - Thread.start { - final holders = classLoader.loadClass("grails.util.Holders") - while(!holders.getPluginManager()) { - sleep(1000) - } - startProjectWatcher(classLoader, buildSettings) - } - - } - - protected void startProjectWatcher(URLClassLoader classLoader, BuildSettings buildSettings) { - try { - final projectCompiler = classLoader.loadClass("org.codehaus.groovy.grails.compiler.GrailsProjectCompiler").newInstance(new PluginBuildSettings(buildSettings), classLoader) - projectCompiler.configureClasspath() - final holders = classLoader.loadClass("grails.util.Holders") - final projectWatcher = classLoader.loadClass("org.codehaus.groovy.grails.compiler.GrailsProjectWatcher").newInstance(projectCompiler, holders.getPluginManager()) - projectWatcher.run() - } catch (e) { - e.printStackTrace() - println "WARNING: There was an error setting up reloading. Changes to classes will not be reflected: ${e.message}" - } - } - - @CompileStatic - protected URLClassLoader initializeClassLoader(BuildSettings buildSettings) { - URLClassLoader newClassLoader = createClassLoader(buildSettings) - if (forkedClassLoader && forkedClassLoader.URLs.toList().containsAll(newClassLoader.URLs.toList())) { - // If the existing class loader includes all URLs of new class loader, the existing one should be used. - // Otherwise a level of nested class loaders would become so deep that slow test causes. - return forkedClassLoader - } - forkedClassLoader = newClassLoader - return newClassLoader - } - - @CompileStatic - protected BuildSettings initializeBuildSettings(ExecutionContext ec) { - final sysProps = ec.systemProps - for(entry in sysProps.entrySet()) { - if (entry.value) { - System.setProperty(entry.key, entry.value) - } - } - def buildSettings = new BuildSettings(ec.grailsHome, ec.baseDir) - buildSettings.setDependenciesExternallyConfigured(true) - buildSettings.loadConfig() - buildSettings.setRuntimeDependencies(ec.runtimeDependencies) - buildSettings.setCompileDependencies(ec.runtimeDependencies) - buildSettings.setTestDependencies(ec.testDependencies) - buildSettings.setProvidedDependencies(ec.providedDependencies) - buildSettings.setBuildDependencies(ec.buildDependencies) - buildSettings.setForkSettings(ec.forkConfig) - - BuildSettingsHolder.settings = buildSettings - configureFork(buildSettings) - startParentPortMonitor() - - buildSettings - } - - protected void startParentPortMonitor() { - def parentProcessPort = System.getProperty(PARENT_PROCESS_PORT) - if (parentProcessPort) { - Thread.start { - def portInt = parentProcessPort.toInteger() - while (true) { - sleep(15000) - if (!isServerRunning(portInt)) { - // parent process killed, so bail out too - GrailsConsole.getInstance().addStatus("Parent process shutdown. Exiting...") - System.exit(1) - } - } - } - } - } - - /** - * @return Whether the server is running - */ - boolean isServerRunning(int port) { - Socket socket = null - try { - socket = new Socket("localhost", port) - return socket.isConnected() - } catch (e) { - return false - } - finally { - try { - socket?.close() - } catch (Throwable e) { - } - } - } - protected void configureFork(BuildSettings buildSettings) { - final runConfig = buildSettings.forkSettings.run - if (runConfig instanceof Map) - configure(runConfig) - } - - protected void initializeLogging(File grailsHome, ClassLoader classLoader) { - try { - Class cls = classLoader.loadClass("org.apache.log4j.PropertyConfigurator") - Method configure = cls.getMethod("configure", URL) - configure.setAccessible(true) - File f = new File(grailsHome.absolutePath + "/scripts/log4j.properties") - if(!f.exists()) { - f = new File(grailsHome.absolutePath + "/grails-scripts/src/main/scripts/log4j.properties") - } - if(f.exists()) { - configure.invoke(cls, f.toURI().toURL()) - } - } catch (Throwable e) { - println("Log4j was not found on the classpath and will not be used for command line logging. Cause "+e.getClass().getName()+": " + e.getMessage()) - } - } - - @CompileStatic - static class TextDumper implements Runnable { - InputStream input - - TextDumper(InputStream input) { - this.input = input - } - - void run() { - try { - def isr = new InputStreamReader(input, "UTF-8") - new BufferedReader(isr).eachLine { String next -> - if (next) { - GrailsConsole.getInstance().log(next) - } - } - } catch (IOException e) { - // ignore, probably due to an interrupt - } - } - } -} - -@CompileStatic -class ExecutionContext implements Serializable { - - private static final long serialVersionUID = 1 - - List runtimeDependencies - List buildDependencies - List providedDependencies - List testDependencies - - File grailsWorkDir - File projectWorkDir - File classesDir - File testClassesDir - File resourcesDir - File projectPluginsDir - File baseDir - File agentJar - - String env - File grailsHome - Map systemProps = [:] - Map forkConfig = [:] - Map argsMap = new LinkedHashMap() - int daemonPort = ForkedGrailsProcess.DEFAULT_DAEMON_PORT - - transient ForkedGrailsProcess process - - ExecutionContext() { - // empty constructor for deserialization - } - - ExecutionContext(ForkedGrailsProcess process) { - this.process = process - this.daemonPort = process.daemonPort - } - - void initialize(BuildSettings settings) { - List isolatedBuildDependencies = buildMinimalIsolatedClasspath(settings) - for( prop in System.properties.keySet() ) { - String p = prop.toString() - if(p.startsWith("grails.")) { - final value = System.properties.get(prop) - if (value) - systemProps[p] = value.toString() - } - } - final commandLine = CommandLineParser.getCurrentCommandLine() - if (commandLine) { - final commandLineSystemProperties = commandLine.systemProperties - for(prop in commandLineSystemProperties.keySet()) { - String p = prop.toString() - final value = commandLineSystemProperties.get(prop) - if (value) - systemProps[p] = value.toString() - - } - } - - buildDependencies = isolatedBuildDependencies - - runtimeDependencies = new ArrayList<>(settings.runtimeDependencies) - def projectApiJar = settings.buildDependencies.find { File f -> f.name.contains('grails-project-api')} - runtimeDependencies.add projectApiJar - runtimeDependencies.addAll settings.pluginRuntimeDependencies - runtimeDependencies.addAll settings.applicationJars - providedDependencies = new ArrayList<>(settings.providedDependencies) - providedDependencies.addAll settings.pluginProvidedDependencies - testDependencies = new ArrayList<>(settings.testDependencies) - testDependencies.addAll settings.pluginTestDependencies - baseDir = settings.baseDir - env = Environment.current.name - grailsHome = settings.grailsHome - classesDir = settings.classesDir - grailsWorkDir = settings.grailsWorkDir - projectWorkDir = settings.projectWorkDir - projectPluginsDir = settings.projectPluginsDir - testClassesDir = settings.testClassesDir - final currentForkConfig = (Map) settings.getForkSettings() - currentForkConfig.each { key, value -> - def forkConf - if(value instanceof Boolean) { - forkConf = value - } - else if (value instanceof Map) { - forkConf = [:] + (Map)value - } - forkConfig[key] = forkConf - } - - final agentReport = settings.dependencyManager.resolveAgent() - if(agentReport && agentReport.jarFiles) { - agentJar = agentReport.jarFiles[0] - } - } - - @CompileStatic - protected List buildMinimalIsolatedClasspath(BuildSettings buildSettings) { - return process.buildMinimalIsolatedClasspath(buildSettings) - } -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProcessConfig.groovy b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProcessConfig.groovy deleted file mode 100644 index 9214073671a..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProcessConfig.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2012 SpringSource - * - * 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 org.codehaus.groovy.grails.cli.fork - -import groovy.transform.CompileStatic - -/** - * Configuration for a forked process - * - * @author Graeme Rocher - * @since 2.3 - */ -@CompileStatic -class ForkedGrailsProcessConfig { - - ForkedGrailsProcessConfig(config) { - if (config instanceof Map) { - forked = true - def map = (Map)config - - if (map.maxMemory) { - maxMemory = map.maxMemory.toString().toInteger() - } - if (map.minMemory) { - minMemory = map.minMemory.toString().toInteger() - } - if (map.maxPerm) { - maxPerm = map.maxPerm.toString().toInteger() - } - if (map.debug) { - debug = true - } - } - else if (config) { - forked = true - } - } - - ForkedGrailsProcessConfig() { - } - - Integer maxMemory = 512 - Integer minMemory = 64 - boolean debug = false - Integer maxPerm = 256 - boolean forked = false - - Map asMap() { - [maxMemory:maxMemory, minMemory:minMemory, debug:debug, maxPerm:maxPerm] - } -} diff --git a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProjectClassExecutor.groovy b/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProjectClassExecutor.groovy deleted file mode 100644 index 664c65a937a..00000000000 --- a/grails-bootstrap/src/main/groovy/org/codehaus/groovy/grails/cli/fork/ForkedGrailsProjectClassExecutor.groovy +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2012 SpringSource - * - * 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 org.codehaus.groovy.grails.cli.fork - -import grails.build.logging.GrailsConsole -import grails.util.BuildSettings -import grails.util.PluginBuildSettings -import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode - -import org.codehaus.groovy.grails.cli.support.GrailsBuildEventListener -import org.codehaus.groovy.grails.cli.support.ScriptBindingInitializer - -/** - * Base class that deals with the setup logic needed to run a Grails build system component - * (GrailsProjectCompiler, GrailsProjectLoader, GrailsProjectRunner etc.) in a forked process. - * - * @author Graeme Rocher - * @since 2.3 - */ -@CompileStatic -abstract class ForkedGrailsProjectClassExecutor extends ForkedGrailsProcess { - - ForkedGrailsProjectClassExecutor(BuildSettings buildSettings) { - executionContext = createExecutionContext() - executionContext.initialize(buildSettings) - } - - protected ExecutionContext createExecutionContext() { - new ExecutionContext(this) - } - - protected ForkedGrailsProjectClassExecutor() { - executionContext = readExecutionContext() - if (executionContext == null) { - throw new IllegalStateException("Forked process created without first creating execution context and calling fork()") - } - } - - protected final int run() { - ExpandoMetaClass.enableGlobally() - - if (isDaemonProcess()) { - startDaemon { cmd -> - def projectClassInstance = initializeProjectInstance() - runInstance(projectClassInstance) - } - return 0 - } - else if (isReserveProcess()) { - // don't wait if the resume directory already exists, another process exists - if (!resumeDir.exists()) { - executionContext = readExecutionContext() - Object projectClassInstance = initializeProjectInstance() - waitForResume() - return runInstance(projectClassInstance) - } - } - else { - Object projectClassInstance = initializeProjectInstance() - return runInstance(projectClassInstance) - } - } - - protected Object initializeProjectInstance() { - ExecutionContext ec = executionContext - BuildSettings buildSettings = initializeBuildSettings(ec) - URLClassLoader classLoader = initializeClassLoader(buildSettings) - initializeLogging(ec.grailsHome, classLoader) - Thread.currentThread().setContextClassLoader(classLoader) - - final projectComponentClass = classLoader.loadClass(getProjectClassType()) - final projectClassInstance = createInstance(projectComponentClass, buildSettings) - projectClassInstance - } - - protected Object createInstance(Class projectComponentClass, BuildSettings buildSettings) { - projectComponentClass.newInstance(buildSettings) - } - - protected GrailsBuildEventListener createEventListener(Binding executionContext) { - GrailsBuildEventListener eventListener = (GrailsBuildEventListener) executionContext.getVariable("eventListener") - GrailsConsole grailsConsole = GrailsConsole.getInstance() - eventListener.globalEventHooks = [ - StatusFinal: [ {message -> grailsConsole.addStatus message.toString() } ], - StatusUpdate: [ {message -> grailsConsole.updateStatus message.toString() } ], - StatusError: [ {message -> grailsConsole.error message.toString() } ] - ] - - eventListener.initialize() - addEventHookToBinding(executionContext, eventListener) - eventListener - } - - @CompileStatic(TypeCheckingMode.SKIP) - private void addEventHookToBinding(Binding executionContext, eventListener) { - executionContext.setVariable("event", { String name, List args -> - eventListener.triggerEvent(name, * args) - }) - } - - protected Binding createExecutionContext(BuildSettings buildSettings, PluginBuildSettings pluginSettings) { - final scriptBinding = new Binding() - ScriptBindingInitializer.initBinding(scriptBinding, buildSettings, (URLClassLoader) forkedClassLoader, GrailsConsole.getInstance(), false) - scriptBinding.setVariable('includeTargets', new IncludeTargets(forkedClassLoader,scriptBinding)) - scriptBinding.setVariable("pluginSettings", pluginSettings) - scriptBinding.setVariable("target") { Map arguments, Closure task -> - scriptBinding.setVariable(arguments.name, task) - } - scriptBinding.setVariable(ScriptBindingInitializer.GRAILS_SETTINGS, buildSettings) - scriptBinding.setVariable(ScriptBindingInitializer.ARGS_MAP, executionContext.argsMap) - scriptBinding - } - - protected abstract String getProjectClassType() - - abstract int runInstance(instance) -} - -@CompileStatic -class IncludeTargets { - ClassLoader classLoader - Binding binding - - private Set loadedClasses = [] - - IncludeTargets(ClassLoader classLoader, Binding binding) { - this.classLoader = classLoader - this.binding = binding - } - /** - * Implementation of the << operator taking a Class parameter. - * - * @param theClass The Class to load and instantiate. - * @return The includer object to allow for << chaining. - */ - def leftShift ( final Class