001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.ivy.ant;
019:
020: import java.io.BufferedInputStream;
021: import java.io.BufferedOutputStream;
022: import java.io.File;
023: import java.io.FileInputStream;
024: import java.io.FileOutputStream;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.io.OutputStream;
028: import java.util.ArrayList;
029: import java.util.Iterator;
030: import java.util.List;
031:
032: import javax.xml.transform.Source;
033: import javax.xml.transform.Transformer;
034: import javax.xml.transform.TransformerConfigurationException;
035: import javax.xml.transform.TransformerException;
036: import javax.xml.transform.TransformerFactory;
037: import javax.xml.transform.stream.StreamResult;
038: import javax.xml.transform.stream.StreamSource;
039:
040: import org.apache.ivy.Ivy;
041: import org.apache.ivy.core.IvyPatternHelper;
042: import org.apache.ivy.core.cache.ResolutionCacheManager;
043: import org.apache.ivy.core.module.id.ModuleId;
044: import org.apache.ivy.core.resolve.ResolveOptions;
045: import org.apache.ivy.core.settings.IvySettings;
046: import org.apache.ivy.plugins.report.XmlReportOutputter;
047: import org.apache.ivy.util.FileUtil;
048: import org.apache.ivy.util.Message;
049: import org.apache.tools.ant.BuildException;
050: import org.apache.tools.ant.taskdefs.XSLTProcess;
051: import org.apache.tools.ant.util.JAXPUtils;
052:
053: /**
054: * This ant task let users generates reports (html, xml, graphml, ...) from the last resolve done.
055: */
056: public class IvyReport extends IvyTask {
057: private File todir;
058:
059: private String organisation;
060:
061: private String module;
062:
063: private String conf;
064:
065: private boolean graph = true;
066:
067: private boolean dot = false;
068:
069: private boolean xml = false;
070:
071: private boolean xsl = true;
072:
073: private File xslFile;
074:
075: private String outputpattern;
076:
077: private String xslext = "html";
078:
079: private List params = new ArrayList();
080:
081: private String resolveId;
082:
083: public File getTodir() {
084: return todir;
085: }
086:
087: public void setTodir(File todir) {
088: this .todir = todir;
089: }
090:
091: public void setCache(File cache) {
092: cacheAttributeNotSupported();
093: }
094:
095: public String getConf() {
096: return conf;
097: }
098:
099: public void setConf(String conf) {
100: this .conf = conf;
101: }
102:
103: public String getModule() {
104: return module;
105: }
106:
107: public void setModule(String module) {
108: this .module = module;
109: }
110:
111: public String getOrganisation() {
112: return organisation;
113: }
114:
115: public void setOrganisation(String organisation) {
116: this .organisation = organisation;
117: }
118:
119: public boolean isGraph() {
120: return graph;
121: }
122:
123: public void setGraph(boolean graph) {
124: this .graph = graph;
125: }
126:
127: public File getXslfile() {
128: return xslFile;
129: }
130:
131: public void setXslfile(File xslFile) {
132: this .xslFile = xslFile;
133: }
134:
135: public String getOutputpattern() {
136: return outputpattern;
137: }
138:
139: public void setOutputpattern(String outputpattern) {
140: this .outputpattern = outputpattern;
141: }
142:
143: public String getResolveId() {
144: return resolveId;
145: }
146:
147: public void setResolveId(String resolveId) {
148: this .resolveId = resolveId;
149: }
150:
151: public void doExecute() throws BuildException {
152: Ivy ivy = getIvyInstance();
153: IvySettings settings = ivy.getSettings();
154:
155: organisation = getProperty(organisation, settings,
156: "ivy.organisation", resolveId);
157: module = getProperty(module, settings, "ivy.module", resolveId);
158: conf = getProperty(conf, settings,
159: "ivy.resolved.configurations", resolveId);
160: if ("*".equals(conf)) {
161: conf = getProperty(settings, "ivy.resolved.configurations",
162: resolveId);
163: }
164: if (conf == null) {
165: throw new BuildException(
166: "no conf provided for ivy report task: "
167: + "It can either be set explicitely via the attribute 'conf' or"
168: + "via 'ivy.resolved.configurations' property or a prior call to <resolve/>");
169: }
170: if (todir == null) {
171: String t = getProperty(settings, "ivy.report.todir");
172: if (t != null) {
173: todir = new File(t);
174: }
175: }
176: outputpattern = getProperty(outputpattern, settings,
177: "ivy.report.output.pattern");
178: if (todir != null && todir.exists()) {
179: todir.mkdirs();
180: }
181: if (outputpattern == null) {
182: outputpattern = "[organisation]-[module]-[conf].[ext]";
183: }
184:
185: if (todir != null && todir.exists() && !todir.isDirectory()) {
186: throw new BuildException(
187: "destination directory should be a directory !");
188: }
189: if (organisation == null) {
190: throw new BuildException(
191: "no organisation provided for ivy report task: "
192: + "It can either be set explicitely via the attribute 'organisation' or "
193: + "via 'ivy.organisation' property or a prior call to <resolve/>");
194: }
195: if (module == null) {
196: throw new BuildException(
197: "no module name provided for ivy report task: "
198: + "It can either be set explicitely via the attribute 'module' or "
199: + "via 'ivy.module' property or a prior call to <resolve/>");
200: }
201: if (resolveId == null) {
202: resolveId = ResolveOptions
203: .getDefaultResolveId(new ModuleId(organisation,
204: module));
205: }
206:
207: try {
208: String[] confs = splitConfs(conf);
209: if (xsl) {
210: genreport(organisation, module, confs);
211: }
212: if (xml) {
213: genxml(organisation, module, confs);
214: }
215: if (graph) {
216: genStyled(organisation, module, confs,
217: getStylePath("ivy-report-graph.xsl"), "graphml");
218: }
219: if (dot) {
220: genStyled(organisation, module, confs,
221: getStylePath("ivy-report-dot.xsl"), "dot");
222: }
223: } catch (IOException e) {
224: throw new BuildException("impossible to generate report: "
225: + e, e);
226: }
227: }
228:
229: private void genxml(String organisation, String module,
230: String[] confs) throws IOException {
231: ResolutionCacheManager cacheMgr = getIvyInstance()
232: .getResolutionCacheManager();
233: for (int i = 0; i < confs.length; i++) {
234: File xml = cacheMgr.getConfigurationResolveReportInCache(
235: resolveId, confs[i]);
236:
237: File out;
238: if (todir != null) {
239: out = new File(todir, IvyPatternHelper.substitute(
240: outputpattern, organisation, module, "", "",
241: "", "xml", confs[i]));
242: } else {
243: out = new File(IvyPatternHelper.substitute(
244: outputpattern, organisation, module, "", "",
245: "", "xml", confs[i]));
246: }
247:
248: FileUtil.copy(xml, out, null);
249: }
250: }
251:
252: private void genreport(String organisation, String module,
253: String[] confs) throws IOException {
254: genStyled(organisation, module, confs, getReportStylePath(),
255: xslext);
256:
257: // copy the css if required
258: if (todir != null && xslFile == null) {
259: File css = new File(todir, "ivy-report.css");
260: if (!css.exists()) {
261: Message.debug("copying report css to " + todir);
262: FileUtil.copy(XmlReportOutputter.class
263: .getResourceAsStream("ivy-report.css"), css,
264: null);
265: }
266: }
267: }
268:
269: private File getReportStylePath() throws IOException {
270: if (xslFile != null) {
271: return xslFile;
272: }
273: // style should be a file (and not an url)
274: // so we have to copy it from classpath to cache
275: ResolutionCacheManager cacheMgr = getIvyInstance()
276: .getResolutionCacheManager();
277: File style = new File(cacheMgr.getResolutionCacheRoot(),
278: "ivy-report.xsl");
279: FileUtil.copy(XmlReportOutputter.class
280: .getResourceAsStream("ivy-report.xsl"), style, null);
281: return style;
282: }
283:
284: private void genStyled(String organisation, String module,
285: String[] confs, File style, String ext) throws IOException {
286: ResolutionCacheManager cacheMgr = getIvyInstance()
287: .getResolutionCacheManager();
288:
289: // process the report with xslt to generate dot file
290: File out;
291: if (todir != null) {
292: out = todir;
293: } else {
294: out = new File(".");
295: }
296:
297: InputStream xsltStream = null;
298: try {
299: // create stream to stylesheet
300: xsltStream = new BufferedInputStream(new FileInputStream(
301: style));
302: Source xsltSource = new StreamSource(xsltStream, JAXPUtils
303: .getSystemId(style));
304:
305: // create transformer
306: TransformerFactory tFactory = TransformerFactory
307: .newInstance();
308: Transformer transformer = tFactory
309: .newTransformer(xsltSource);
310:
311: // add standard parameters
312: transformer.setParameter("confs", conf);
313: transformer.setParameter("extension", xslext);
314:
315: // add the provided XSLT parameters
316: for (Iterator it = params.iterator(); it.hasNext();) {
317: XSLTProcess.Param param = (XSLTProcess.Param) it.next();
318: transformer.setParameter(param.getName(), param
319: .getExpression());
320: }
321:
322: // create the report
323: for (int i = 0; i < confs.length; i++) {
324: File reportFile = cacheMgr
325: .getConfigurationResolveReportInCache(
326: resolveId, confs[i]);
327: File outFile = new File(out, IvyPatternHelper
328: .substitute(outputpattern, organisation,
329: module, "", "", "", ext, confs[i]));
330:
331: log("Processing " + reportFile + " to " + outFile);
332:
333: // make sure the output directory exist
334: File outFileDir = outFile.getParentFile();
335: if (!outFileDir.exists()) {
336: if (!outFileDir.mkdirs()) {
337: throw new BuildException(
338: "Unable to create directory: "
339: + outFileDir.getAbsolutePath());
340: }
341: }
342:
343: InputStream inStream = null;
344: OutputStream outStream = null;
345: try {
346: inStream = new BufferedInputStream(
347: new FileInputStream(reportFile));
348: outStream = new BufferedOutputStream(
349: new FileOutputStream(outFile));
350: StreamResult res = new StreamResult(outStream);
351: Source src = new StreamSource(inStream, JAXPUtils
352: .getSystemId(style));
353: transformer.transform(src, res);
354: } catch (TransformerException e) {
355: throw new BuildException(e);
356: } finally {
357: if (inStream != null) {
358: try {
359: inStream.close();
360: } catch (IOException e) {
361: // ignore
362: }
363: }
364: if (outStream != null) {
365: try {
366: outStream.close();
367: } catch (IOException e) {
368: // ignore
369: }
370: }
371: }
372: }
373: } catch (TransformerConfigurationException e) {
374: throw new BuildException(e);
375: } finally {
376: if (xsltStream != null) {
377: try {
378: xsltStream.close();
379: } catch (IOException e) {
380: // ignore
381: }
382: }
383: }
384: }
385:
386: private File getStylePath(String styleResourceName)
387: throws IOException {
388: // style should be a file (and not an url)
389: // so we have to copy it from classpath to cache
390: ResolutionCacheManager cacheMgr = getIvyInstance()
391: .getResolutionCacheManager();
392: File style = new File(cacheMgr.getResolutionCacheRoot(),
393: styleResourceName);
394: FileUtil.copy(XmlReportOutputter.class
395: .getResourceAsStream(styleResourceName), style, null);
396: return style;
397: }
398:
399: public boolean isXml() {
400: return xml;
401: }
402:
403: public void setXml(boolean xml) {
404: this .xml = xml;
405: }
406:
407: public boolean isXsl() {
408: return xsl;
409: }
410:
411: public void setXsl(boolean xsl) {
412: this .xsl = xsl;
413: }
414:
415: public String getXslext() {
416: return xslext;
417: }
418:
419: public void setXslext(String xslext) {
420: this .xslext = xslext;
421: }
422:
423: public XSLTProcess.Param createParam() {
424: XSLTProcess.Param result = new XSLTProcess.Param();
425: params.add(result);
426: return result;
427: }
428:
429: public boolean isDot() {
430: return dot;
431: }
432:
433: public void setDot(boolean dot) {
434: this.dot = dot;
435: }
436:
437: }
|