blob: 88520f12cd2f10e10daf701ff3ae7e7dde8c209f [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.ivy.ant;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.apache.ivy.core.cache.ArtifactOrigin;
import org.apache.ivy.core.cache.RepositoryCacheManager;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.report.ArtifactDownloadReport;
import org.apache.ivy.core.resolve.IvyNode;
import org.apache.ivy.core.resolve.ResolveOptions;
import org.apache.ivy.core.resolve.ResolvedModuleRevision;
import org.apache.ivy.core.retrieve.RetrieveOptions;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
/**
* Generates a report of all artifacts involved during the last resolve.
*/
public class IvyArtifactReport extends IvyPostResolveTask {
private File tofile;
private String pattern;
public File getTofile() {
return tofile;
}
public void setTofile(File aFile) {
tofile = aFile;
}
public String getPattern() {
return pattern;
}
public void setPattern(String aPattern) {
pattern = aPattern;
}
public void doExecute() throws BuildException {
prepareAndCheck();
if (tofile == null) {
throw new BuildException(
"no destination file name: please provide it through parameter 'tofile'");
}
pattern = getProperty(pattern, getSettings(), "ivy.retrieve.pattern");
try {
String[] confs = splitConfs(getConf());
ModuleDescriptor md = null;
if (getResolveId() != null) {
md = (ModuleDescriptor) getResolvedDescriptor(getResolveId());
} else {
md = (ModuleDescriptor) getResolvedDescriptor(getOrganisation(), getModule(), false);
}
IvyNode[] dependencies = getIvyInstance().getResolveEngine().getDependencies(
md,
((ResolveOptions) new ResolveOptions().setLog(getLog())).setConfs(confs)
.setResolveId(getResolveId()).setValidate(doValidate(getSettings())), null);
Map artifactsToCopy = getIvyInstance().getRetrieveEngine().determineArtifactsToCopy(
ModuleRevisionId.newInstance(getOrganisation(), getModule(), getRevision()),
pattern,
((RetrieveOptions) new RetrieveOptions().setLog(getLog())).setConfs(confs)
.setResolveId(getResolveId()));
Map moduleRevToArtifactsMap = new HashMap();
for (Iterator iter = artifactsToCopy.keySet().iterator(); iter.hasNext();) {
ArtifactDownloadReport artifact = (ArtifactDownloadReport) iter.next();
Set moduleRevArtifacts = (Set) moduleRevToArtifactsMap.get(artifact.getArtifact()
.getModuleRevisionId());
if (moduleRevArtifacts == null) {
moduleRevArtifacts = new HashSet();
moduleRevToArtifactsMap.put(artifact.getArtifact().getModuleRevisionId(),
moduleRevArtifacts);
}
moduleRevArtifacts.add(artifact);
}
generateXml(dependencies, moduleRevToArtifactsMap, artifactsToCopy);
} catch (ParseException e) {
log(e.getMessage(), Project.MSG_ERR);
throw new BuildException("syntax errors in ivy file: " + e, e);
} catch (IOException e) {
throw new BuildException("impossible to generate report: " + e, e);
}
}
private void generateXml(IvyNode[] dependencies, Map moduleRevToArtifactsMap,
Map artifactsToCopy) {
try {
FileOutputStream fileOuputStream = new FileOutputStream(tofile);
try {
TransformerHandler saxHandler = createTransformerHandler(fileOuputStream);
saxHandler.startDocument();
saxHandler.startElement(null, "modules", "modules", new AttributesImpl());
for (int i = 0; i < dependencies.length; i++) {
IvyNode dependency = dependencies[i];
if (dependency.getModuleRevision() == null || dependency.isCompletelyEvicted()) {
continue;
}
startModule(saxHandler, dependency);
Set artifactsOfModuleRev = (Set) moduleRevToArtifactsMap.get(dependency
.getModuleRevision().getId());
if (artifactsOfModuleRev != null) {
for (Iterator iter = artifactsOfModuleRev.iterator(); iter.hasNext();) {
ArtifactDownloadReport artifact = (ArtifactDownloadReport) iter.next();
RepositoryCacheManager cache = dependency.getModuleRevision()
.getArtifactResolver().getRepositoryCacheManager();
startArtifact(saxHandler, artifact.getArtifact());
writeOriginLocationIfPresent(cache, saxHandler, artifact);
writeCacheLocationIfPresent(cache, saxHandler, artifact);
Set artifactDestPaths = (Set) artifactsToCopy.get(artifact);
for (Iterator iterator = artifactDestPaths.iterator(); iterator
.hasNext();) {
String artifactDestPath = (String) iterator.next();
writeRetrieveLocation(saxHandler, artifactDestPath);
}
saxHandler.endElement(null, "artifact", "artifact");
}
}
saxHandler.endElement(null, "module", "module");
}
saxHandler.endElement(null, "modules", "modules");
saxHandler.endDocument();
} finally {
fileOuputStream.close();
}
} catch (SAXException e) {
throw new BuildException("impossible to generate report", e);
} catch (TransformerConfigurationException e) {
throw new BuildException("impossible to generate report", e);
} catch (IOException e) {
throw new BuildException("impossible to generate report", e);
}
}
private TransformerHandler createTransformerHandler(FileOutputStream fileOuputStream)
throws TransformerFactoryConfigurationError, TransformerConfigurationException,
SAXException {
SAXTransformerFactory transformerFact = (SAXTransformerFactory) SAXTransformerFactory
.newInstance();
TransformerHandler saxHandler = transformerFact.newTransformerHandler();
saxHandler.getTransformer().setOutputProperty(OutputKeys.ENCODING, "UTF-8");
saxHandler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");
saxHandler.setResult(new StreamResult(fileOuputStream));
return saxHandler;
}
private void startModule(TransformerHandler saxHandler, IvyNode dependency) throws SAXException {
AttributesImpl moduleAttrs = new AttributesImpl();
moduleAttrs.addAttribute(null, "organisation", "organisation", "CDATA", dependency
.getModuleId().getOrganisation());
moduleAttrs.addAttribute(null, "name", "name", "CDATA", dependency.getModuleId().getName());
ResolvedModuleRevision moduleRevision = dependency.getModuleRevision();
moduleAttrs.addAttribute(null, "rev", "rev", "CDATA", moduleRevision.getId().getRevision());
moduleAttrs.addAttribute(null, "status", "status", "CDATA", moduleRevision.getDescriptor()
.getStatus());
saxHandler.startElement(null, "module", "module", moduleAttrs);
}
private void startArtifact(TransformerHandler saxHandler, Artifact artifact)
throws SAXException {
AttributesImpl artifactAttrs = new AttributesImpl();
artifactAttrs.addAttribute(null, "name", "name", "CDATA", artifact.getName());
artifactAttrs.addAttribute(null, "ext", "ext", "CDATA", artifact.getExt());
artifactAttrs.addAttribute(null, "type", "type", "CDATA", artifact.getType());
saxHandler.startElement(null, "artifact", "artifact", artifactAttrs);
}
private void writeOriginLocationIfPresent(RepositoryCacheManager cache,
TransformerHandler saxHandler, ArtifactDownloadReport artifact) throws IOException,
SAXException {
ArtifactOrigin origin = artifact.getArtifactOrigin();
if (!ArtifactOrigin.isUnknown(origin)) {
String originName = origin.getLocation();
boolean isOriginLocal = origin.isLocal();
String originLocation;
AttributesImpl originLocationAttrs = new AttributesImpl();
if (isOriginLocal) {
originLocationAttrs.addAttribute(null, "is-local", "is-local", "CDATA", "true");
originLocation = originName.replace('\\', '/');
} else {
originLocationAttrs.addAttribute(null, "is-local", "is-local", "CDATA", "false");
originLocation = originName;
}
saxHandler
.startElement(null, "origin-location", "origin-location", originLocationAttrs);
char[] originLocationAsChars = originLocation.toCharArray();
saxHandler.characters(originLocationAsChars, 0, originLocationAsChars.length);
saxHandler.endElement(null, "origin-location", "origin-location");
}
}
private void writeCacheLocationIfPresent(RepositoryCacheManager cache,
TransformerHandler saxHandler, ArtifactDownloadReport artifact) throws SAXException {
File archiveInCache = artifact.getLocalFile();
if (archiveInCache != null) {
saxHandler.startElement(null, "cache-location", "cache-location", new AttributesImpl());
char[] archiveInCacheAsChars = archiveInCache.getPath().replace('\\', '/')
.toCharArray();
saxHandler.characters(archiveInCacheAsChars, 0, archiveInCacheAsChars.length);
saxHandler.endElement(null, "cache-location", "cache-location");
}
}
private void writeRetrieveLocation(TransformerHandler saxHandler, String artifactDestPath)
throws SAXException {
artifactDestPath = removeLeadingPath(getProject().getBaseDir(), new File(artifactDestPath));
saxHandler.startElement(null, "retrieve-location", "retrieve-location",
new AttributesImpl());
char[] artifactDestPathAsChars = artifactDestPath.replace('\\', '/').toCharArray();
saxHandler.characters(artifactDestPathAsChars, 0, artifactDestPathAsChars.length);
saxHandler.endElement(null, "retrieve-location", "retrieve-location");
}
// method largely inspired by ant 1.6.5 FileUtils method
public String removeLeadingPath(File leading, File path) {
String l = leading.getAbsolutePath();
String p = path.getAbsolutePath();
if (l.equals(p)) {
return "";
}
// ensure that l ends with a /
// so we never think /foo was a parent directory of /foobar
if (!l.endsWith(File.separator)) {
l += File.separator;
}
return (p.startsWith(l)) ? p.substring(l.length()) : p;
}
}