| /* |
| * 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; |
| } |
| } |