Java tutorial
/* * Copyright 2007-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 org.gradle.api.internal.project; import groovy.lang.MissingPropertyException; import groovy.lang.Script; import groovy.util.AntBuilder; import org.apache.commons.lang.StringUtils; import org.gradle.api.*; import org.gradle.api.internal.BeanDynamicObject; import org.gradle.api.internal.BuildInternal; import org.gradle.api.internal.DynamicObject; import org.gradle.api.internal.DynamicObjectHelper; import org.gradle.api.internal.artifacts.DependencyManagerFactory; import org.gradle.api.internal.tasks.DefaultTaskEngine; import org.gradle.api.internal.tasks.TaskEngine; import org.gradle.api.invocation.Build; import org.gradle.api.logging.LogLevel; import org.gradle.api.plugins.Convention; import org.gradle.api.tasks.Directory; import org.gradle.api.tasks.util.BaseDirConverter; import org.gradle.groovy.scripts.ScriptSource; import org.gradle.util.Clock; import org.gradle.util.GUtil; import org.gradle.util.PathHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; /** * @author Hans Dockter */ public abstract class AbstractProject implements ProjectInternal { private static Logger logger = LoggerFactory.getLogger(AbstractProject.class); private static Logger buildLogger = LoggerFactory.getLogger(Project.class); private Project rootProject; private BuildInternal build; private BuildScriptProcessor buildScriptProcessor; private ClassLoader buildScriptClassLoader; private String buildFileName; private Script buildScript; private ScriptSource buildScriptSource; private PluginRegistry pluginRegistry; private File projectDir; private ProjectInternal parent; private String name; private Object group = DEFAULT_GROUP; private Object version = DEFAULT_VERSION; private Map<String, Project> childProjects = new HashMap<String, Project>(); private List<String> defaultTasks = new ArrayList<String>(); private Set<Project> dependsOnProjects = new HashSet<Project>(); private State state; private List<Plugin> plugins = new ArrayList<Plugin>(); private BaseDirConverter baseDirConverter = new BaseDirConverter(); private AntBuilderFactory antBuilderFactory; private AntBuilder ant = null; private DependencyManager dependencies; private String archivesTaskBaseName; private String archivesBaseName; private String buildDirName = Project.DEFAULT_BUILD_DIR_NAME; private Set<Class<? extends Plugin>> appliedPlugins = new HashSet<Class<? extends Plugin>>(); private String path = null; private int depth = 0; private TaskEngine taskEngine = new DefaultTaskEngine(); private ITaskFactory taskFactory; private IProjectRegistry projectRegistry; private DependencyManagerFactory dependencyManagerFactory; private List<AfterEvaluateListener> afterEvaluateListeners = new ArrayList<AfterEvaluateListener>(); private StandardOutputRedirector standardOutputRedirector = new DefaultStandardOutputRedirector(); private DynamicObjectHelper dynamicObjectHelper; public AbstractProject(String name) { this.name = name; dynamicObjectHelper = new DynamicObjectHelper(this); dynamicObjectHelper.setConvention(new Convention()); } public AbstractProject(String name, ProjectInternal parent, File projectDir, String buildFileName, ScriptSource buildScriptSource, ClassLoader buildScriptClassLoader, ITaskFactory taskFactory, DependencyManagerFactory dependencyManagerFactory, AntBuilderFactory antBuilderFactory, BuildScriptProcessor buildScriptProcessor, PluginRegistry pluginRegistry, IProjectRegistry projectRegistry, BuildInternal build) { assert name != null; this.rootProject = parent != null ? parent.getRootProject() : this; this.projectDir = projectDir; this.parent = parent; this.name = name; this.buildFileName = buildFileName; this.buildScriptClassLoader = buildScriptClassLoader; this.taskFactory = taskFactory; this.dependencyManagerFactory = dependencyManagerFactory; this.dependencies = dependencyManagerFactory.createDependencyManager(this, build.getGradleUserHomeDir()); this.antBuilderFactory = antBuilderFactory; this.buildScriptProcessor = buildScriptProcessor; this.pluginRegistry = pluginRegistry; this.projectRegistry = projectRegistry; this.state = State.CREATED; this.archivesTaskBaseName = Project.DEFAULT_ARCHIVES_TASK_BASE_NAME; this.archivesBaseName = name; this.buildScriptSource = buildScriptSource; this.build = build; if (parent == null) { path = Project.PATH_SEPARATOR; } else { path = parent.absolutePath(name); } dynamicObjectHelper = new DynamicObjectHelper(this); dynamicObjectHelper.setConvention(new Convention()); if (parent != null) { dynamicObjectHelper.setParent(parent.getInheritedScope()); } dynamicObjectHelper.addObject(taskEngine, DynamicObjectHelper.Location.AfterConvention); if (parent != null) { depth = parent.getDepth() + 1; } projectRegistry.addProject(this); } public String getRelativeFilePath() { return "/" + rootProject.getName() + "/" + path.substring(1).replace(Project.PATH_SEPARATOR, "/"); } public Project getRootProject() { return rootProject; } public void setRootProject(Project rootProject) { this.rootProject = rootProject; } public Build getBuild() { return build; } public void setBuild(BuildInternal build) { this.build = build; } public BuildScriptProcessor getBuildScriptProcessor() { return buildScriptProcessor; } public void setBuildScriptProcessor(BuildScriptProcessor buildScriptProcessor) { this.buildScriptProcessor = buildScriptProcessor; } public ClassLoader getBuildScriptClassLoader() { return buildScriptClassLoader; } public void setBuildScriptClassLoader(ClassLoader buildScriptClassLoader) { this.buildScriptClassLoader = buildScriptClassLoader; } public String getBuildFileName() { return buildFileName; } public String getBuildFileClassName() { return buildScriptSource.getClassName(); } public void setBuildFileName(String buildFileName) { this.buildFileName = buildFileName; } public Script getBuildScript() { return buildScript; } public void setBuildScript(Script buildScript) { this.buildScript = buildScript; dynamicObjectHelper.addObject(new BeanDynamicObject(buildScript).withNoProperties(), DynamicObjectHelper.Location.BeforeConvention); } public ScriptSource getBuildScriptSource() { return buildScriptSource; } public void setBuildScriptSource(ScriptSource buildScriptSource) { this.buildScriptSource = buildScriptSource; } public PluginRegistry getPluginRegistry() { return pluginRegistry; } public void setPluginRegistry(PluginRegistry pluginRegistry) { this.pluginRegistry = pluginRegistry; } public File getRootDir() { return rootProject.getProjectDir(); } public ProjectInternal getParent() { return parent; } public void setParent(ProjectInternal parent) { this.parent = parent; dynamicObjectHelper.setParent(parent == null ? null : parent.getInheritedScope()); } public DynamicObjectHelper getDynamicObjectHelper() { return dynamicObjectHelper; } public DynamicObject getInheritedScope() { return dynamicObjectHelper.getInheritable(); } public String getName() { return name; } public Object getGroup() { return group; } public void setGroup(Object group) { this.group = group; } public Object getVersion() { return version; } public void setVersion(Object version) { this.version = version; } public Map<String, Project> getChildProjects() { return childProjects; } public void setChildProjects(Map<String, Project> childProjects) { this.childProjects = childProjects; } public List<String> getDefaultTasks() { return defaultTasks; } public void setDefaultTasks(List<String> defaultTasks) { this.defaultTasks = defaultTasks; } public Set<Project> getDependsOnProjects() { return dependsOnProjects; } public void setDependsOnProjects(Set<Project> dependsOnProjects) { this.dependsOnProjects = dependsOnProjects; } public Map<String, Object> getAdditionalProperties() { return dynamicObjectHelper.getAdditionalProperties(); } public void setAdditionalProperties(Map<String, Object> additionalProperties) { dynamicObjectHelper.setAdditionalProperties(additionalProperties); } public State getState() { return state; } public void setState(State state) { this.state = state; } public List<Plugin> getPlugins() { return plugins; } public void setPlugins(List<Plugin> plugins) { this.plugins = plugins; } public BaseDirConverter getBaseDirConverter() { return baseDirConverter; } public void setBaseDirConverter(BaseDirConverter baseDirConverter) { this.baseDirConverter = baseDirConverter; } public void setAnt(AntBuilder ant) { this.ant = ant; } public DependencyManager getDependencies() { return dependencies; } public void setDependencies(DependencyManager dependencies) { this.dependencies = dependencies; } public String getArchivesTaskBaseName() { return archivesTaskBaseName; } public void setArchivesTaskBaseName(String archivesTaskBaseName) { this.archivesTaskBaseName = archivesTaskBaseName; } public String getBuildDirName() { return buildDirName; } public void setBuildDirName(String buildDirName) { this.buildDirName = buildDirName; } public Convention getConvention() { return dynamicObjectHelper.getConvention(); } public void setConvention(Convention convention) { dynamicObjectHelper.setConvention(convention); } public Set<Class<? extends Plugin>> getAppliedPlugins() { return appliedPlugins; } public void setAppliedPlugins(Set<Class<? extends Plugin>> appliedPlugins) { this.appliedPlugins = appliedPlugins; } public String getPath() { return path; } public int getDepth() { return depth; } public String getArchivesBaseName() { return archivesBaseName; } public void setArchivesBaseName(String archivesBaseName) { this.archivesBaseName = archivesBaseName; } public ITaskFactory getTaskFactory() { return taskFactory; } public void setTaskFactory(ITaskFactory taskFactory) { this.taskFactory = taskFactory; } public IProjectRegistry getProjectRegistry() { return projectRegistry; } public void setProjectRegistry(IProjectRegistry projectRegistry) { this.projectRegistry = projectRegistry; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AbstractProject that = (AbstractProject) o; if (!path.equals(that.path)) return false; return true; } @Override public int hashCode() { return path.hashCode(); } public int depthCompare(Project otherProject) { return new Integer(getDepth()).compareTo(otherProject.getDepth()); } public int compareTo(Project otherProject) { int depthCompare = depthCompare(otherProject); if (depthCompare == 0) { return path.compareTo(otherProject.getPath()); } else { return depthCompare; } } public String absolutePath(String path) { if (!isAbsolutePath(path)) { String prefix = this == rootProject ? "" : Project.PATH_SEPARATOR; return this.path + prefix + path; } return path; } public static boolean isAbsolutePath(String path) { return PathHelper.isAbsolutePath(path); } public Project project(String path) { Project project = findProject(path); if (project == null) { throw new UnknownProjectException( String.format("Project with path '%s' could not be found in %s.", path, this)); } return project; } public Project findProject(String path) { if (!GUtil.isTrue(path)) { throw new InvalidUserDataException("A path must be specified!"); } return projectRegistry.getProject(isAbsolutePath(path) ? path : absolutePath(path)); } public Set<Project> getAllprojects() { return projectRegistry.getAllProjects(this.path); } public Set<Project> getSubprojects() { return projectRegistry.getSubProjects(this.path); } public void subprojects(ProjectAction action) { applyActions(getSubprojects(), action); } public void allprojects(ProjectAction action) { applyActions(getAllprojects(), action); } public void applyActions(Set<Project> projects, ProjectAction action) { for (Project project : projects) { action.execute(project); } } public AntBuilder getAnt() { if (ant == null) { ant = createAntBuilder(); } return ant; } public AntBuilder createAntBuilder() { return antBuilderFactory.createAntBuilder(); } /** * This method is used when scripts access the project via project.x */ public Project getProject() { return this; } public AbstractProject evaluate() { if (state == State.INITIALIZED) { return this; } Clock clock = new Clock(); state = State.INITIALIZING; setBuildScript(buildScriptProcessor.createScript(this)); try { standardOutputRedirector.on(LogLevel.QUIET); buildScript.run(); standardOutputRedirector.flush(); } catch (Throwable t) { standardOutputRedirector.flush(); throw new GradleScriptException(String.format("A problem occurred evaluating %s.", this), t, getBuildScriptSource()); } logger.debug("Timing: Running the build script took " + clock.getTime()); state = State.INITIALIZED; notifyAfterEvaluateListener(); logger.info("Project= " + path + " evaluated."); logger.debug("Timing: Project evaluation took " + clock.getTime()); return this; } private void notifyAfterEvaluateListener() { for (AfterEvaluateListener afterEvaluateListener : afterEvaluateListeners) { afterEvaluateListener.afterEvaluate(this); } } public Project usePlugin(String pluginName) { return usePlugin(pluginName, new HashMap<String, Object>()); } public Project usePlugin(String pluginName, Map<String, ?> customValues) { if (usePluginInternal(pluginRegistry.getPlugin(pluginName), customValues) == null) { throw new InvalidUserDataException("Plugin with id " + pluginName + " can not be found!"); } return this; } public Project usePlugin(Class<? extends Plugin> pluginClass) { return usePlugin(pluginClass, new HashMap<String, Object>()); } public Project usePlugin(Class<? extends Plugin> pluginClass, Map<String, ?> customValues) { if (usePluginInternal(pluginRegistry.getPlugin(pluginClass), customValues) == null) { throw new InvalidUserDataException("Plugin class " + pluginClass + " can not be found!"); } return this; } private Plugin usePluginInternal(Plugin plugin, Map<String, ?> customValues) { if (plugin == null) { return null; } pluginRegistry.apply(plugin.getClass(), this, customValues); plugins.add(plugin); return plugin; } public Task findTask(String path) { if (!GUtil.isTrue(path)) { throw new InvalidUserDataException("A path must be specified!"); } if (!path.contains(PATH_SEPARATOR)) { return taskEngine.findTask(path); } String projectPath = StringUtils.substringBeforeLast(path, PATH_SEPARATOR); Project project = findProject(!GUtil.isTrue(projectPath) ? PATH_SEPARATOR : projectPath); if (project == null) { return null; } return project.task(StringUtils.substringAfterLast(path, PATH_SEPARATOR)); } public Map<String, Task> getTasks() { return (Map<String, Task>) taskEngine.getProperties(); } public Task task(String path) { Task task = findTask(path); if (task == null) { throw new UnknownTaskException( String.format("Task with path '%s' could not be found in %s.", path, this)); } return task; } public void defaultTasks(String... defaultTasks) { if (defaultTasks == null) { throw new InvalidUserDataException("Default tasks must not be null!"); } this.defaultTasks = new ArrayList<String>(); for (String defaultTask : defaultTasks) { if (defaultTask == null) { throw new InvalidUserDataException("Default tasks must not be null!"); } this.defaultTasks.add(defaultTask); } } public Task createTask(String name) { return createTask(new HashMap<String, Object>(), name, (TaskAction) null); } public Task createTask(Map<String, ?> args, String name) { return createTask(args, name, (TaskAction) null); } public Task createTask(String name, TaskAction action) { return createTask(new HashMap<String, Object>(), name, action); } public Task createTask(Map args, String name, TaskAction action) { Task task = taskFactory.createTask(this, getTasks(), args, name); taskEngine.addTask(task); if (action != null) { task.doFirst(action); } return task; } public void addChildProject(ProjectInternal childProject) { childProjects.put(childProject.getName(), childProject); } public File getProjectDir() { return projectDir; } public void setProjectDir(File projectDir) { this.projectDir = projectDir; } public File getBuildDir() { return new File(getProjectDir(), buildDirName); } public void dependsOn(String path) { dependsOn(path, true); } public void dependsOn(String path, boolean evaluateDependsOnProject) { if (!GUtil.isTrue(path)) { throw new InvalidUserDataException("You must specify a project!"); } dependsOnProjects.add(project(path)); if (evaluateDependsOnProject) { evaluationDependsOn(path); } } public Project evaluationDependsOn(String path) { if (!GUtil.isTrue(path)) { throw new InvalidUserDataException("You must specify a project!"); } DefaultProject projectToEvaluate = (DefaultProject) project(path); if (projectToEvaluate.getState() == State.INITIALIZING) { throw new CircularReferenceException( String.format("Circular referencing during evaluation for %s.", projectToEvaluate)); } return projectToEvaluate.evaluate(); } public Project childrenDependOnMe() { for (Project project : childProjects.values()) { project.dependsOn(this.path, false); } return this; } public Project dependsOnChildren() { return dependsOnChildren(false); } public Project dependsOnChildren(boolean evaluateDependsOnProject) { for (Project project : childProjects.values()) { dependsOn(project.getPath(), evaluateDependsOnProject); } return this; } public String toString() { if (parent != null) { return String.format("project '%s'", path); } else { return String.format("root project '%s'", name); } } public Map<Project, Set<Task>> getAllTasks(boolean recursive) { final Map<Project, Set<Task>> foundTargets = new TreeMap<Project, Set<Task>>(); ProjectAction action = new ProjectAction() { public void execute(Project project) { foundTargets.put(project, new TreeSet<Task>(project.getTasks().values())); } }; if (recursive) { allprojects(action); } else { action.execute(this); } return foundTargets; } public Set<Task> getTasksByName(final String name, boolean recursive) { if (!GUtil.isTrue(name)) { throw new InvalidUserDataException("Name is not specified!"); } final Set<Task> foundTasks = new HashSet<Task>(); ProjectAction action = new ProjectAction() { public void execute(Project project) { if (project.findTask(name) != null) { foundTasks.add(project.getTasks().get(name)); } } }; if (recursive) { allprojects(action); } else { action.execute(this); } return foundTasks; } public File file(Object path) { return file(path, PathValidation.NONE); } public File file(Object path, PathValidation validation) { return baseDirConverter.baseDir(path.toString(), getProjectDir(), validation); } public File relativePath(Object path) { File result = findRelativePath(path); if (result == null) { throw new GradleException("Path = " + path + " is not a subdirectory of the project root dir."); } return result; } public File findRelativePath(Object path) { File file = new File(path.toString()); if (!file.isAbsolute()) { return file; } File loopFile = file; String relativePath = ""; while (loopFile != null) { if (loopFile.equals(getProjectDir())) { break; } relativePath = loopFile.getName() + "/" + relativePath; loopFile = loopFile.getParentFile(); } return loopFile == null ? null : new File(relativePath); } public Task dir(String path) { String[] pathElements = path.split("/"); String name = ""; for (String pathElement : pathElements) { name += name.length() != 0 ? "/" + pathElement : pathElement; if (taskEngine.findTask(name) != null) { if (!(taskEngine.findTask(name) instanceof Directory)) { throw new InvalidUserDataException("A non directory task with this name already exsists."); } } else { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("type", Directory.class); createTask(map, name); } } return task(path); } public TaskEngine getTaskEngine() { return taskEngine; } public void setTaskEngine(TaskEngine taskEngine) { this.taskEngine = taskEngine; } public AntBuilderFactory getAntBuilderFactory() { return antBuilderFactory; } public void setAntBuilderFactory(AntBuilderFactory antBuilderFactory) { this.antBuilderFactory = antBuilderFactory; } public DependencyManagerFactory getDependencyManagerFactory() { return dependencyManagerFactory; } public void setDependencyManagerFactory(DependencyManagerFactory dependencyManagerFactory) { this.dependencyManagerFactory = dependencyManagerFactory; } public List<AfterEvaluateListener> getAfterEvaluateListeners() { return afterEvaluateListeners; } public AfterEvaluateListener addAfterEvaluateListener(AfterEvaluateListener afterEvaluateListener) { afterEvaluateListeners.add(afterEvaluateListener); return afterEvaluateListener; } public Logger getLogger() { return buildLogger; } public StandardOutputRedirector getStandardOutputRedirector() { return standardOutputRedirector; } public void setStandardOutputRedirector(StandardOutputRedirector standardOutputRedirector) { this.standardOutputRedirector = standardOutputRedirector; } public void disableStandardOutputCapture() { standardOutputRedirector.flush(); standardOutputRedirector.off(); } public void captureStandardOutput(LogLevel level) { standardOutputRedirector.on(level); } public Object property(String propertyName) throws MissingPropertyException { return dynamicObjectHelper.getProperty(propertyName); } public boolean hasProperty(String propertyName) { return dynamicObjectHelper.hasProperty(propertyName); } public Map<String, ?> getProperties() { return dynamicObjectHelper.getProperties(); } public Rule addRule(Rule rule) { return taskEngine.addRule(rule); } public List<Rule> getRules() { return taskEngine.getRules(); } }