| /* |
| * 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 java.io.File; |
| |
| import org.apache.easyant.core.EasyAntMagicNames; |
| import org.apache.ivy.core.LogOptions; |
| import org.apache.ivy.core.module.id.ModuleId; |
| import org.apache.ivy.core.module.id.ModuleRevisionId; |
| import org.apache.ivy.core.report.ArtifactDownloadReport; |
| import org.apache.ivy.core.report.ResolveReport; |
| import org.apache.ivy.core.resolve.ResolveOptions; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.taskdefs.ImportTask; |
| import org.apache.tools.ant.types.Path; |
| |
| /** |
| * This abstract task is used to include / import modules. |
| * |
| * The include mechanism is similar to the current import task, excepts that it automatically prefix all targets of the |
| * used build module (=ant script). The prefix used by default is the name of the imported project, but it can be |
| * overriden when calling "include". |
| * |
| * Include is useful to use features provided by a build module, while preserving a namespace isolation to avoid names |
| * collisions. |
| * |
| * While possible, overriding a target defined in a included module is not recommended. To do so, the import mechanism |
| * is preferred. |
| * |
| */ |
| public abstract class AbstractImport extends AbstractEasyAntTask { |
| |
| private String as; |
| private String mode; |
| private boolean mandatory; |
| private String buildConfigurations; |
| private String mainConf = "default"; |
| private String providedConf = "provided"; |
| private boolean changing = false; |
| |
| public AbstractImport() { |
| super(); |
| } |
| |
| /** |
| * Import a module |
| * |
| * @param moduleRevisionId |
| * {@link ModuleRevisionId} of main artifact |
| * @param report |
| * a resolved report of the module to import |
| */ |
| protected void importModule(ModuleRevisionId moduleRevisionId, ResolveReport report) { |
| // Check dependency on core |
| checkCoreCompliance(report, providedConf); |
| |
| Path path = createModulePath(moduleRevisionId.getModuleId()); |
| File antFile = null; |
| for (int j = 0; j < report.getConfigurationReport(mainConf).getAllArtifactsReports().length; j++) { |
| ArtifactDownloadReport artifact = report.getConfigurationReport(mainConf).getAllArtifactsReports()[j]; |
| if ("ant".equals(artifact.getType())) { |
| antFile = artifact.getLocalFile(); |
| } else if (shouldBeAddedToClasspath(artifact)) { |
| path.createPathElement().setLocation(artifact.getLocalFile()); |
| } else { |
| handleOtherResourceFile(moduleRevisionId, artifact.getName(), artifact.getExt(), |
| artifact.getLocalFile()); |
| } |
| } |
| // effective import should be executed AFTER any other resource files has been handled |
| if (antFile != null && antFile.exists()) { |
| doEffectiveImport(antFile); |
| } |
| } |
| |
| public boolean shouldBeAddedToClasspath(ArtifactDownloadReport artifact) { |
| String[] types; |
| if (getProject().getProperty(EasyAntMagicNames.IMPORT_CLASSPATH_TYPES) != null) { |
| types = getProject().getProperty(EasyAntMagicNames.IMPORT_CLASSPATH_TYPES).split(","); |
| } else { |
| types = new String[] { "jar", "bundle" }; |
| } |
| for (String type : types) { |
| if (artifact.getType().equals(type)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Do effective import of a given ant file |
| * |
| * @param antFile |
| * a given ant file |
| */ |
| protected void doEffectiveImport(File antFile) { |
| ImportTask importTask = new ImportTask(); |
| importTask.setFile(antFile.getAbsolutePath()); |
| if (as != null) { |
| importTask.setAs(as); |
| importTask.setPrefixSeparator(""); |
| } |
| if (mode != null && "include".equals(mode)) { |
| importTask.setTaskType(getMode()); |
| } |
| initTask(importTask).execute(); |
| } |
| |
| /** |
| * <p> |
| * Register all location of other resource file in properties. |
| * </p> |
| * <p> |
| * Properties are composed with the following syntax : [organisation].[module].[artifact].[type].file |
| * </p> |
| * <p> |
| * The '.artifact' is optional when module name and artifact name are the same. [organisation].[module].[type].file |
| * </p> |
| * |
| * @param moduleRevisionId |
| * a {@link ModuleRevisionId} of the main artifact |
| * @param artifactName |
| * artifact name |
| * @param artifactExtension |
| * artifact extension name |
| * @param localResourceFile |
| */ |
| protected void handleOtherResourceFile(ModuleRevisionId moduleRevisionId, String artifactName, |
| String artifactExtension, File localResourceFile) { |
| if (localResourceFile == null) { |
| getProject().log( |
| "Can't find artifact " + artifactName + " ext" + artifactExtension |
| + ". See resolution report to have details", Project.MSG_WARN); |
| } else { |
| StringBuilder sb = new StringBuilder(); |
| sb.append(moduleRevisionId.getOrganisation()); |
| sb.append("#"); |
| sb.append(moduleRevisionId.getName()); |
| sb.append("."); |
| if (!moduleRevisionId.getName().equals(artifactName)) { |
| sb.append(artifactName); |
| sb.append("."); |
| } |
| sb.append(artifactExtension); |
| sb.append(".file"); |
| |
| getProject().log( |
| "registering location of artifact " + artifactName + " ext" + artifactExtension + " on " |
| + sb.toString(), Project.MSG_DEBUG); |
| getProject().setNewProperty(sb.toString(), localResourceFile.getAbsolutePath()); |
| } |
| } |
| |
| /** |
| * creates a classpath specific for each module, this classpath will contains all the required dependency .jars. The |
| * classpath is named [organisation]#[module].classpath |
| * |
| * @param moduleId |
| * @return |
| */ |
| protected Path createModulePath(ModuleId moduleId) { |
| Path path = new Path(getProject()); |
| getProject().addReference(moduleId.toString() + ".classpath", path); |
| return path; |
| } |
| |
| /** |
| * Configures resolve options |
| * |
| * @return configured resolveOptions |
| */ |
| protected ResolveOptions configureResolveOptions() { |
| // Here we do not specify explicit configuration to resolve as |
| // we want to check multiple configurations. |
| // If we make specify explicitly configurations to resolve, the |
| // resolution could through exceptions when configuration does |
| // not exist in resolved modules. |
| // resolveOptions.setConfs(new String[] { mainConf,providedConf }); |
| |
| // By default we consider that main conf is default. |
| // To verify core compliance we can have a dependency on |
| // easyant-core in a specific configuration. |
| // By default this configuration is provided. |
| |
| // An error can be thrown if module contains non-public configurations. |
| ResolveOptions resolveOptions = new ResolveOptions(); |
| resolveOptions.setLog(getResolveLog()); |
| |
| Boolean offline = Boolean.valueOf(getProject().getProperty(EasyAntMagicNames.EASYANT_OFFLINE)); |
| resolveOptions.setUseCacheOnly(offline); |
| return resolveOptions; |
| } |
| |
| /** |
| * Check dependency on easyant core with a given configuration. If dependency is found we'll check compliance with |
| * current core version. It uses {@link CoreRevisionCheckerTask} internally. |
| * |
| * @param report |
| * a {@link ResolveReport} |
| * @param confToCheck |
| * configuration to check |
| */ |
| protected void checkCoreCompliance(ResolveReport report, String confToCheck) { |
| if (report.getConfigurationReport(confToCheck) != null) { |
| log("checking module's provided dependencies ...", Project.MSG_DEBUG); |
| for (Object o : report.getConfigurationReport(confToCheck).getModuleRevisionIds()) { |
| ModuleRevisionId currentmrid = (ModuleRevisionId) o; |
| log("checking " + currentmrid.toString(), Project.MSG_DEBUG); |
| if (currentmrid.getOrganisation().equals("org.apache.easyant") |
| && currentmrid.getName().equals("easyant-core")) { |
| CoreRevisionCheckerTask checker = new CoreRevisionCheckerTask(); |
| checker.setRequiredRevision(currentmrid.getRevision()); |
| initTask(checker).execute(); |
| } |
| } |
| } |
| } |
| |
| public void setDynamicAttribute(String attributeName, String value) throws BuildException { |
| PropertyTask property = new PropertyTask(); |
| property.setName(attributeName); |
| property.setValue(value); |
| initTask(property).execute(); |
| } |
| |
| /** |
| * Get resolve log settings |
| * |
| * @return a string representing the log strategy |
| */ |
| protected String getResolveLog() { |
| String downloadLog = getProject().getProperty(EasyAntMagicNames.MODULE_DOWNLOAD_LOG); |
| return downloadLog != null ? downloadLog : LogOptions.LOG_DOWNLOAD_ONLY; |
| } |
| |
| /** |
| * Get the alias name |
| * |
| * @return a string that represents the alias name |
| */ |
| public String getAs() { |
| return as; |
| } |
| |
| /** |
| * Set the alias name |
| * |
| * @param as |
| * a string that represents the alias name |
| */ |
| public void setAs(String as) { |
| this.as = as; |
| } |
| |
| /** |
| * Get the import mode |
| * |
| * @return a string that represents the import mode (e.g. import / include) |
| */ |
| public String getMode() { |
| return mode; |
| } |
| |
| /** |
| * Set the import mode |
| * |
| * @param mode |
| * a string that represents the import mode (e.g. import / include) |
| */ |
| public void setMode(String mode) { |
| this.mode = mode; |
| } |
| |
| public String getBuildConfigurations() { |
| return buildConfigurations; |
| } |
| |
| public void setBuildConfigurations(String conf) { |
| this.buildConfigurations = conf; |
| } |
| |
| public void setConf(String conf) { |
| this.buildConfigurations = conf; |
| } |
| |
| /** |
| * Get the main configuration where plugin are resolved |
| * |
| * @return a string representing the main configuration |
| */ |
| public String getMainConf() { |
| return mainConf; |
| } |
| |
| /** |
| * Set the main configuration where plugin are resolved |
| * |
| * @param mainConf |
| * a string representing the main configuration |
| */ |
| public void setMainConf(String mainConf) { |
| this.mainConf = mainConf; |
| } |
| |
| /** |
| * Get the configuration that may contain dependency on easyant-core. This configuration is used to check core |
| * compliance at resolve time. It should not affect the plugin classpath |
| * |
| * @return provided configuration |
| */ |
| public String getProvidedConf() { |
| return providedConf; |
| } |
| |
| /** |
| * Set the configuration that may contain dependency on easyant-core. This configuration is used to check core |
| * compliance at resolve time. It should not affect the plugin classpath |
| * |
| * @return provided configuration |
| */ |
| public void setProvidedConf(String providedConf) { |
| this.providedConf = providedConf; |
| } |
| |
| /** |
| * Can we skip the load of this module? |
| * |
| * return true if the module can't be skipped |
| */ |
| public boolean isMandatory() { |
| return mandatory; |
| } |
| |
| /** |
| * Can we skip the load of this module? |
| * |
| * @param mandatory |
| * true if the module can't be skipped |
| */ |
| public void setMandatory(boolean mandatory) { |
| this.mandatory = mandatory; |
| |
| } |
| |
| public boolean isChanging() { |
| return changing; |
| } |
| |
| public void setChanging(boolean changing) { |
| this.changing = changing; |
| } |
| |
| } |