blob: cfbda06c37cc1e2e50af87543ebf89d4859629ac [file] [log] [blame]
/*
* 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.core.parser;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.easyant.core.EasyAntConstants;
import org.apache.easyant.core.descriptor.AdvancedInheritableItem;
import org.apache.easyant.core.descriptor.ConfigureProjectDescriptor;
import org.apache.easyant.core.descriptor.DefaultEasyAntDescriptor;
import org.apache.easyant.core.descriptor.EasyAntModuleDescriptor;
import org.apache.easyant.core.descriptor.ExtensionPointMappingDescriptor;
import org.apache.easyant.core.descriptor.PluginDescriptor;
import org.apache.easyant.core.descriptor.PluginType;
import org.apache.easyant.core.descriptor.PropertyDescriptor;
import org.apache.easyant.core.ivy.InheritableScope;
import org.apache.ivy.Ivy;
import org.apache.ivy.ant.IvyConflict;
import org.apache.ivy.ant.IvyDependency;
import org.apache.ivy.ant.IvyDependencyArtifact;
import org.apache.ivy.ant.IvyDependencyConf;
import org.apache.ivy.ant.IvyDependencyExclude;
import org.apache.ivy.ant.IvyDependencyInclude;
import org.apache.ivy.ant.IvyExclude;
import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.module.descriptor.Configuration;
import org.apache.ivy.core.module.descriptor.DefaultExtendsDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleId;
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.parser.ParserSettings;
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.plugins.repository.file.FileResource;
import org.apache.ivy.util.FileUtil;
import org.apache.ivy.util.Message;
import org.apache.ivy.util.PropertiesFile;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* Parses an easyant module descriptor and output an EasyAntModuleDescriptor
*/
public class DefaultEasyAntXmlModuleDescriptorParser extends XmlModuleDescriptorParser implements
EasyAntModuleDescriptorParser {
private static final DefaultEasyAntXmlModuleDescriptorParser INSTANCE = new DefaultEasyAntXmlModuleDescriptorParser();
public static DefaultEasyAntXmlModuleDescriptorParser getInstance() {
return INSTANCE;
}
static final String[] PLUGIN_REGULAR_ATTRIBUTES = new String[] { "organisation", "org", "module", "revision",
"rev", "mrid", "conf", "mode", "as", "inheritable", "inherit-scope" };
public boolean accept(Resource res) {
return res.getName().endsWith(".ivy") || res.getName().endsWith(".xml");
}
protected Parser newParser(ParserSettings ivySettings) {
return new EasyAntParser(this, ivySettings);
}
private EasyAntModuleDescriptor easyAntModuleDescriptor;
public EasyAntModuleDescriptor getEasyAntModuleDescriptor() {
return easyAntModuleDescriptor;
}
public ModuleDescriptor parseDescriptor(ParserSettings ivySettings, URL xmlURL, Resource res, boolean validate)
throws ParseException, IOException {
EasyAntParser parser = (EasyAntParser) newParser(ivySettings);
parser.setValidate(validate);
parser.setResource(res);
parser.setInput(xmlURL);
parser.parse();
easyAntModuleDescriptor = parser.getEasyAntModuleDescriptor();
return parser.getModuleDescriptor();
}
private enum EasyAntState {
NONE, BUILDTYPE, PLUGIN, PLUGIN_DEPENDENCY, CONFIGURE_PROJECT
}
public class EasyAntParser extends Parser {
private EasyAntState easyAntState;
private DefaultEasyAntDescriptor easyAntModuleDescriptor;
private String easyantPrefix;
private PluginDescriptor currentPluginDescriptor;
private IvyDependency currentPluginDependency;
public EasyAntParser(ModuleDescriptorParser parser, ParserSettings ivySettings) {
super(parser, ivySettings);
easyAntState = EasyAntState.NONE;
easyAntModuleDescriptor = new DefaultEasyAntDescriptor();
easyantPrefix = "";
}
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
super.startElement(uri, localName, name, attributes);
if (name.equals(easyantPrefix + ":build") && State.EXTRA_INFO == getState()) {
eaBuildStarted(attributes);
}
if (name.equals(easyantPrefix + ":plugin") && State.EXTRA_INFO == getState()) {
pluginStarted(attributes);
}
if (name.equals(easyantPrefix + ":property") && State.EXTRA_INFO == getState()) {
easyantPropertyStarted(attributes);
}
if (name.equals(easyantPrefix + ":bindtarget") && State.EXTRA_INFO == getState()) {
bindTargetStarted(attributes);
}
if (name.equals(easyantPrefix + ":configure-project") && State.EXTRA_INFO == getState()) {
if (easyAntState != EasyAntState.NONE) {
throw new SAXException("configure-project is not supported as a nested element");
}
configureProjectStarted(attributes);
}
if (name.equals(easyantPrefix + ":dependency") && easyAntState == EasyAntState.PLUGIN) {
pluginDependencyStarted(attributes);
}
if (name.equals(easyantPrefix + ":exclude") && easyAntState == EasyAntState.PLUGIN_DEPENDENCY) {
pluginDependencyExcludeStarted(attributes);
}
if (name.equals(easyantPrefix + ":include") && easyAntState == EasyAntState.PLUGIN_DEPENDENCY) {
pluginDependencyIncludeStarted(attributes);
}
if (name.equals(easyantPrefix + ":artifact") && easyAntState == EasyAntState.PLUGIN_DEPENDENCY) {
pluginDependencyIncludeStarted(attributes);
}
if (name.equals(easyantPrefix + ":conf") && easyAntState == EasyAntState.PLUGIN_DEPENDENCY) {
pluginDependencyConfStarted(attributes);
}
if (name.equals(easyantPrefix + ":exclude") && easyAntState == EasyAntState.PLUGIN) {
pluginExcludeStarted(attributes);
}
if (name.equals(easyantPrefix + ":conflict") && easyAntState == EasyAntState.PLUGIN) {
pluginConflictStarted(attributes);
}
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
super.endElement(uri, localName, name);
if (name.equals(easyantPrefix + ":plugin") && easyAntState == EasyAntState.PLUGIN) {
endPlugin();
}
if (name.equals(easyantPrefix + ":dependency") && easyAntState == EasyAntState.PLUGIN_DEPENDENCY) {
endPluginDependency();
}
if (name.equals(easyantPrefix + ":configure-project") && easyAntState == EasyAntState.CONFIGURE_PROJECT) {
easyAntState = EasyAntState.NONE;
}
}
protected void endPlugin() {
currentPluginDescriptor = null;
easyAntState = EasyAntState.NONE;
}
public void endPluginDependency() {
currentPluginDependency = null;
easyAntState = EasyAntState.PLUGIN;
}
@Override
protected void ivyModuleStarted(Attributes attributes) throws SAXException {
super.ivyModuleStarted(attributes);
// lookup easyant namespace
for (Object o : getMd().getExtraAttributesNamespaces().entrySet()) {
Entry<?, ?> namespace = (Entry<?, ?>) o;
if (EasyAntConstants.EASYANT_MD_NAMESPACE.equals(namespace.getValue())) {
easyantPrefix = (String) namespace.getKey();
}
}
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
for (Configuration conf : getMd().getConfigurations()) {
if ("profile".equals(conf.getExtraAttribute(easyantPrefix + ":type"))) {
Message.debug("Adding build configuration named " + conf.getName());
easyAntModuleDescriptor.addBuildConfiguration(conf.getName());
}
}
try {
easyAntModuleDescriptor.setIvyModuleDescriptor(super.getModuleDescriptor());
} catch (ParseException e) {
throw new SAXException(e);
}
}
/**
* Parses configure-project tag
*
* @param attributes
* represents configure project attributes
*/
protected void configureProjectStarted(Attributes attributes) {
easyAntState = EasyAntState.CONFIGURE_PROJECT;
ConfigureProjectDescriptor configureProjectDescriptor = new ConfigureProjectDescriptor();
String basedir = getSettings().substitute(attributes.getValue("basedir"));
String defaultTarget = getSettings().substitute(attributes.getValue("defaulttarget"));
configureProjectDescriptor.setBasedir(basedir);
configureProjectDescriptor.setDefaultTarget(defaultTarget);
handlePropertyAsAttribute(attributes, Arrays.asList("basedir", "defaulttarget"),
configureProjectDescriptor, null);
handleInheritedScopeAttribute(attributes, configureProjectDescriptor);
easyAntModuleDescriptor.setConfigureProjectDescriptor(configureProjectDescriptor);
}
/**
* Parsing the plugin tag
*
* @param attributes
* reprensents the plugins attributes
*/
protected void pluginStarted(Attributes attributes) {
easyAntState = EasyAntState.PLUGIN;
PluginDescriptor plugin = handleCommonPluginDescriptorAttributes(attributes, PluginType.PLUGIN);
// plugin specific attribute
boolean mandatory = false;
String mandatoryValue = getSettings().substitute(attributes.getValue("mandatory"));
if (mandatoryValue != null && "true".equals(mandatoryValue)) {
mandatory = true;
}
plugin.setMandatory(mandatory);
handleInheritedScopeAttribute(attributes, plugin);
currentPluginDescriptor = plugin;
easyAntModuleDescriptor.addPlugin(plugin);
handlePropertyAsAttribute(attributes, Arrays.asList(PLUGIN_REGULAR_ATTRIBUTES), plugin,
plugin.getBuildConfigurations());
}
/**
* Parsing the easyant tag
*
* @param attributes
* reprensents the easyant attributes
*/
protected void eaBuildStarted(Attributes attributes) {
easyAntState = EasyAntState.BUILDTYPE;
PluginDescriptor buildtype = handleCommonPluginDescriptorAttributes(attributes, PluginType.BUILDTYPE);
// a build type cannot be skipped
buildtype.setMandatory(true);
easyAntModuleDescriptor.setBuildType(buildtype);
handlePropertyAsAttribute(attributes, Arrays.asList(PLUGIN_REGULAR_ATTRIBUTES), buildtype,
buildtype.getBuildConfigurations());
}
private PluginDescriptor handleCommonPluginDescriptorAttributes(Attributes attributes, PluginType pluginType) {
PluginDescriptor pluginDescriptor = new PluginDescriptor();
String mrid = getSettings().substitute(attributes.getValue("mrid"));
if (mrid != null) {
if (!mrid.matches(".*#.*")) {
if (pluginType == PluginType.BUILDTYPE) {
Message.debug("No organisation specified for buildtype " + mrid + " using the default one");
mrid = EasyAntConstants.EASYANT_BUILDTYPES_ORGANISATION + "#" + mrid;
} else {
Message.debug("No organisation specified for plugin " + mrid + " using the default one");
mrid = EasyAntConstants.EASYANT_PLUGIN_ORGANISATION + "#" + mrid;
}
}
pluginDescriptor.setMrid(mrid);
} else {
String module = getSettings().substitute(attributes.getValue("module"));
String org = attributes.getValue("org") != null ? attributes.getValue("org") : attributes
.getValue("organisation");
org = getSettings().substitute(org);
if (org == null) {
if (pluginType == PluginType.BUILDTYPE) {
Message.debug("No organisation specified for buildtype " + module + " using the default one");
org = EasyAntConstants.EASYANT_BUILDTYPES_ORGANISATION;
} else {
Message.debug("No organisation specified for plugin " + module + " using the default one");
org = EasyAntConstants.EASYANT_PLUGIN_ORGANISATION;
}
}
String revision = attributes.getValue("rev") != null ? attributes.getValue("rev") : attributes
.getValue("revision");
revision = getSettings().substitute(revision);
pluginDescriptor.setOrganisation(org);
pluginDescriptor.setModule(module);
pluginDescriptor.setRevision(revision);
}
String conf = getSettings().substitute(attributes.getValue("conf"));
pluginDescriptor.setBuildConfigurations(conf);
pluginDescriptor.setMode(getSettings().substitute(attributes.getValue("mode")));
pluginDescriptor.setAs(getSettings().substitute(attributes.getValue("as")));
return pluginDescriptor;
}
public void pluginDependencyStarted(Attributes attributes) {
easyAntState = EasyAntState.PLUGIN_DEPENDENCY;
IvyDependency ivyDependency = new IvyDependency();
ivyDependency.setOrg(getSettings().substitute(attributes.getValue("org")));
ivyDependency.setForce(Boolean.valueOf(getSettings().substitute(attributes.getValue("force"))));
ivyDependency.setChanging(Boolean.valueOf(getSettings().substitute(attributes.getValue("changing"))));
String transitiveValue = getSettings().substitute(attributes.getValue("transitive"));
boolean transitive = (transitiveValue == null) ? true : Boolean.valueOf(attributes.getValue("transitive"));
ivyDependency.setTransitive(transitive);
ivyDependency.setName(getSettings().substitute(attributes.getValue("name")));
ivyDependency.setBranch(getSettings().substitute(attributes.getValue("branch")));
ivyDependency.setRev(getSettings().substitute(attributes.getValue("rev")));
currentPluginDescriptor.addDependency(ivyDependency);
currentPluginDependency = ivyDependency;
}
public void pluginDependencyExcludeStarted(Attributes attributes) {
IvyDependencyExclude ivyDependencyExclude = currentPluginDependency.createExclude();
ivyDependencyExclude.setOrg(getSettings().substitute(attributes.getValue("org")));
ivyDependencyExclude.setModule(getSettings().substitute(attributes.getValue("module")));
ivyDependencyExclude.setName(getSettings().substitute(attributes.getValue("name")));
ivyDependencyExclude.setExt(getSettings().substitute(attributes.getValue("ext")));
ivyDependencyExclude.setType(getSettings().substitute(attributes.getValue("type")));
ivyDependencyExclude.setMatcher(getSettings().substitute(attributes.getValue("matcher")));
}
public void pluginDependencyIncludeStarted(Attributes attributes) {
IvyDependencyInclude ivyDependencyInclude = currentPluginDependency.createInclude();
ivyDependencyInclude.setName(getSettings().substitute(attributes.getValue("name")));
ivyDependencyInclude.setExt(getSettings().substitute(attributes.getValue("ext")));
ivyDependencyInclude.setType(getSettings().substitute(attributes.getValue("type")));
ivyDependencyInclude.setMatcher(getSettings().substitute(attributes.getValue("matcher")));
}
public void pluginDependencyArtifactStarted(Attributes attributes) {
IvyDependencyArtifact ivyDependencyArtifact = currentPluginDependency.createArtifact();
ivyDependencyArtifact.setName(getSettings().substitute(attributes.getValue("name")));
ivyDependencyArtifact.setExt(getSettings().substitute(attributes.getValue("ext")));
ivyDependencyArtifact.setType(getSettings().substitute(attributes.getValue("type")));
ivyDependencyArtifact.setUrl(getSettings().substitute(attributes.getValue("url")));
}
public void pluginDependencyConfStarted(Attributes attributes) {
IvyDependencyConf ivyDependencyConf = currentPluginDependency.createConf();
ivyDependencyConf.setMapped(getSettings().substitute(attributes.getValue("mapped")));
}
public void pluginConflictStarted(Attributes attributes) {
IvyConflict ivyConflict = new IvyConflict();
ivyConflict.setOrg(getSettings().substitute(attributes.getValue("org")));
ivyConflict.setModule(getSettings().substitute(attributes.getValue("module")));
ivyConflict.setRev(getSettings().substitute(attributes.getValue("rev")));
ivyConflict.setManager(getSettings().substitute(attributes.getValue("manager")));
ivyConflict.setMatcher(getSettings().substitute(attributes.getValue("matcher")));
currentPluginDescriptor.addConflict(ivyConflict);
}
public void pluginExcludeStarted(Attributes attributes) {
IvyExclude ivyExclude = new IvyExclude();
ivyExclude.setOrg(getSettings().substitute(attributes.getValue("org")));
ivyExclude.setModule(getSettings().substitute(attributes.getValue("module")));
ivyExclude.setArtifact(getSettings().substitute(attributes.getValue("artifact")));
ivyExclude.setType(getSettings().substitute(attributes.getValue("type")));
ivyExclude.setExt(getSettings().substitute(attributes.getValue("ext")));
ivyExclude.setMatcher(getSettings().substitute(attributes.getValue("matcher")));
currentPluginDescriptor.addExcludes(ivyExclude);
}
/**
* handle properties as attribute
*
* @param attributes
* a set of attributes
* @param ignoredAttributes
* a list of ignored attributes
* @param parentNode
* parent node used to apply some attributes to subelements (can be null)
* @param buildConf
* build configurations where this property should be applied (can be null)
*
*/
private void handlePropertyAsAttribute(Attributes attributes, List<String> ignoredAttributes,
AdvancedInheritableItem parentNode, String buildConf) {
for (int i = 0; i < attributes.getLength(); i++) {
if (!ignoredAttributes.contains(attributes.getQName(i))) {
String propertyName = attributes.getQName(i);
String value = IvyContext.getContext().getSettings().substitute(attributes.getValue(i));
PropertyDescriptor property = new PropertyDescriptor(propertyName);
property.setValue(value);
property.setBuildConfigurations(buildConf);
if (parentNode != null) {
property.setInheritScope(parentNode.getInheritScope());
property.setInheritable(parentNode.isInheritable());
}
easyAntModuleDescriptor.getProperties().put(propertyName, property);
}
}
}
/**
* Handle inherited scope specific attributes
*
* @param attributes
* a set of attributes
* @param inheritScopeElement
* an element supporting inherit scope attributes
*/
private void handleInheritedScopeAttribute(Attributes attributes, AdvancedInheritableItem inheritScopeElement) {
String inheritScopeValue = getSettings().substitute(attributes.getValue("inherit-scope"));
if (inheritScopeValue != null) {
InheritableScope scope = InheritableScope.valueOf(inheritScopeValue.toUpperCase());
inheritScopeElement.setInheritScope(scope);
}
String inheritableValue = getSettings().substitute(attributes.getValue("inheritable"));
if (inheritableValue != null) {
inheritScopeElement.setInheritable("true".equalsIgnoreCase(inheritableValue));
}
}
/**
* Parsing the bindtarget tag
*
* @param attributes
* reprensents the bindtarget attributes
*/
protected void bindTargetStarted(Attributes attributes) {
String target = getSettings().substitute(attributes.getValue("target"));
String toExtensionPoint = getSettings().substitute(attributes.getValue("extensionOf"));
String conf = getSettings().substitute(attributes.getValue("conf"));
if (EasyAntState.PLUGIN == easyAntState && conf == null) {
conf = currentPluginDescriptor.getBuildConfigurations();
}
// if bindtarget tag is a subelement and look if an alias was
// defined on the plugin
if (EasyAntState.PLUGIN == easyAntState && currentPluginDescriptor.getAs() != null) {
// check if the fully qualified name was defined, if not get
// the alias defined on the plugin
if (!target.startsWith(currentPluginDescriptor.getAs())) {
target = currentPluginDescriptor.getAs() + target;
}
}
ExtensionPointMappingDescriptor extensionPointMappingDescriptor = new ExtensionPointMappingDescriptor();
extensionPointMappingDescriptor.setBuildConfigurations(conf);
extensionPointMappingDescriptor.setTarget(target);
extensionPointMappingDescriptor.setExtensionPoint(toExtensionPoint);
handleInheritedScopeAttribute(attributes, extensionPointMappingDescriptor);
easyAntModuleDescriptor.addExtensionPointMapping(extensionPointMappingDescriptor);
}
public EasyAntModuleDescriptor getEasyAntModuleDescriptor() {
return easyAntModuleDescriptor;
}
/**
* Parse the property tag
*
* @param attributes
* reprensents the plugins attributes
* @throws SAXException
*/
protected void easyantPropertyStarted(Attributes attributes) throws SAXException {
String conf = getSettings().substitute(attributes.getValue("conf"));
// if property tag is a subelement and
// no build configuration was defined looked at plugin build
// configurations
if (EasyAntState.PLUGIN == easyAntState && conf == null) {
conf = currentPluginDescriptor.getBuildConfigurations();
}
if (attributes.getValue("file") != null) {
String fileName = getSettings().substitute(attributes.getValue("file"));
File file = new File(fileName);
if (!file.exists()) {
throw new SAXException(fileName + " doesn't exists !");
}
PropertiesFile props = new PropertiesFile(file, "project properties");
Enumeration<?> enumeration = props.propertyNames();
while (enumeration.hasMoreElements()) {
String key = (String) enumeration.nextElement();
String value = getSettings().substitute(props.getProperty(key));
// put this variable on the context
IvyContext.getContext().getSettings().getVariableContainer().setVariable(key, value, true);
PropertyDescriptor property = new PropertyDescriptor(key);
property.setValue(value);
property.setBuildConfigurations(conf);
applyInheritableItemAttributesFromParentNode(property);
// override with explicit inherited scope attributes
handleInheritedScopeAttribute(attributes, property);
easyAntModuleDescriptor.getProperties().put(key, property);
}
} else if (attributes.getValue("name") != null) {
String propertyName = getSettings().substitute(attributes.getValue("name"));
String value = getSettings().substitute(attributes.getValue("value"));
// put this variable on the context
IvyContext.getContext().getSettings().getVariableContainer().setVariable(propertyName, value, true);
PropertyDescriptor property = new PropertyDescriptor(propertyName, getMd().getModuleRevisionId());
property.setValue(value);
property.setBuildConfigurations(conf);
applyInheritableItemAttributesFromParentNode(property);
// override with explicit inherited scope attributes
handleInheritedScopeAttribute(attributes, property);
easyAntModuleDescriptor.getProperties().put(propertyName, property);
}
}
/**
* Apply {@link AdvancedInheritableItem} attributes from current plugin
*
* @param currentItem
*/
private void applyInheritableItemAttributesFromParentNode(AdvancedInheritableItem currentItem) {
AdvancedInheritableItem parentNode = null;
if (easyAntState == EasyAntState.PLUGIN) {
parentNode = currentPluginDescriptor;
} else if (easyAntState == EasyAntState.CONFIGURE_PROJECT) {
parentNode = easyAntModuleDescriptor.getConfigureProjectDescriptor();
}
if (parentNode != null) {
currentItem.setInheritable(parentNode.isInheritable());
currentItem.setInheritScope(parentNode.getInheritScope());
}
}
/**
* Merge all metadata with an other module descriptor
*
* @param parent
* an other module descriptor
*/
protected void mergeAll(ModuleDescriptor parent) {
super.mergeAll(parent);
if (parent.getParser() instanceof DefaultEasyAntXmlModuleDescriptorParser) {
DefaultEasyAntXmlModuleDescriptorParser parser = (DefaultEasyAntXmlModuleDescriptorParser) parent
.getParser();
mergeEasyantProperties(parser.getEasyAntModuleDescriptor().getProperties());
mergeEasyantPlugins(parser.getEasyAntModuleDescriptor().getPlugins());
mergeBindTargets(parser.getEasyAntModuleDescriptor().getExtensionPointsMappings());
mergeConfigureProject(parser.getEasyAntModuleDescriptor().getConfigureProjectDescriptor());
}
}
/**
* Merge with other module descriptor
*
* @param extendTypes
* a string that represents what we should extends
* @param parent
* an other module descriptor
* @throws ParseException
*/
protected void mergeWithOtherModuleDescriptor(@SuppressWarnings("rawtypes") List extendTypes,
ModuleDescriptor parent) throws ParseException {
super.mergeWithOtherModuleDescriptor(extendTypes, parent);
if (parent.getParser() instanceof DefaultEasyAntXmlModuleDescriptorParser) {
DefaultEasyAntXmlModuleDescriptorParser parser = (DefaultEasyAntXmlModuleDescriptorParser) parent
.getParser();
if (extendTypes.contains("properties")) {
mergeEasyantProperties(parser.getEasyAntModuleDescriptor().getProperties());
}
if (extendTypes.contains("plugins")) {
mergeEasyantPlugins(parser.getEasyAntModuleDescriptor().getPlugins());
}
if (extendTypes.contains("bindtarget")) {
mergeBindTargets(parser.getEasyAntModuleDescriptor().getExtensionPointsMappings());
}
if (extendTypes.contains("configure-project")) {
mergeConfigureProject(parser.getEasyAntModuleDescriptor().getConfigureProjectDescriptor());
}
}
}
/**
* Merge easyant plugins
*
* @param plugins
* a list of plugins that will be merged with current one
*/
protected void mergeEasyantPlugins(List<PluginDescriptor> plugins) {
for (PluginDescriptor plugin : plugins) {
if (plugin.isInheritable()) {
StringBuilder sb = new StringBuilder("Merging plugin : ");
sb.append(plugin.toString());
if (plugin.getSourceModule() != null) {
sb.append(" from ").append(plugin.getSourceModule().toString());
}
Message.debug(sb.toString());
easyAntModuleDescriptor.addPlugin(plugin);
}
}
}
/**
* Merge easyant properties
*
* @param properties
* a map of properties that will be merged with current one
*/
protected void mergeEasyantProperties(Map<String, PropertyDescriptor> properties) {
for (PropertyDescriptor prop : properties.values()) {
if (prop.isInheritable()) {
IvyContext.getContext().getSettings().getVariableContainer()
.setVariable(prop.getName(), prop.getValue(), true);
StringBuilder sb = new StringBuilder("Merging property");
sb.append(prop.getName());
if (prop.getSourceModule() != null) {
sb.append(" from ").append(prop.getSourceModule().toString());
}
Message.debug(sb.toString());
easyAntModuleDescriptor.getProperties().put(prop.getName(), prop);
}
}
}
protected void mergeBindTargets(List<ExtensionPointMappingDescriptor> extensionPointsMappings) {
for (ExtensionPointMappingDescriptor extensionPointMappingDescriptor : extensionPointsMappings) {
if (extensionPointMappingDescriptor.isInheritable()) {
StringBuilder sb = new StringBuilder("Merging extension-point binding : ");
sb.append(extensionPointMappingDescriptor.toString());
if (extensionPointMappingDescriptor.getSourceModule() != null) {
sb.append(" from ").append(extensionPointMappingDescriptor.getSourceModule().toString());
}
Message.debug(sb.toString());
easyAntModuleDescriptor.addExtensionPointMapping(extensionPointMappingDescriptor);
}
}
}
/**
* Merge configure project
*
* @param configureProjectDescriptor
* {@link ConfigureProjectDescriptor} that will be merged with current one
*/
protected void mergeConfigureProject(ConfigureProjectDescriptor configureProjectDescriptor) {
if (configureProjectDescriptor != null && configureProjectDescriptor.isInheritable()) {
StringBuilder sb = new StringBuilder("Merging configure project : ");
sb.append(configureProjectDescriptor.toString());
if (configureProjectDescriptor.getSourceModule() != null) {
sb.append(" from ").append(configureProjectDescriptor.getSourceModule().toString());
}
Message.debug(sb.toString());
ConfigureProjectDescriptor currentDescriptor = easyAntModuleDescriptor.getConfigureProjectDescriptor();
if (currentDescriptor == null) {
currentDescriptor = new ConfigureProjectDescriptor();
easyAntModuleDescriptor.setConfigureProjectDescriptor(configureProjectDescriptor);
}
currentDescriptor.setDefaultTarget(configureProjectDescriptor.getDefaultTarget());
}
}
/**
* Get the default parent location
*
* @return a string that represents the default parent location
*/
protected String getDefaultParentLocation() {
return "../parent.ivy";
}
/**
* TODO: Fix for IVY-1391, should be removed on next ivy upgrade
*/
/**
* Handle extends elements. It checks :
* <ul>
* <li>filesystem based on location attribute, if no one is specified it will check the default parent location</li>
* <li>cache to find a resolved parent descriptor</li>
* <li>ask repositories to retrieve the parent module descriptor</li>
* </ul>
*
* @param attributes
* @throws ParseException
*/
protected void extendsStarted(Attributes attributes) throws ParseException {
String parentOrganisation = getSettings().substitute(attributes.getValue("organisation"));
String parentModule = getSettings().substitute(attributes.getValue("module"));
String parentRevision = attributes.getValue("revision") != null ? getSettings().substitute(
attributes.getValue("revision")) : Ivy.getWorkingRevision();
String location = attributes.getValue("location") != null ? getSettings().substitute(
attributes.getValue("location")) : getDefaultParentLocation();
ModuleDescriptor parent = null;
String extendType = attributes.getValue("extendType") != null ? getSettings().substitute(
attributes.getValue("extendType").toLowerCase(Locale.US)) : "all";
List<String> extendTypes = Arrays.asList(extendType.split(","));
ModuleId parentMid = new ModuleId(parentOrganisation, parentModule);
ModuleRevisionId parentMrid = new ModuleRevisionId(parentMid, parentRevision);
// check on filesystem based on location attribute (for dev ONLY)
boolean local = false;
try {
parent = parseParentModuleOnFilesystem(location);
if (parent != null) {
ModuleId foundMid = parent.getResolvedModuleRevisionId().getModuleId();
if (!foundMid.equals(parentMid)) {
// the filesystem contains a parent module with different organisation
// or module name; ignore that parent module
Message.info("Found a parent module with unexpected ModuleRevisionId at source location "
+ location + "! Expected: " + parentMid + ". Found: " + foundMid
+ ". This parent module will be ignored.");
parent = null;
}
}
local = parent != null;
} catch (IOException e) {
Message.warn("Unable to parse included ivy file " + location + " : " + e.getMessage());
}
// if not found, tries to resolve using repositories
if (parent == null) {
try {
parent = parseOtherIvyFile(parentMrid);
} catch (ParseException e) {
Message.warn("Unable to parse included ivy file for " + parentMrid.toString() + " : "
+ e.getMessage());
}
}
// if still not found throw an exception
if (parent == null) {
throw new ParseException("Unable to parse included ivy file for " + parentMrid.toString(), 0);
}
DefaultExtendsDescriptor ed = new DefaultExtendsDescriptor(parent, location,
extendTypes.toArray(new String[extendTypes.size()]), local);
getMd().addInheritedDescriptor(ed);
mergeWithOtherModuleDescriptor(extendTypes, parent);
}
/**
* Returns the parent module using the location attribute (for dev purpose).
*
* @param location
* a given location
* @throws IOException
* @throws ParseException
*/
private ModuleDescriptor parseParentModuleOnFilesystem(String location) throws IOException, ParseException {
if (!"file".equals(getDescriptorURL().getProtocol())) {
return null;
}
File file = new File(location);
if (!file.isAbsolute()) {
URL url = getSettings().getRelativeUrlResolver().getURL(getDescriptorURL(), location);
try {
file = new File(new URI(url.toExternalForm()));
} catch (URISyntaxException e) {
file = new File(url.getPath());
}
}
file = FileUtil.normalize(file.getAbsolutePath());
if (!file.exists()) {
Message.verbose("Parent module doesn't exist on the filesystem: " + file.getAbsolutePath());
return null;
}
FileResource res = new FileResource(null, file);
ModuleDescriptorParser parser = ModuleDescriptorParserRegistry.getInstance().getParser(res);
return parser.parseDescriptor(getSettings(), file.toURI().toURL(), res, isValidate());
}
}
}