/*
* Copyright 2013 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.publish.ivy.internal.publisher;
import org.gradle.api.Action;
import org.gradle.api.UncheckedIOException;
import org.gradle.api.XmlProvider;
import org.gradle.api.artifacts.DependencyArtifact;
import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.publish.ivy.IvyArtifact;
import org.gradle.api.publish.ivy.IvyConfiguration;
import org.gradle.api.publish.ivy.internal.dependency.IvyDependencyInternal;
import org.gradle.internal.xml.SimpleXmlWriter;
import org.gradle.internal.xml.XmlTransformer;
import org.gradle.util.CollectionUtils;
import javax.xml.namespace.QName;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class IvyDescriptorFileGenerator {
private static final String IVY_FILE_ENCODING = "UTF-8";
private static final String IVY_DATE_PATTERN = "yyyyMMddHHmmss";
private final SimpleDateFormat ivyDateFormat = new SimpleDateFormat(IVY_DATE_PATTERN);
private final IvyPublicationIdentity projectIdentity;
private String branch;
private String status;
private Map<QName, String> extraInfo;
private XmlTransformer xmlTransformer = new XmlTransformer();
private List<IvyConfiguration> configurations = new ArrayList<IvyConfiguration>();
private List<IvyArtifact> artifacts = new ArrayList<IvyArtifact>();
private List<IvyDependencyInternal> dependencies = new ArrayList<IvyDependencyInternal>();
public IvyDescriptorFileGenerator(IvyPublicationIdentity projectIdentity) {
this.projectIdentity = projectIdentity;
}
public void setStatus(String status) {
this.status = status;
}
public void setBranch(String branch) {
this.branch = branch;
}
public Map<QName, String> getExtraInfo() {
return extraInfo;
}
public void setExtraInfo(Map<QName, String> extraInfo) {
this.extraInfo = extraInfo;
}
public IvyDescriptorFileGenerator addConfiguration(IvyConfiguration ivyConfiguration) {
configurations.add(ivyConfiguration);
return this;
}
public IvyDescriptorFileGenerator addArtifact(IvyArtifact ivyArtifact) {
artifacts.add(ivyArtifact);
return this;
}
public IvyDescriptorFileGenerator addDependency(IvyDependencyInternal ivyDependency) {
dependencies.add(ivyDependency);
return this;
}
public IvyDescriptorFileGenerator withXml(final Action<XmlProvider> action) {
xmlTransformer.addAction(action);
return this;
}
public IvyDescriptorFileGenerator writeTo(File file) {
xmlTransformer.transform(file, IVY_FILE_ENCODING, new Action<Writer>() {
public void execute(Writer writer) {
try {
writeDescriptor(writer);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
});
return this;
}
private void writeDescriptor(final Writer writer) throws IOException {
OptionalAttributeXmlWriter xmlWriter = new OptionalAttributeXmlWriter(writer, " ", IVY_FILE_ENCODING);
xmlWriter.startElement("ivy-module").attribute("version", "2.0");
if (usesClassifier()) {
xmlWriter.attribute("xmlns:m", "http://ant.apache.org/ivy/maven");
}
xmlWriter.startElement("info")
.attribute("organisation", projectIdentity.getOrganisation())
.attribute("module", projectIdentity.getModule())
.attribute("branch", branch)
.attribute("revision", projectIdentity.getRevision())
.attribute("status", status)
.attribute("publication", ivyDateFormat.format(new Date()));
if (extraInfo != null) {
for (Map.Entry<QName, String> entry : extraInfo.entrySet()) {
if (entry.getKey() != null) {
xmlWriter.startElement("ns:" + entry.getKey().getLocalPart())
.attribute("xmlns:ns", entry.getKey().getNamespaceURI())
.characters(entry.getValue())
.endElement();
}
}
}
xmlWriter.endElement();
writeConfigurations(xmlWriter);
writePublications(xmlWriter);
writeDependencies(xmlWriter);
xmlWriter.endElement();
}
private boolean usesClassifier() {
for (IvyArtifact artifact : artifacts) {
if (artifact.getClassifier() != null) {
return true;
}
}
for (IvyDependencyInternal dependency : this.dependencies) {
for (DependencyArtifact dependencyArtifact : dependency.getArtifacts()) {
if (dependencyArtifact.getClassifier() != null) {
return true;
}
}
}
return false;
}
private void writeConfigurations(OptionalAttributeXmlWriter xmlWriter) throws IOException {
xmlWriter.startElement("configurations");
for (IvyConfiguration configuration : configurations) {
xmlWriter.startElement("conf")
.attribute("name", configuration.getName())
.attribute("visibility", "public");
if (configuration.getExtends().size() > 0) {
xmlWriter.attribute("extends", CollectionUtils.join(",", configuration.getExtends()));
}
xmlWriter.endElement();
}
xmlWriter.endElement();
}
private void writePublications(OptionalAttributeXmlWriter xmlWriter) throws IOException {
xmlWriter.startElement("publications");
for (IvyArtifact artifact : artifacts) {
xmlWriter.startElement("artifact")
.attribute("name", artifact.getName())
.attribute("type", artifact.getType())
.attribute("ext", artifact.getExtension())
.attribute("conf", artifact.getConf())
.attribute("m:classifier", artifact.getClassifier())
.endElement();
}
xmlWriter.endElement();
}
private void writeDependencies(OptionalAttributeXmlWriter xmlWriter) throws IOException {
xmlWriter.startElement("dependencies");
for (IvyDependencyInternal dependency : dependencies) {
xmlWriter.startElement("dependency")
.attribute("org", dependency.getOrganisation())
.attribute("name", dependency.getModule())
.attribute("rev", dependency.getRevision())
.attribute("conf", dependency.getConfMapping());
if (!dependency.isTransitive()) {
xmlWriter.attribute("transitive", "false");
}
for (DependencyArtifact dependencyArtifact : dependency.getArtifacts()) {
printDependencyArtifact(dependencyArtifact, xmlWriter);
}
for(ExcludeRule excludeRule : dependency.getExcludeRules()) {
writeDependencyExclude(excludeRule, xmlWriter);
}
xmlWriter.endElement();
}
xmlWriter.endElement();
}
private void writeDependencyExclude(ExcludeRule excludeRule, OptionalAttributeXmlWriter xmlWriter) throws IOException {
xmlWriter.startElement("exclude")
.attribute("org", excludeRule.getGroup())
.attribute("module", excludeRule.getModule())
.endElement();
}
private void printDependencyArtifact(DependencyArtifact dependencyArtifact, OptionalAttributeXmlWriter xmlWriter) throws IOException {
// TODO Use IvyArtifact here
xmlWriter.startElement("artifact")
.attribute("name", dependencyArtifact.getName())
.attribute("type", dependencyArtifact.getType())
.attribute("ext", dependencyArtifact.getExtension())
.attribute("m:classifier", dependencyArtifact.getClassifier())
.endElement();
}
private static class OptionalAttributeXmlWriter extends SimpleXmlWriter {
public OptionalAttributeXmlWriter(Writer writer, String indent, String encoding) throws IOException {
super(writer, indent, encoding);
}
@Override
public OptionalAttributeXmlWriter startElement(String name) throws IOException {
super.startElement(name);
return this;
}
@Override
public OptionalAttributeXmlWriter attribute(String name, String value) throws IOException {
if (value != null) {
super.attribute(name, value);
}
return this;
}
}
}