選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Fop.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.tools.anttasks;
  19. // Ant
  20. import org.apache.tools.ant.BuildException;
  21. import org.apache.tools.ant.DirectoryScanner;
  22. import org.apache.tools.ant.Project;
  23. import org.apache.tools.ant.Task;
  24. import org.apache.tools.ant.types.FileSet;
  25. import org.apache.tools.ant.util.GlobPatternMapper;
  26. // Java
  27. import java.io.BufferedOutputStream;
  28. import java.io.File;
  29. import java.io.IOException;
  30. import java.io.OutputStream;
  31. import java.net.MalformedURLException;
  32. import java.util.List;
  33. import java.util.Vector;
  34. // FOP
  35. import org.apache.fop.apps.FOPException;
  36. import org.apache.fop.apps.FOUserAgent;
  37. import org.apache.fop.apps.FopFactory;
  38. import org.apache.fop.apps.MimeConstants;
  39. import org.apache.fop.cli.InputHandler;
  40. import org.apache.commons.logging.impl.SimpleLog;
  41. import org.apache.commons.logging.Log;
  42. import org.xml.sax.SAXException;
  43. /**
  44. * Wrapper for FOP which allows it to be accessed from within an Ant task.
  45. * Accepts the inputs:
  46. * <ul>
  47. * <li>fofile -> formatting objects file to be transformed</li>
  48. * <li>format -> MIME type of the format to generate ex. "application/pdf"</li>
  49. * <li>outfile -> output filename</li>
  50. * <li>baseDir -> directory to work from</li>
  51. * <li>relativebase -> (true | false) control whether to use each FO's
  52. * directory as base directory. false uses the baseDir parameter.</li>
  53. * <li>userconfig -> file with user configuration (same as the "-c" command
  54. * line option)</li>
  55. * <li>messagelevel -> (error | warn | info | verbose | debug) level to output
  56. * non-error messages</li>
  57. * <li>logFiles -> Controls whether the names of the files that are processed
  58. * are logged or not</li>
  59. * </ul>
  60. */
  61. public class Fop extends Task {
  62. private File foFile;
  63. private File xmlFile;
  64. private File xsltFile;
  65. private String xsltParams;
  66. private List/*<FileSet>*/ filesets = new java.util.ArrayList/*<FileSet>*/();
  67. private File outFile;
  68. private File outDir;
  69. private String format; //MIME type
  70. private File baseDir;
  71. private File userConfig;
  72. private int messageType = Project.MSG_VERBOSE;
  73. private boolean logFiles = true;
  74. private boolean force = false;
  75. private boolean relativebase = false;
  76. private boolean throwExceptions = true;
  77. /**
  78. * Sets the filename for the userconfig.xml.
  79. * @param userConfig Configuration to use
  80. */
  81. public void setUserconfig(File userConfig) {
  82. this.userConfig = userConfig;
  83. }
  84. /**
  85. * Returns the file for the userconfig.xml.
  86. * @return the userconfig.xml file
  87. */
  88. public File getUserconfig() {
  89. return this.userConfig;
  90. }
  91. /**
  92. * Sets the input XSL-FO file.
  93. * @param foFile input XSL-FO file
  94. */
  95. public void setFofile(File foFile) {
  96. this.foFile = foFile;
  97. }
  98. /**
  99. * Gets the input XSL-FO file.
  100. * @return input XSL-FO file
  101. */
  102. public File getFofile() {
  103. return foFile;
  104. }
  105. /**
  106. * Gets the input XML file.
  107. * @return the input XML file.
  108. */
  109. public File getXmlFile() {
  110. return xmlFile;
  111. }
  112. /**
  113. * Sets the input XML file.
  114. * @param xmlFile the input XML file.
  115. */
  116. public void setXmlFile(File xmlFile) {
  117. this.xmlFile = xmlFile;
  118. }
  119. /**
  120. * Gets the input XSLT file.
  121. * @return the input XSLT file.
  122. */
  123. public File getXsltFile() {
  124. return xsltFile;
  125. }
  126. /**
  127. * Sets the input XSLT file.
  128. * @param xsltFile the input XSLT file.
  129. */
  130. public void setXsltFile(File xsltFile) {
  131. this.xsltFile = xsltFile;
  132. }
  133. /**
  134. * Gets the XSLT parameters
  135. * @return the XSLT parameters
  136. */
  137. public String getXsltParams() {
  138. return xsltParams;
  139. }
  140. /**
  141. * Sets the XSLT parameters
  142. * @param xsltParams the XSLT parameters
  143. */
  144. public void setXsltParams(String xsltParams) {
  145. this.xsltParams = xsltParams;
  146. }
  147. /**
  148. * Adds a set of XSL-FO files (nested fileset attribute).
  149. * @param set a fileset
  150. */
  151. public void addFileset(FileSet set) {
  152. filesets.add(set);
  153. }
  154. /**
  155. * Returns the current list of filesets.
  156. * @return the filesets
  157. */
  158. public List getFilesets() {
  159. return this.filesets;
  160. }
  161. /**
  162. * Set whether to include files (external-graphics, instream-foreign-object)
  163. * from a path relative to the .fo file (true) or the working directory (false, default)
  164. * only useful for filesets
  165. *
  166. * @param relbase true if paths are relative to file.
  167. */
  168. public void setRelativebase(boolean relbase) {
  169. this.relativebase = relbase;
  170. }
  171. /**
  172. * Gets the relative base attribute
  173. * @return the relative base attribute
  174. */
  175. public boolean getRelativebase() {
  176. return relativebase;
  177. }
  178. /**
  179. * Set whether to check dependencies, or to always generate;
  180. * optional, default is false.
  181. *
  182. * @param force true if always generate.
  183. */
  184. public void setForce(boolean force) {
  185. this.force = force;
  186. }
  187. /**
  188. * Gets the force attribute
  189. * @return the force attribute
  190. */
  191. public boolean getForce() {
  192. return force;
  193. }
  194. /**
  195. * Sets the output file.
  196. * @param outFile File to output to
  197. */
  198. public void setOutfile(File outFile) {
  199. this.outFile = outFile;
  200. }
  201. /**
  202. * Gets the output file.
  203. * @return the output file
  204. */
  205. public File getOutfile() {
  206. return this.outFile;
  207. }
  208. /**
  209. * Sets the output directory.
  210. * @param outDir Directory to output to
  211. */
  212. public void setOutdir(File outDir) {
  213. this.outDir = outDir;
  214. }
  215. /**
  216. * Gets the output directory.
  217. * @return the output directory
  218. */
  219. public File getOutdir() {
  220. return this.outDir;
  221. }
  222. /**
  223. * Sets output format (MIME type).
  224. * @param format the output format
  225. */
  226. public void setFormat(String format) {
  227. this.format = format;
  228. }
  229. /**
  230. * Gets the output format (MIME type).
  231. * @return the output format
  232. */
  233. public String getFormat() {
  234. return this.format;
  235. }
  236. /**
  237. * Set whether exceptions are thrown.
  238. * default is false.
  239. *
  240. * @param force true if always generate.
  241. */
  242. public void setThrowexceptions(boolean throwExceptions) {
  243. this.throwExceptions = throwExceptions;
  244. }
  245. /**
  246. * Gets the throw exceptions attribute
  247. * @return the throw exceptions attribute
  248. */
  249. public boolean getThrowexceptions() {
  250. return this.throwExceptions;
  251. }
  252. /**
  253. * Sets the message level to be used while processing.
  254. * @param messageLevel (error | warn| info | verbose | debug)
  255. */
  256. public void setMessagelevel(String messageLevel) {
  257. if (messageLevel.equalsIgnoreCase("info")) {
  258. messageType = Project.MSG_INFO;
  259. } else if (messageLevel.equalsIgnoreCase("verbose")) {
  260. messageType = Project.MSG_VERBOSE;
  261. } else if (messageLevel.equalsIgnoreCase("debug")) {
  262. messageType = Project.MSG_DEBUG;
  263. } else if (messageLevel.equalsIgnoreCase("err")
  264. || messageLevel.equalsIgnoreCase("error")) {
  265. messageType = Project.MSG_ERR;
  266. } else if (messageLevel.equalsIgnoreCase("warn")) {
  267. messageType = Project.MSG_WARN;
  268. } else {
  269. log("messagelevel set to unknown value \"" + messageLevel
  270. + "\"", Project.MSG_ERR);
  271. throw new BuildException("unknown messagelevel");
  272. }
  273. }
  274. /**
  275. * Returns the message type corresponding to Project.MSG_*
  276. * representing the current message level.
  277. * @see org.apache.tools.ant.Project
  278. */
  279. public int getMessageType() {
  280. return messageType;
  281. }
  282. /**
  283. * Sets the base directory for single FO file (non-fileset) usage
  284. * @param baseDir File to use as a working directory
  285. */
  286. public void setBasedir(File baseDir) {
  287. this.baseDir = baseDir;
  288. }
  289. /**
  290. * Gets the base directory.
  291. * @return the base directory
  292. */
  293. public File getBasedir() {
  294. return (baseDir != null) ? baseDir : getProject().resolveFile(".");
  295. }
  296. /**
  297. * Controls whether the filenames of the files that are processed are logged
  298. * or not.
  299. * @param logFiles True if the feature should be enabled
  300. */
  301. public void setLogFiles(boolean logFiles) {
  302. this.logFiles = logFiles;
  303. }
  304. /**
  305. * Returns True if the filename of each file processed should be logged.
  306. * @return True if the filenames should be logged.
  307. */
  308. public boolean getLogFiles() {
  309. return this.logFiles;
  310. }
  311. /**
  312. * {@inheritDoc}
  313. */
  314. public void execute() throws BuildException {
  315. int logLevel = SimpleLog.LOG_LEVEL_INFO;
  316. switch (getMessageType()) {
  317. case Project.MSG_DEBUG : logLevel = SimpleLog.LOG_LEVEL_DEBUG; break;
  318. case Project.MSG_INFO : logLevel = SimpleLog.LOG_LEVEL_INFO; break;
  319. case Project.MSG_WARN : logLevel = SimpleLog.LOG_LEVEL_WARN; break;
  320. case Project.MSG_ERR : logLevel = SimpleLog.LOG_LEVEL_ERROR; break;
  321. case Project.MSG_VERBOSE: logLevel = SimpleLog.LOG_LEVEL_DEBUG; break;
  322. default: logLevel = SimpleLog.LOG_LEVEL_INFO;
  323. }
  324. SimpleLog logger = new SimpleLog("FOP/Anttask");
  325. logger.setLevel(logLevel);
  326. try {
  327. FOPTaskStarter starter = new FOPTaskStarter(this);
  328. starter.setLogger(logger);
  329. starter.run();
  330. } catch (FOPException ex) {
  331. throw new BuildException(ex);
  332. } catch (IOException ioe) {
  333. throw new BuildException(ioe);
  334. } catch (SAXException saxex) {
  335. throw new BuildException(saxex);
  336. }
  337. }
  338. }
  339. class FOPTaskStarter {
  340. // configure fopFactory as desired
  341. private FopFactory fopFactory = FopFactory.newInstance();
  342. private Fop task;
  343. private String baseURL = null;
  344. /**
  345. * logging instance
  346. */
  347. protected Log logger = null;
  348. /**
  349. * Sets the Commons-Logging instance for this class
  350. * @param logger The Commons-Logging instance
  351. */
  352. public void setLogger(Log logger) {
  353. this.logger = logger;
  354. }
  355. /**
  356. * Returns the Commons-Logging instance for this class
  357. * @return The Commons-Logging instance
  358. */
  359. protected Log getLogger() {
  360. return logger;
  361. }
  362. FOPTaskStarter(Fop task) throws SAXException, IOException {
  363. this.task = task;
  364. if (task.getUserconfig() != null) {
  365. fopFactory.setUserConfig(task.getUserconfig());
  366. }
  367. }
  368. private static final String[][] SHORT_NAMES = {
  369. {"pdf", MimeConstants.MIME_PDF},
  370. {"ps", MimeConstants.MIME_POSTSCRIPT},
  371. {"mif", MimeConstants.MIME_MIF},
  372. {"rtf", MimeConstants.MIME_RTF},
  373. {"pcl", MimeConstants.MIME_PCL},
  374. {"txt", MimeConstants.MIME_PLAIN_TEXT},
  375. {"at", MimeConstants.MIME_FOP_AREA_TREE},
  376. {"xml", MimeConstants.MIME_FOP_AREA_TREE},
  377. {"tiff", MimeConstants.MIME_TIFF},
  378. {"tif", MimeConstants.MIME_TIFF},
  379. {"png", MimeConstants.MIME_PNG},
  380. {"afp", MimeConstants.MIME_AFP}
  381. };
  382. private String normalizeOutputFormat(String format) {
  383. if (format == null) {
  384. return MimeConstants.MIME_PDF;
  385. }
  386. for (int i = 0; i < SHORT_NAMES.length; i++) {
  387. if (SHORT_NAMES[i][0].equals(format)) {
  388. return SHORT_NAMES[i][1];
  389. }
  390. }
  391. return format; //no change
  392. }
  393. private static final String[][] EXTENSIONS = {
  394. {MimeConstants.MIME_FOP_AREA_TREE, ".at.xml"},
  395. {MimeConstants.MIME_FOP_AWT_PREVIEW, null},
  396. {MimeConstants.MIME_FOP_PRINT, null},
  397. {MimeConstants.MIME_PDF, ".pdf"},
  398. {MimeConstants.MIME_POSTSCRIPT, ".ps"},
  399. {MimeConstants.MIME_PCL, ".pcl"},
  400. {MimeConstants.MIME_PCL_ALT, ".pcl"},
  401. {MimeConstants.MIME_PLAIN_TEXT, ".txt"},
  402. {MimeConstants.MIME_RTF, ".rtf"},
  403. {MimeConstants.MIME_RTF_ALT1, ".rtf"},
  404. {MimeConstants.MIME_RTF_ALT2, ".rtf"},
  405. {MimeConstants.MIME_MIF, ".mif"},
  406. {MimeConstants.MIME_SVG, ".svg"},
  407. {MimeConstants.MIME_PNG, ".png"},
  408. {MimeConstants.MIME_JPEG, ".jpg"},
  409. {MimeConstants.MIME_TIFF, ".tif"},
  410. {MimeConstants.MIME_AFP, ".afp"},
  411. {MimeConstants.MIME_AFP_ALT, ".afp"},
  412. {MimeConstants.MIME_XSL_FO, ".fo"}
  413. };
  414. private String determineExtension(String outputFormat) {
  415. for (int i = 0; i < EXTENSIONS.length; i++) {
  416. if (EXTENSIONS[i][0].equals(outputFormat)) {
  417. String ext = EXTENSIONS[i][1];
  418. if (ext == null) {
  419. throw new RuntimeException("Output format '"
  420. + outputFormat + "' does not produce a file.");
  421. } else {
  422. return ext;
  423. }
  424. }
  425. }
  426. return ".unk"; //unknown
  427. }
  428. private File replaceExtension(File file, String expectedExt,
  429. String newExt) {
  430. String name = file.getName();
  431. if (name.toLowerCase().endsWith(expectedExt)) {
  432. name = name.substring(0, name.length() - expectedExt.length());
  433. }
  434. name = name.concat(newExt);
  435. return new File(file.getParentFile(), name);
  436. }
  437. /**
  438. * {@inheritDoc}
  439. */
  440. public void run() throws FOPException {
  441. //Set base directory
  442. if (task.getBasedir() != null) {
  443. try {
  444. this.baseURL = task.getBasedir().toURI().toURL().toExternalForm();
  445. } catch (MalformedURLException mfue) {
  446. logger.error("Error creating base URL from base directory", mfue);
  447. }
  448. } else {
  449. try {
  450. if (task.getFofile() != null) {
  451. this.baseURL = task.getFofile().getParentFile().toURI().toURL().
  452. toExternalForm();
  453. }
  454. } catch (MalformedURLException mfue) {
  455. logger.error("Error creating base URL from XSL-FO input file", mfue);
  456. }
  457. }
  458. task.log("Using base URL: " + baseURL, Project.MSG_DEBUG);
  459. String outputFormat = normalizeOutputFormat(task.getFormat());
  460. String newExtension = determineExtension(outputFormat);
  461. // actioncount = # of fofiles actually processed through FOP
  462. int actioncount = 0;
  463. // skippedcount = # of fofiles which haven't changed (force = "false")
  464. int skippedcount = 0;
  465. // deal with single source file
  466. if (task.getFofile() != null) {
  467. if (task.getFofile().exists()) {
  468. File outf = task.getOutfile();
  469. if (outf == null) {
  470. throw new BuildException("outfile is required when fofile is used");
  471. }
  472. if (task.getOutdir() != null) {
  473. outf = new File(task.getOutdir(), outf.getName());
  474. }
  475. // Render if "force" flag is set OR
  476. // OR output file doesn't exist OR
  477. // output file is older than input file
  478. if (task.getForce() || !outf.exists()
  479. || (task.getFofile().lastModified() > outf.lastModified() )) {
  480. render(task.getFofile(), outf, outputFormat);
  481. actioncount++;
  482. } else if (outf.exists()
  483. && (task.getFofile().lastModified() <= outf.lastModified() )) {
  484. skippedcount++;
  485. }
  486. }
  487. } else if (task.getXmlFile() != null && task.getXsltFile() != null) {
  488. if (task.getXmlFile().exists() && task.getXsltFile().exists()) {
  489. File outf = task.getOutfile();
  490. if (outf == null) {
  491. throw new BuildException("outfile is required when fofile is used");
  492. }
  493. if (task.getOutdir() != null) {
  494. outf = new File(task.getOutdir(), outf.getName());
  495. }
  496. // Render if "force" flag is set OR
  497. // OR output file doesn't exist OR
  498. // output file is older than input file
  499. if (task.getForce() || !outf.exists()
  500. || (task.getXmlFile().lastModified() > outf.lastModified() ||
  501. task.getXsltFile().lastModified() > outf.lastModified())) {
  502. render(task.getXmlFile(), task.getXsltFile(), outf, outputFormat);
  503. actioncount++;
  504. } else if (outf.exists()
  505. && (task.getXmlFile().lastModified() <= outf.lastModified() ||
  506. task.getXsltFile().lastModified() <= outf.lastModified())) {
  507. skippedcount++;
  508. }
  509. }
  510. }
  511. GlobPatternMapper mapper = new GlobPatternMapper();
  512. String inputExtension = ".fo";
  513. File xsltFile = task.getXsltFile();
  514. if (xsltFile != null) {
  515. inputExtension = ".xml";
  516. }
  517. mapper.setFrom("*" + inputExtension);
  518. mapper.setTo("*" + newExtension);
  519. // deal with the filesets
  520. for (int i = 0; i < task.getFilesets().size(); i++) {
  521. FileSet fs = (FileSet) task.getFilesets().get(i);
  522. DirectoryScanner ds = fs.getDirectoryScanner(task.getProject());
  523. String[] files = ds.getIncludedFiles();
  524. for (int j = 0; j < files.length; j++) {
  525. File f = new File(fs.getDir(task.getProject()), files[j]);
  526. File outf = null;
  527. if (task.getOutdir() != null && files[j].endsWith(inputExtension)) {
  528. String[] sa = mapper.mapFileName(files[j]);
  529. outf = new File(task.getOutdir(), sa[0]);
  530. } else {
  531. outf = replaceExtension(f, inputExtension, newExtension);
  532. if (task.getOutdir() != null) {
  533. outf = new File(task.getOutdir(), outf.getName());
  534. }
  535. }
  536. File dir = outf.getParentFile();
  537. if (!dir.exists()) {
  538. dir.mkdirs();
  539. }
  540. try {
  541. if (task.getRelativebase()) {
  542. this.baseURL = f.getParentFile().toURI().toURL().
  543. toExternalForm();
  544. }
  545. if (this.baseURL == null) {
  546. this.baseURL = fs.getDir(task.getProject()).toURI().toURL().
  547. toExternalForm();
  548. }
  549. } catch (Exception e) {
  550. task.log("Error setting base URL", Project.MSG_DEBUG);
  551. }
  552. // Render if "force" flag is set OR
  553. // OR output file doesn't exist OR
  554. // output file is older than input file
  555. if (task.getForce() || !outf.exists()
  556. || (f.lastModified() > outf.lastModified() )) {
  557. if (xsltFile != null) {
  558. render(f, xsltFile, outf, outputFormat);
  559. } else {
  560. render(f, outf, outputFormat);
  561. }
  562. actioncount++;
  563. } else if (outf.exists() && (f.lastModified() <= outf.lastModified() )) {
  564. skippedcount++;
  565. }
  566. }
  567. }
  568. if (actioncount + skippedcount == 0) {
  569. task.log("No files processed. No files were selected by the filesets "
  570. + "and no fofile was set." , Project.MSG_WARN);
  571. } else if (skippedcount > 0) {
  572. task.log(skippedcount + " xslfo file(s) skipped (no change found"
  573. + " since last generation; set force=\"true\" to override)."
  574. , Project.MSG_INFO);
  575. }
  576. }
  577. private void renderInputHandler(InputHandler inputHandler, File outFile, String outputFormat) throws Exception {
  578. OutputStream out = null;
  579. try {
  580. out = new java.io.FileOutputStream(outFile);
  581. out = new BufferedOutputStream(out);
  582. } catch (Exception ex) {
  583. throw new BuildException("Failed to open " + outFile, ex);
  584. }
  585. boolean success = false;
  586. try {
  587. FOUserAgent userAgent = fopFactory.newFOUserAgent();
  588. userAgent.setBaseURL(this.baseURL);
  589. inputHandler.renderTo(userAgent, outputFormat, out);
  590. success = true;
  591. } catch (Exception ex) {
  592. if (task.getThrowexceptions()) {
  593. throw new BuildException(ex);
  594. }
  595. throw ex;
  596. } finally {
  597. try {
  598. out.close();
  599. } catch (IOException ioe) {
  600. logger.error("Error closing output file", ioe);
  601. }
  602. if (!success) {
  603. outFile.delete();
  604. }
  605. }
  606. }
  607. private void render(File foFile, File outFile,
  608. String outputFormat) throws FOPException {
  609. InputHandler inputHandler = new InputHandler(foFile);
  610. try {
  611. renderInputHandler(inputHandler, outFile, outputFormat);
  612. } catch (Exception ex) {
  613. logger.error("Error rendering fo file: " + foFile, ex);
  614. }
  615. if (task.getLogFiles()) {
  616. task.log(foFile + " -> " + outFile, Project.MSG_INFO);
  617. }
  618. }
  619. private void render(File xmlFile, File xsltFile, File outFile, String outputFormat) {
  620. //TODO: implement support for XSLT params
  621. final Vector xsltParams = null;
  622. InputHandler inputHandler = new InputHandler(xmlFile, xsltFile, xsltParams);
  623. try {
  624. renderInputHandler(inputHandler, outFile, outputFormat);
  625. } catch (Exception ex) {
  626. logger.error("Error rendering xml/xslt files: " + xmlFile + ", " + xsltFile, ex);
  627. }
  628. if (task.getLogFiles()) {
  629. task.log("xml: " + xmlFile + ", xslt: " + xsltFile + " -> " + outFile, Project.MSG_INFO);
  630. }
  631. }
  632. }