org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser Maven / Gradle / Ivy
/*
* 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.ivy.plugins.parser;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.Configuration;
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.plugins.repository.ResourceHelper;
import org.apache.ivy.plugins.repository.url.URLResource;
import org.apache.ivy.util.Message;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
public abstract class AbstractModuleDescriptorParser implements ModuleDescriptorParser {
public ModuleDescriptor parseDescriptor(ParserSettings ivySettings, URL descriptorURL,
boolean validate) throws ParseException, IOException {
return parseDescriptor(ivySettings, descriptorURL,
new URLResource(descriptorURL), validate);
}
public String getType() {
return "ivy";
}
public Artifact getMetadataArtifact(ModuleRevisionId mrid, Resource res) {
return DefaultArtifact.newIvyArtifact(mrid, new Date(res.getLastModified()));
}
protected abstract static class AbstractParser extends DefaultHandler {
private static final String DEFAULT_CONF_MAPPING = "*->*";
private String defaultConf; // used only as defaultconf, not used for
// guesssing right side part of a mapping
private String defaultConfMapping; // same as default conf but is used
// for guesssing right side part of a mapping
private DefaultDependencyDescriptor defaultConfMappingDescriptor;
private Resource res;
private List errors = new ArrayList();
private DefaultModuleDescriptor md;
private ModuleDescriptorParser parser;
protected AbstractParser(ModuleDescriptorParser parser) {
this.parser = parser;
}
public ModuleDescriptorParser getModuleDescriptorParser() {
return parser;
}
protected void checkErrors() throws ParseException {
if (!errors.isEmpty()) {
throw new ParseException(errors.toString(), 0);
}
}
public void setResource(Resource res) {
this.res = res; // used for log and date only
md = new DefaultModuleDescriptor(parser, res);
md.setLastModified(ResourceHelper.getLastModifiedOrDefault(res));
}
protected Resource getResource() {
return res;
}
protected String getDefaultConfMapping() {
return defaultConfMapping;
}
protected void setDefaultConfMapping(String defaultConf) {
defaultConfMapping = defaultConf;
}
protected void parseDepsConfs(String confs, DefaultDependencyDescriptor dd) {
parseDepsConfs(confs, dd, defaultConfMapping != null);
}
protected void parseDepsConfs(String confs, DefaultDependencyDescriptor dd,
boolean useDefaultMappingToGuessRightOperande) {
parseDepsConfs(confs, dd, useDefaultMappingToGuessRightOperande, true);
}
protected void parseDepsConfs(String confs, DefaultDependencyDescriptor dd,
boolean useDefaultMappingToGuessRightOperande, boolean evaluateConditions) {
if (confs == null) {
return;
}
String[] conf = confs.split(";");
parseDepsConfs(conf, dd, useDefaultMappingToGuessRightOperande, evaluateConditions);
}
protected void parseDepsConfs(String[] conf, DefaultDependencyDescriptor dd,
boolean useDefaultMappingToGuessRightOperande) {
parseDepsConfs(conf, dd, useDefaultMappingToGuessRightOperande, true);
}
protected void parseDepsConfs(String[] conf, DefaultDependencyDescriptor dd,
boolean useDefaultMappingToGuessRightOperande, boolean evaluateConditions) {
replaceConfigurationWildcards(md);
for (int i = 0; i < conf.length; i++) {
String[] ops = conf[i].split("->");
if (ops.length == 1) {
String[] modConfs = ops[0].split(",");
if (!useDefaultMappingToGuessRightOperande) {
for (int j = 0; j < modConfs.length; j++) {
dd.addDependencyConfiguration(modConfs[j].trim(), modConfs[j].trim());
}
} else {
for (int j = 0; j < modConfs.length; j++) {
String[] depConfs = getDefaultConfMappingDescriptor()
.getDependencyConfigurations(modConfs[j]);
if (depConfs.length > 0) {
for (int k = 0; k < depConfs.length; k++) {
String mappedDependency = evaluateConditions
? evaluateCondition(depConfs[k].trim(), dd)
: depConfs[k].trim();
if (mappedDependency != null) {
dd.addDependencyConfiguration(modConfs[j].trim(),
mappedDependency);
}
}
} else {
// no default mapping found for this configuration, map
// configuration to itself
dd.addDependencyConfiguration(modConfs[j].trim(), modConfs[j]
.trim());
}
}
}
} else if (ops.length == 2) {
String[] modConfs = ops[0].split(",");
String[] depConfs = ops[1].split(",");
for (int j = 0; j < modConfs.length; j++) {
for (int k = 0; k < depConfs.length; k++) {
String mappedDependency = evaluateConditions ? evaluateCondition(
depConfs[k].trim(), dd) : depConfs[k].trim();
if (mappedDependency != null) {
dd.addDependencyConfiguration(modConfs[j].trim(), mappedDependency);
}
}
}
} else {
addError("invalid conf " + conf[i] + " for " + dd);
}
}
if (md.isMappingOverride()) {
addExtendingConfigurations(conf, dd, useDefaultMappingToGuessRightOperande);
}
}
/**
* Evaluate the optional condition in the given configuration, like "[org=MYORG]confX". If
* the condition evaluates to true, the configuration is returned, if the condition
* evaluatate to false, null is returned. If there are no conditions, the configuration
* itself is returned.
*
* @param conf
* the configuration to evaluate
* @param dd
* the dependencydescriptor to which the configuration will be added
* @return the evaluated condition
*/
private String evaluateCondition(String conf, DefaultDependencyDescriptor dd) {
if (conf.charAt(0) != '[') {
return conf;
}
int endConditionIndex = conf.indexOf(']');
if (endConditionIndex == -1) {
addError("invalid conf " + conf + " for " + dd);
return null;
}
String condition = conf.substring(1, endConditionIndex);
int notEqualIndex = condition.indexOf("!=");
if (notEqualIndex == -1) {
int equalIndex = condition.indexOf('=');
if (equalIndex == -1) {
addError("invalid conf " + conf + " for " + dd.getDependencyRevisionId());
return null;
}
String leftOp = condition.substring(0, equalIndex).trim();
String rightOp = condition.substring(equalIndex + 1).trim();
// allow organisation synonyms, like 'org' or 'organization'
if (leftOp.equals("org") || leftOp.equals("organization")) {
leftOp = "organisation";
}
String attrValue = dd.getAttribute(leftOp);
if (!rightOp.equals(attrValue)) {
return null;
}
} else {
String leftOp = condition.substring(0, notEqualIndex).trim();
String rightOp = condition.substring(notEqualIndex + 2).trim();
// allow organisation synonyms, like 'org' or 'organization'
if (leftOp.equals("org") || leftOp.equals("organization")) {
leftOp = "organisation";
}
String attrValue = dd.getAttribute(leftOp);
if (rightOp.equals(attrValue)) {
return null;
}
}
return conf.substring(endConditionIndex + 1);
}
private void addExtendingConfigurations(String[] confs, DefaultDependencyDescriptor dd,
boolean useDefaultMappingToGuessRightOperande) {
for (int i = 0; i < confs.length; i++) {
addExtendingConfigurations(confs[i], dd, useDefaultMappingToGuessRightOperande);
}
}
private void addExtendingConfigurations(String conf, DefaultDependencyDescriptor dd,
boolean useDefaultMappingToGuessRightOperande) {
Set configsToAdd = new HashSet();
Configuration[] configs = md.getConfigurations();
for (int i = 0; i < configs.length; i++) {
String[] ext = configs[i].getExtends();
for (int j = 0; j < ext.length; j++) {
if (conf.equals(ext[j])) {
String configName = configs[i].getName();
configsToAdd.add(configName);
addExtendingConfigurations(configName, dd,
useDefaultMappingToGuessRightOperande);
}
}
}
String[] confs = (String[]) configsToAdd.toArray(new String[configsToAdd.size()]);
parseDepsConfs(confs, dd, useDefaultMappingToGuessRightOperande);
}
protected DependencyDescriptor getDefaultConfMappingDescriptor() {
if (defaultConfMappingDescriptor == null) {
defaultConfMappingDescriptor = new DefaultDependencyDescriptor(ModuleRevisionId
.newInstance("", "", ""), false);
parseDepsConfs(defaultConfMapping, defaultConfMappingDescriptor, false, false);
}
return defaultConfMappingDescriptor;
}
protected void addError(String msg) {
if (res != null) {
errors.add(msg + " in " + res + "\n");
} else {
errors.add(msg + "\n");
}
}
public void warning(SAXParseException ex) {
Message.warn("xml parsing: " + getLocationString(ex) + ": " + ex.getMessage());
}
public void error(SAXParseException ex) {
addError("xml parsing: " + getLocationString(ex) + ": " + ex.getMessage());
}
public void fatalError(SAXParseException ex) throws SAXException {
addError("[Fatal Error] " + getLocationString(ex) + ": " + ex.getMessage());
}
/** Returns a string of the location. */
private String getLocationString(SAXParseException ex) {
StringBuffer str = new StringBuffer();
String systemId = ex.getSystemId();
if (systemId != null) {
int index = systemId.lastIndexOf('/');
if (index != -1) {
systemId = systemId.substring(index + 1);
}
str.append(systemId);
} else if (getResource() != null) {
str.append(getResource().toString());
}
str.append(':');
str.append(ex.getLineNumber());
str.append(':');
str.append(ex.getColumnNumber());
return str.toString();
} // getLocationString(SAXParseException):String
protected String getDefaultConf() {
return defaultConfMapping != null ? defaultConfMapping
: (defaultConf != null ? defaultConf : DEFAULT_CONF_MAPPING);
}
protected void setDefaultConf(String defaultConf) {
this.defaultConf = defaultConf;
}
public ModuleDescriptor getModuleDescriptor() throws ParseException {
checkErrors();
return md;
}
protected Date getDefaultPubDate() {
return new Date(md.getLastModified());
}
private void replaceConfigurationWildcards(ModuleDescriptor md) {
Configuration[] configs = md.getConfigurations();
for (int i = 0; i < configs.length; i++) {
configs[i].replaceWildcards(md);
}
}
protected void setMd(DefaultModuleDescriptor md) {
this.md = md;
}
protected DefaultModuleDescriptor getMd() {
return md;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy