| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.easyant.tasks; |
| |
| import org.apache.easyant.core.BuildConfigurationHelper; |
| import org.apache.easyant.core.EasyAntConstants; |
| import org.apache.easyant.core.EasyAntMagicNames; |
| import org.apache.easyant.core.descriptor.*; |
| import org.apache.easyant.core.ivy.InheritableScope; |
| import org.apache.easyant.core.ivy.IvyInstanceHelper; |
| import org.apache.easyant.core.parser.DefaultEasyAntXmlModuleDescriptorParser; |
| import org.apache.easyant.core.parser.EasyAntModuleDescriptorParser; |
| import org.apache.ivy.ant.IvyConfigure; |
| import org.apache.ivy.ant.IvyDependency; |
| import org.apache.ivy.ant.IvyInfo; |
| import org.apache.ivy.core.IvyContext; |
| import org.apache.ivy.core.cache.EasyAntRepositoryCacheManager; |
| import org.apache.ivy.core.cache.EasyantResolutionCacheManager; |
| import org.apache.ivy.core.module.id.ModuleRevisionId; |
| import org.apache.ivy.plugins.parser.ModuleDescriptorParser; |
| import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry; |
| import org.apache.ivy.plugins.repository.url.URLResource; |
| import org.apache.ivy.util.StringUtils; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.taskdefs.ImportTask; |
| |
| import java.io.File; |
| import java.net.MalformedURLException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| /** |
| * This task is the main class, used to parse module.ivy and execute the all the statement behind the easyant tag. |
| */ |
| public class LoadModule extends AbstractEasyAntTask { |
| |
| private File buildFile; |
| private File buildModule; |
| private String easyAntMDParserClassName; |
| private Boolean useBuildRepository; |
| |
| /** |
| * Get the file name that will be loaded |
| * |
| * @return a file that represents a module descriptor |
| */ |
| public File getBuildModule() { |
| return buildModule; |
| } |
| |
| /** |
| * set the file name that will be loaded |
| * |
| * @param file represents a module descriptor |
| */ |
| public void setBuildModule(File file) { |
| this.buildModule = file; |
| } |
| |
| public File getBuildFile() { |
| return buildFile; |
| } |
| |
| public void setBuildFile(File buildFile) { |
| this.buildFile = buildFile; |
| } |
| |
| public void setUseBuildRepository(boolean value) { |
| this.useBuildRepository = value; |
| } |
| |
| /** |
| * Set the classname of the easyant parser you want to use |
| * |
| * @param easyAntMDParserClassName |
| */ |
| public void setEasyAntMDParserClassName(String easyAntMDParserClassName) { |
| this.easyAntMDParserClassName = easyAntMDParserClassName; |
| } |
| |
| public void execute() throws BuildException { |
| if (buildModule != null && buildModule.exists()) { |
| |
| // make sure it's not a directory (this falls into the ultra |
| // paranoid lets check everything category |
| |
| if (buildModule.isDirectory()) { |
| throw new BuildException("What? buildModule: " + buildModule + " is a dir!"); |
| } |
| |
| IvyInfo info = new IvyInfo(); |
| info.setFile(buildModule); |
| // Not sure we should bound IvyInfo to easyantIvyInstance |
| info.setSettingsRef(IvyInstanceHelper.buildEasyAntIvyReference(getProject())); |
| initTask(info).execute(); |
| getProject().setName(getProject().getProperty("ivy.module")); |
| |
| // load override buildFile before buildModule to allow target/extension-point |
| // override |
| File f = new File(buildModule.getParent(), EasyAntConstants.DEFAULT_OVERRIDE_BUILD_FILE); |
| if (f.exists()) { |
| log("Loading override build file : " + buildFile.getAbsolutePath()); |
| loadBuildFile(f); |
| } |
| |
| log("Loading build module : " + buildModule.getAbsolutePath()); |
| loadBuildModule(buildModule); |
| } |
| |
| if (buildFile != null && buildFile.exists()) { |
| // make sure it's not a directory (this falls into the ultra |
| // paranoid lets check everything category |
| |
| if (buildFile.isDirectory()) { |
| throw new BuildException("What? buildFile: " + buildFile + " is a dir!"); |
| } |
| |
| log("Loading build file : " + buildFile.getAbsolutePath()); |
| loadBuildFile(buildFile); |
| } |
| |
| String projectIvyInstanceProp = IvyInstanceHelper.getProjectIvyInstanceName(getProject()); |
| |
| // create project ivy instance except if project ivy instance is linked |
| // to easyant ivy instance |
| if (!EasyAntMagicNames.EASYANT_IVY_INSTANCE.equals(projectIvyInstanceProp)) { |
| configureProjectIvyinstance(projectIvyInstanceProp); |
| } |
| |
| configureProjectOfflineResolver(); |
| |
| if (shouldUseBuildRepository()) { |
| configureBuildRepository(); |
| } |
| |
| if (getProject().getDefaultTarget() == null |
| && getProject().getTargets().containsKey(EasyAntConstants.DEFAULT_TARGET)) { |
| getProject().setDefault(EasyAntConstants.DEFAULT_TARGET); |
| } |
| } |
| |
| /** |
| * Configure project offline repository If offline mode is enabled, it will acts as dictator resolver |
| */ |
| private void configureProjectOfflineResolver() { |
| if (EasyAntMagicNames.EASYANT_IVY_INSTANCE.equals(IvyInstanceHelper.getProjectIvyInstanceName(getProject()))) { |
| getProject().setProperty(EasyAntMagicNames.OFFLINE_PROJECT_RESOLVER, |
| getProject().getProperty(EasyAntMagicNames.OFFLINE_EASYANT_RESOLVER)); |
| } else { |
| |
| getProject().setProperty(EasyAntMagicNames.OFFLINE_PROJECT_RESOLVER, |
| EasyAntConstants.DEFAULT_OFFLINE_PROJECT_RESOLVER); |
| ConfigureBuildScopedRepository projectOfflineRepository = new ConfigureBuildScopedRepository(); |
| projectOfflineRepository.setGenerateWrapperResoler(false); |
| projectOfflineRepository.setName(getProject().getProperty(EasyAntMagicNames.OFFLINE_PROJECT_RESOLVER)); |
| projectOfflineRepository.setDictator(Project.toBoolean(getProject().getProperty( |
| EasyAntMagicNames.EASYANT_OFFLINE))); |
| projectOfflineRepository.setSettingsRef(IvyInstanceHelper.buildProjectIvyReference(getProject())); |
| projectOfflineRepository.setTarget(getProject().getProperty(EasyAntMagicNames.OFFLINE_BASE_DIRECTORY)); |
| initTask(projectOfflineRepository).execute(); |
| } |
| } |
| |
| /** |
| * |
| */ |
| private void configureProjectIvyinstance(String projectIvyInstanceName) { |
| IvyConfigure projectIvyInstance = new IvyConfigure(); |
| projectIvyInstance.setSettingsId(projectIvyInstanceName); |
| boolean ivysettingsConfigured = false; |
| // project ivy settings can be specified by properties |
| if (getProject().getProperty(EasyAntMagicNames.PROJECT_IVY_SETTING_FILE) != null) { |
| File projectIvyFile = new File(getProject().getProperty(EasyAntMagicNames.PROJECT_IVY_SETTING_FILE)); |
| |
| if (projectIvyFile.exists()) { |
| projectIvyInstance.setFile(projectIvyFile); |
| ivysettingsConfigured = true; |
| } |
| |
| } |
| if (getProject().getProperty(EasyAntMagicNames.PROJECT_IVY_SETTING_URL) != null) { |
| String url = getProject().getProperty(EasyAntMagicNames.PROJECT_IVY_SETTING_URL); |
| try { |
| projectIvyInstance.setUrl(url); |
| ivysettingsConfigured = true; |
| } catch (MalformedURLException malformedUrl) { |
| throw new BuildException("Unable to parse project ivysettings from the following url : " + url, |
| malformedUrl); |
| } |
| } |
| // if no property is set check the default user location |
| if (!ivysettingsConfigured) { |
| File userProjectIvyFile = new File(getProject().replaceProperties( |
| EasyAntConstants.DEFAULT_USER_PROJECT_IVYSETTINGS)); |
| if (userProjectIvyFile.exists()) { |
| projectIvyInstance.setFile(userProjectIvyFile); |
| ivysettingsConfigured = true; |
| } |
| } |
| // set default project ivy settings location accessible through properties, |
| // then users can import it if they don't want to use it directly |
| String defaultUrl = this.getClass().getResource("/org/apache/easyant/core/default-project-ivysettings.xml") |
| .toExternalForm(); |
| getProject().setNewProperty(EasyAntMagicNames.PROJECT_DEFAULT_IVYSETTINGS, defaultUrl); |
| if (!ivysettingsConfigured) { |
| File localSettings = new File(getProject().getBaseDir(), "ivysettings.xml"); |
| if (localSettings.exists()) { |
| getProject().log("loading local project settings file...", Project.MSG_VERBOSE); |
| projectIvyInstance.setFile(localSettings); |
| getProject() |
| .setNewProperty(EasyAntMagicNames.PROJECT_IVY_SETTING_FILE, localSettings.getAbsolutePath()); |
| |
| } else { |
| getProject().log("no settings file found, using default...", Project.MSG_VERBOSE); |
| getProject().setNewProperty(EasyAntMagicNames.PROJECT_IVY_SETTING_URL, defaultUrl); |
| try { |
| projectIvyInstance.setUrl(defaultUrl); |
| } catch (MalformedURLException e) { |
| throw new BuildException("Unable to parse project ivysettings from the following url : " |
| + defaultUrl, e); |
| } |
| } |
| } |
| |
| initTask(projectIvyInstance).perform(); |
| |
| // FIXME: hack as ResolutionCacheManager use XmlModuleDescriptorParser under the hood |
| EasyAntRepositoryCacheManager cacheManager = new EasyAntRepositoryCacheManager("default-project-cache", |
| getProjectIvyInstance().getSettings(), getProjectIvyInstance().getSettings().getDefaultCache()); |
| getProjectIvyInstance().getSettings().setDefaultRepositoryCacheManager(cacheManager); |
| |
| EasyantResolutionCacheManager resolutionCacheManager = new EasyantResolutionCacheManager(); |
| resolutionCacheManager.setBasedir(getProjectIvyInstance().getSettings().getDefaultResolutionCacheBasedir()); |
| resolutionCacheManager.setSettings(getProjectIvyInstance().getSettings()); |
| getProjectIvyInstance().getSettings().setResolutionCacheManager(resolutionCacheManager); |
| |
| } |
| |
| protected void loadBuildFile(File buildModule) { |
| ImportTask importTask = new ImportTask(); |
| importTask.setFile(buildModule.getAbsolutePath()); |
| importTask.setOptional(true); |
| initTask(importTask).perform(); |
| } |
| |
| protected void loadBuildModule(File buildModule) { |
| IvyContext.pushNewContext().setIvy(getEasyAntIvyInstance()); |
| EasyAntModuleDescriptorParser parser = getEasyAntModuleDescriptorParser(buildModule); |
| log("Loading EasyAnt module descriptor :" + parser.getClass().getName(), Project.MSG_DEBUG); |
| |
| try { |
| parser.parseDescriptor(getEasyAntIvyInstance().getSettings(), buildModule.toURI().toURL(), new URLResource( |
| buildModule.toURI().toURL()), true); |
| EasyAntModuleDescriptor md = parser.getEasyAntModuleDescriptor(); |
| ModuleRevisionId currentModule = md.getIvyModuleDescriptor().getModuleRevisionId(); |
| |
| String buildConfigurations = null; |
| for (String conf : md.getBuildConfigurations()) { |
| if (buildConfigurations == null) { |
| buildConfigurations = conf; |
| } else { |
| buildConfigurations = buildConfigurations + "," + conf; |
| } |
| } |
| getProject().setProperty(EasyAntMagicNames.AVAILABLE_BUILD_CONFIGURATIONS, buildConfigurations); |
| updateMainConfs(); |
| |
| for (PropertyDescriptor property : md.getProperties().values()) { |
| if (canInherit(property, currentModule)) { |
| PropertyTask propTask = new PropertyTask(); |
| propTask.setName(property.getName()); |
| propTask.setValue(property.getValue()); |
| propTask.setBuildConfigurations(property.getBuildConfigurations()); |
| propTask.setTaskType("antlib:org.apache.easyant:property"); |
| getOwningTarget().addTask(propTask); |
| initTask(propTask).perform(); |
| } |
| } |
| if (md.getConfigureProjectDescriptor() != null) { |
| ConfigureProjectDescriptor descriptor = md.getConfigureProjectDescriptor(); |
| ConfigureProject configureProject = new ConfigureProject(); |
| configureProject.setDefaultTarget(descriptor.getDefaultTarget()); |
| configureProject.setBasedir(descriptor.getBasedir()); |
| configureProject.setTaskType("antlib:org.apache.easyant:configure-project"); |
| getOwningTarget().addTask(configureProject); |
| initTask(configureProject).perform(); |
| } |
| |
| ResolvePlugins resolvePlugins = new ResolvePlugins(); |
| |
| if (md.getBuildType() != null) { |
| if (canInherit(md.getBuildType(), currentModule)) { |
| // Import importTask = new Import(); |
| // importTask.setMrid(md.getBuildType().getMrid()); |
| // importTask.setMode(md.getBuildType().getMode()); |
| // importTask.setAs(md.getBuildType().getAs()); |
| // importTask.setMandatory(md.getBuildType().isMandatory()); |
| // importTask.setBuildConfigurations(md.getBuildType().getBuildConfigurations()); |
| // importTask.setDependencies(md.getBuildType().getDependencies()); |
| // importTask.setConflicts(md.getBuildType().getConflicts()); |
| // importTask.setExcludes(md.getBuildType().getExcludes()); |
| // |
| // importTask.setTaskType("antlib:org.apache.easyant:import"); |
| // getOwningTarget().addTask(importTask); |
| // initTask(importTask).perform(); |
| IvyDependency buildtype = resolvePlugins.createDependency(); |
| buildtype.setOrg(md.getBuildType().getModuleRevisionId().getOrganisation()); |
| buildtype.setName(md.getBuildType().getModuleRevisionId().getName()); |
| buildtype.setRev(md.getBuildType().getModuleRevisionId().getRevision()); |
| } |
| } |
| for (PluginDescriptor plugin : md.getPlugins()) { |
| if (canInherit(plugin, currentModule)) { |
| // Import importTask = new Import(); |
| // importTask.setMrid(plugin.getMrid()); |
| // importTask.setMode(plugin.getMode()); |
| // importTask.setAs(plugin.getAs()); |
| // importTask.setMandatory(plugin.isMandatory()); |
| // importTask.setBuildConfigurations(plugin.getBuildConfigurations()); |
| // importTask.setDependencies(plugin.getDependencies()); |
| // importTask.setConflicts(plugin.getConflicts()); |
| // importTask.setExcludes(plugin.getExcludes()); |
| // importTask.setTaskType("antlib:org.apache.easyant:import"); |
| // getOwningTarget().addTask(importTask); |
| // initTask(importTask).perform(); |
| IvyDependency pluginDependency = resolvePlugins.createDependency(); |
| pluginDependency.setOrg(plugin.getModuleRevisionId().getOrganisation()); |
| pluginDependency.setName(plugin.getModuleRevisionId().getName()); |
| pluginDependency.setRev(plugin.getModuleRevisionId().getRevision()); |
| } |
| } |
| initTask(resolvePlugins).execute(); |
| |
| if (md.getBuildType() != null) { |
| if (canInherit(md.getBuildType(), currentModule)) { |
| ImportDeferred importDeferredTask = new ImportDeferred(); |
| importDeferredTask.setOrganisation(md.getBuildType().getModuleRevisionId().getOrganisation()); |
| importDeferredTask.setModule(md.getBuildType().getModuleRevisionId().getName()); |
| importDeferredTask.setMode(md.getBuildType().getMode()); |
| importDeferredTask.setAs(md.getBuildType().getAs()); |
| importDeferredTask.setMandatory(md.getBuildType().isMandatory()); |
| importDeferredTask.setBuildConfigurations(md.getBuildType().getBuildConfigurations()); |
| |
| importDeferredTask.setTaskType("antlib:org.apache.easyant:import-deferred"); |
| getOwningTarget().addTask(importDeferredTask); |
| initTask(importDeferredTask).perform(); |
| } |
| } |
| for (PluginDescriptor plugin : md.getPlugins()) { |
| if (canInherit(plugin, currentModule)) { |
| ImportDeferred importDeferredTask = new ImportDeferred(); |
| importDeferredTask.setOrganisation(plugin.getModuleRevisionId().getOrganisation()); |
| importDeferredTask.setModule(plugin.getModuleRevisionId().getName()); |
| importDeferredTask.setMode(plugin.getMode()); |
| importDeferredTask.setAs(plugin.getAs()); |
| importDeferredTask.setMandatory(plugin.isMandatory()); |
| importDeferredTask.setBuildConfigurations(plugin.getBuildConfigurations()); |
| importDeferredTask.setTaskType("antlib:org.apache.easyant:import-deferred"); |
| getOwningTarget().addTask(importDeferredTask); |
| initTask(importDeferredTask).perform(); |
| |
| } |
| } |
| |
| // Apply ExtensionPointMapping |
| for (ExtensionPointMappingDescriptor epMapping : md.getExtensionPointsMappings()) { |
| BindTarget bindTarget = new BindTarget(); |
| bindTarget.setTarget(epMapping.getTarget()); |
| bindTarget.setExtensionOf(epMapping.getExtensionPoint()); |
| bindTarget.setBuildConfigurations(epMapping.getBuildConfigurations()); |
| initTask(bindTarget).perform(); |
| } |
| } catch (Exception e) { |
| throw new BuildException("problem while parsing Ivy module file: " + e.getMessage(), e); |
| } |
| IvyContext.popContext(); |
| } |
| |
| /** |
| * Check if an inheritable item can be inherited by verifying {@link InheritableScope} |
| * |
| * @param inheritableItem a given {@link AdvancedInheritableItem} |
| * @param currentModule current module |
| * @return true if item can be inherited |
| */ |
| private boolean canInherit(AdvancedInheritableItem inheritableItem, ModuleRevisionId currentModule) { |
| if (currentModule.equals(inheritableItem.getSourceModule())) { |
| return !InheritableScope.CHILD.equals(inheritableItem.getInheritScope()); |
| } else { |
| return true; |
| } |
| |
| } |
| |
| /** |
| * This method is in charge to update the main.confs property with all the active build configuration for the |
| * current project. |
| */ |
| private void updateMainConfs() { |
| if (getProject().getProperty(EasyAntMagicNames.AVAILABLE_BUILD_CONFIGURATIONS) == null |
| || getProject().getProperty(EasyAntMagicNames.ACTIVE_BUILD_CONFIGURATIONS) == null) { |
| return; |
| } |
| |
| List<String> availableBuildConfigurations = Arrays.asList(getProject().getProperty( |
| EasyAntMagicNames.AVAILABLE_BUILD_CONFIGURATIONS).split(",")); |
| // remove spaces in active confs |
| String activeConfs = getProject().getProperty(EasyAntMagicNames.ACTIVE_BUILD_CONFIGURATIONS); |
| List<String> activeBuildConfigurations = BuildConfigurationHelper.buildList(activeConfs); |
| List<String> mainConfsList = new ArrayList<String>(); |
| for (String conf : activeBuildConfigurations) { |
| if (availableBuildConfigurations.contains(conf)) { |
| mainConfsList.add(conf); |
| } else { |
| log("removing unused configuration " + conf, Project.MSG_DEBUG); |
| } |
| } |
| if (!mainConfsList.isEmpty()) { |
| String mainConfs = StringUtils.join(mainConfsList.toArray(new String[mainConfsList.size()]), ","); |
| log("updating main.confs with active profile for current project :" + mainConfs, Project.MSG_DEBUG); |
| getProject().setProperty(EasyAntMagicNames.MAIN_CONFS, mainConfs); |
| } |
| |
| } |
| |
| protected EasyAntModuleDescriptorParser getEasyAntModuleDescriptorParser(File file) throws BuildException { |
| ModuleDescriptorParser mdp; |
| EasyAntModuleDescriptorParser parser; |
| try { |
| mdp = ModuleDescriptorParserRegistry.getInstance().getParser(new URLResource(file.toURI().toURL())); |
| } catch (MalformedURLException e) { |
| throw new BuildException("Impossible to find a parser for " + file.getName()); |
| } |
| // If valid easyant parser is defined use it |
| if (mdp != null && mdp.getClass().isInstance(EasyAntModuleDescriptorParser.class)) { |
| return (EasyAntModuleDescriptorParser) mdp; |
| } else { |
| // if the user has customized the loadmodule task |
| if (easyAntMDParserClassName != null) { |
| |
| try { |
| Class<? extends EasyAntModuleDescriptorParser> c = Class.forName(easyAntMDParserClassName) |
| .asSubclass(EasyAntModuleDescriptorParser.class); |
| log("Creating instance of " + easyAntMDParserClassName, Project.MSG_DEBUG); |
| parser = c.newInstance(); |
| ModuleDescriptorParserRegistry.getInstance().addParser(parser); |
| return parser; |
| } catch (Exception e) { |
| throw new BuildException("Unable to load " + easyAntMDParserClassName, e); |
| } |
| |
| } |
| // the default one |
| log("Creating instance of " + DefaultEasyAntXmlModuleDescriptorParser.class.getName(), Project.MSG_DEBUG); |
| parser = new DefaultEasyAntXmlModuleDescriptorParser(); |
| ModuleDescriptorParserRegistry.getInstance().addParser(parser); |
| return parser; |
| |
| } |
| } |
| |
| /** |
| * @return true if this module should use a build-scoped repository and cache to find artifacts generated by other |
| * modules in the same build. |
| */ |
| private boolean shouldUseBuildRepository() { |
| // if a value has been provided by task attribute, return it |
| if (useBuildRepository != null) { |
| return useBuildRepository; |
| } |
| // otherwise, look for a value in property configuration, defaulting to |
| // false if no value. |
| return Project.toBoolean(getProject().getProperty(EasyAntMagicNames.USE_BUILD_REPOSITORY)); |
| } |
| |
| /** |
| * Change the given Ivy settings to use a local build-scoped repository and cache by default. This allows submodules |
| * to access each others' artifacts before they have been published to a shared repository. |
| */ |
| private void configureBuildRepository() throws BuildException { |
| ConfigureBuildScopedRepository configureBuildScopedRepository = new ConfigureBuildScopedRepository(); |
| configureBuildScopedRepository.setName(EasyAntConstants.BUILD_SCOPE_REPOSITORY); |
| configureBuildScopedRepository.setSettingsRef(IvyInstanceHelper.buildProjectIvyReference(getProject())); |
| configureBuildScopedRepository.setGenerateWrapperResoler(true); |
| getProject().setProperty(EasyAntMagicNames.EASYANT_BUILD_REPOSITORY, EasyAntConstants.BUILD_SCOPE_REPOSITORY); |
| initTask(configureBuildScopedRepository).perform(); |
| } |
| |
| } |