blob: 89c7d93d8a4d4953c9ecafeb7b83c9c6d3cb4d8f [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
*
* https://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.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.ivy.Ivy;
import org.apache.ivy.core.cache.ResolutionCacheManager;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
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.core.report.ResolveReport;
import org.apache.ivy.core.resolve.ResolveOptions;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.plugins.matcher.PatternMatcher;
import org.apache.ivy.plugins.report.XmlReportOutputter;
import org.apache.ivy.util.FileUtil;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.XSLTProcess;
/**
* Generates a report of dependencies of a set of modules in the repository. The set of modules is
* specified using organisation/module and matcher.
*/
public class IvyRepositoryReport extends IvyTask {
private String organisation = "*";
private String module;
private String branch;
private String revision = "latest.integration";
private String matcher = PatternMatcher.EXACT_OR_REGEXP;
private File todir;
private boolean graph = false;
private boolean dot = false;
private boolean xml = true;
private boolean xsl = false;
private String xslFile;
private String outputname = "ivy-repository-report";
private String xslext = "html";
private final List<XSLTProcess.Param> params = new ArrayList<>();
public void doExecute() throws BuildException {
Ivy ivy = getIvyInstance();
IvySettings settings = ivy.getSettings();
if (xsl && xslFile == null) {
throw new BuildException("xsl file is mandatory when using xsl generation");
}
if (module == null && PatternMatcher.EXACT.equals(matcher)) {
throw new BuildException("no module name provided for ivy repository graph task: "
+ "It can either be set explicitly via the attribute 'module' or "
+ "via 'ivy.module' property or a prior call to <resolve/>");
} else if (module == null && !PatternMatcher.EXACT.equals(matcher)) {
module = PatternMatcher.ANY_EXPRESSION;
}
ModuleRevisionId moduleRevisionId = ModuleRevisionId.newInstance(organisation, module, revision);
try {
ModuleRevisionId criteria = (revision == null) || settings.getVersionMatcher().isDynamic(moduleRevisionId)
? new ModuleRevisionId(new ModuleId(organisation, module), branch, "*")
: new ModuleRevisionId(new ModuleId(organisation, module), branch, revision);
ModuleRevisionId[] mrids = ivy.listModules(criteria, settings.getMatcher(matcher));
// replace all found revisions with the original requested revision
Set<ModuleRevisionId> modules = new HashSet<>();
for (ModuleRevisionId mrid : mrids) {
modules.add(ModuleRevisionId.newInstance(mrid, revision));
}
mrids = modules.toArray(new ModuleRevisionId[modules.size()]);
ModuleDescriptor md = DefaultModuleDescriptor.newCallerInstance(mrids, true, false);
String resolveId = ResolveOptions.getDefaultResolveId(md);
ResolveReport report = ivy.resolve(md, new ResolveOptions().setResolveId(resolveId)
.setValidate(doValidate(settings)));
ResolutionCacheManager cacheMgr = getIvyInstance().getResolutionCacheManager();
new XmlReportOutputter().output(report, cacheMgr, new ResolveOptions());
if (graph) {
gengraph(cacheMgr, md.getModuleRevisionId().getOrganisation(),
md.getModuleRevisionId().getName());
}
if (dot) {
gendot(cacheMgr, md.getModuleRevisionId().getOrganisation(),
md.getModuleRevisionId().getName());
}
if (xml) {
FileUtil.copy(cacheMgr.getConfigurationResolveReportInCache(resolveId, "default"),
new File(getTodir(), outputname + ".xml"), null);
}
if (xsl) {
genreport(cacheMgr, md.getModuleRevisionId().getOrganisation(),
md.getModuleRevisionId().getName());
}
} catch (Exception e) {
throw new BuildException("impossible to generate graph for " + moduleRevisionId + ": " + e, e);
}
}
private void genreport(ResolutionCacheManager cache, String organisation, String module) {
// first process the report with xslt
XSLTProcess xslt = new XSLTProcess();
xslt.setTaskName(getTaskName());
xslt.setProject(getProject());
xslt.init();
String resolveId = ResolveOptions.getDefaultResolveId(new ModuleId(organisation, module));
xslt.setIn(cache.getConfigurationResolveReportInCache(resolveId, "default"));
xslt.setOut(new File(getTodir(), outputname + "." + xslext));
xslt.setStyle(xslFile);
XSLTProcess.Param xslExt = xslt.createParam();
xslExt.setName("extension");
xslExt.setExpression(xslext);
// add the provided XSLT parameters
for (XSLTProcess.Param param : params) {
XSLTProcess.Param realParam = xslt.createParam();
realParam.setName(param.getName());
realParam.setExpression(param.getExpression());
}
xslt.execute();
}
private void gengraph(ResolutionCacheManager cache, String organisation, String module)
throws IOException {
gen(cache, organisation, module, getGraphStylePath(cache.getResolutionCacheRoot()),
"graphml");
}
private String getGraphStylePath(File cache) throws IOException {
// style should be a file (and not an url)
// so we have to copy it from classpath to cache
File style = new File(cache, "ivy-report-graph-all.xsl");
FileUtil.copy(XmlReportOutputter.class.getResourceAsStream("ivy-report-graph-all.xsl"),
style, null);
return style.getAbsolutePath();
}
private void gendot(ResolutionCacheManager cache, String organisation, String module)
throws IOException {
gen(cache, organisation, module, getDotStylePath(cache.getResolutionCacheRoot()), "dot");
}
private String getDotStylePath(File cache) throws IOException {
// style should be a file (and not an url)
// so we have to copy it from classpath to cache
File style = new File(cache, "ivy-report-dot-all.xsl");
FileUtil.copy(XmlReportOutputter.class.getResourceAsStream("ivy-report-dot-all.xsl"),
style, null);
return style.getAbsolutePath();
}
private void gen(ResolutionCacheManager cache, String organisation, String module,
String style, String ext) {
XSLTProcess xslt = new XSLTProcess();
xslt.setTaskName(getTaskName());
xslt.setProject(getProject());
xslt.init();
String resolveId = ResolveOptions.getDefaultResolveId(new ModuleId(organisation, module));
xslt.setIn(cache.getConfigurationResolveReportInCache(resolveId, "default"));
xslt.setOut(new File(getTodir(), outputname + "." + ext));
xslt.setBasedir(cache.getResolutionCacheRoot());
xslt.setStyle(style);
xslt.execute();
}
public File getTodir() {
if (todir == null && getProject() != null) {
return getProject().getBaseDir();
}
return todir;
}
public void setTodir(File todir) {
this.todir = todir;
}
public boolean isGraph() {
return graph;
}
public void setGraph(boolean graph) {
this.graph = graph;
}
public String getXslfile() {
return xslFile;
}
public void setXslfile(String xslFile) {
this.xslFile = xslFile;
}
public boolean isXml() {
return xml;
}
public void setXml(boolean xml) {
this.xml = xml;
}
public boolean isXsl() {
return xsl;
}
public void setXsl(boolean xsl) {
this.xsl = xsl;
}
public String getXslext() {
return xslext;
}
public void setXslext(String xslext) {
this.xslext = xslext;
}
public XSLTProcess.Param createParam() {
XSLTProcess.Param result = new XSLTProcess.Param();
params.add(result);
return result;
}
public String getOutputname() {
return outputname;
}
public void setOutputname(String outputpattern) {
outputname = outputpattern;
}
public void setCache(File cache) {
cacheAttributeNotSupported();
}
public String getMatcher() {
return matcher;
}
public void setMatcher(String matcher) {
this.matcher = matcher;
}
public String getModule() {
return module;
}
public void setModule(String module) {
this.module = module;
}
public String getOrganisation() {
return organisation;
}
public void setOrganisation(String organisation) {
this.organisation = organisation;
}
public String getRevision() {
return revision;
}
public void setRevision(String revision) {
this.revision = revision;
}
public String getBranch() {
return branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
public boolean isDot() {
return dot;
}
public void setDot(boolean dot) {
this.dot = dot;
}
}