Index: D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/TransformMojo.java =================================================================== --- D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/TransformMojo.java (revision 4202) +++ D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/TransformMojo.java (working copy) @@ -26,7 +26,11 @@ import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import javax.xml.transform.TransformerException; + import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -35,9 +39,7 @@ import org.apache.maven.settings.Settings; /** - * Transforms a set of Docbook files into XHTML output. Currently there is only support for - * XHTML output, though is planned to add all kind of outputs available in the standard - * stylesheets. + * Transforms a set of Docbook files into XHTML and PDF output. * * @author jgonzalez * @goal transform @@ -87,10 +89,34 @@ private String outputEncoding; /** + * Specifies the list of desired output formats. Example: + * <outputFormats> + * <param>xhtml</param> + * <param>pdf</param> + * </outputFormats> + * @parameter + */ + private String[] outputFormats = new String[] { "xhtml", "pdf" }; + + /** + *

Specifies a list of customization stylesheets for the specified output + * formats. The default value is to use no customizations, but you can point + * this configuration parameter to your own stylesheets that set parameters + * or override templates.

An example configuration that changes the pdf + * stylesheet:

+ *
<customizations>
+     *   <pdf>src/main/resources/docbook2pdf.xsl</pdf>
+     * </customizations>
+ *

All relative URLs are resolved against resourcePath

+ * @parameter + */ + private Map customizations = new HashMap(); + + /** * Specifies the stylesheet location, useful if you want to use a local copy or a - * specific version instead of the current release from the Internet. + * specific version instead of the current release from the maven repository. * - * @parameter expression="${stylesheetLocation}" default-value="http://docbook.sourceforge.net/release/xsl/current/" + * @parameter expression="${stylesheetLocation}" default-value="resource://net/sourceforge/docbook/" */ private String stylesheetLocation; @@ -106,8 +132,6 @@ { Log log = this.getLog(); - //System.setProperty( TRANSFORMER_FACTORY_PROPERTY_NAME, TRANSFORMER_FACTORY_CLASS ); - Proxy activeProxy = this.settings.getActiveProxy(); String httpProxyHost = System.getProperty( "http.proxyHost" ); String httpProxyPort = System.getProperty( "http.proxyPort" ); @@ -139,15 +163,25 @@ this.resourceDirectory, this.databaseDirectory, this.outputDirectory, - stylesheetLocationURI ); + stylesheetLocationURI, customizations ); + + for ( int i = 0; i < outputFormats.length; i++ ) + { + documentTransformer.enableOutputFormat( outputFormats[i] ); + } + documentTransformer.transform(); } + catch ( TransformerException e ) + { + throw new MojoExecutionException( "Unable to transform documents", e ); + } finally { resetProperties( httpProxyHost, httpProxyPort, httpNonProxyHosts ); } } - + private void resetProperties( String httpProxyHost, String httpProxyPort, String httpNonProxyHosts ) { if ( httpProxyHost != null ) Index: D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/DocumentTransformer.java =================================================================== --- D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/DocumentTransformer.java (revision 4202) +++ D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/DocumentTransformer.java (working copy) @@ -23,12 +23,18 @@ */ package org.codehaus.mojo.docbook; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.net.URI; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.Set; import javax.xml.transform.Result; @@ -36,9 +42,13 @@ import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; import org.apache.maven.plugin.logging.Log; import org.codehaus.plexus.compiler.util.scan.InclusionScanException; import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner; @@ -48,11 +58,14 @@ /** * @author jgonzalez + * @author Lars Trieloff */ public class DocumentTransformer { - protected Log log; + private Set sourcePatterns; + protected Log log; + protected File sourceDirectory; protected File resourceDirectory; @@ -63,27 +76,56 @@ protected URI stylesheetLocation; - /** - * @param log - * @param sourceDirectory - * @param outputDirectory - */ + private boolean generateHtml; + + private boolean generatePdf; + + private MojoURIResolver mojoResolver; + + private String xslfoCustomization; + + private String xhtmlCustomization; + + public DocumentTransformer( Log log, File sourceDirectory, File resourceDirectory, File databaseDirectory, - File outputDirectory, URI stylesheetLocation ) + File outputDirectory, URI stylesheetLocation ) { + this( log, sourceDirectory, resourceDirectory, databaseDirectory, outputDirectory, stylesheetLocation, null ); + } + + public DocumentTransformer( Log log, File sourceDirectory, File resourceDirectory, File databaseDirectory, + File outputDirectory, URI stylesheetLocation, Map customizations ) + { this.log = log; this.sourceDirectory = sourceDirectory; this.resourceDirectory = resourceDirectory; this.databaseDirectory = databaseDirectory; this.outputDirectory = outputDirectory; this.stylesheetLocation = stylesheetLocation; + this.mojoResolver = new MojoURIResolver(); + + this.xslfoCustomization = (String) customizations.get("pdf"); + this.xhtmlCustomization = (String) customizations.get("xhtml"); + + this.sourcePatterns = new HashSet(2); + this.sourcePatterns.add("*.xml"); + this.sourcePatterns.add("**/*xml"); } public void transform() + throws TransformerException { - StaleSourceScanner scanner = new StaleSourceScanner( 0, Collections.singleton( "**/*.xml" ), + StaleSourceScanner scanner = new StaleSourceScanner( 0, this.sourcePatterns, Collections.EMPTY_SET ); - scanner.addSourceMapping( new SuffixMapping( ".xml", ".html" ) ); + if (generateHtml) + { + scanner.addSourceMapping( new SuffixMapping( ".xml", ".html" ) ); + } + if ( generatePdf ) + { + scanner.addSourceMapping( new SuffixMapping( ".xml", ".pdf" ) ); + } + Set staleDocbookFiles; try { @@ -99,7 +141,7 @@ DirectoryScanner docbookScanner = new DirectoryScanner(); docbookScanner.setBasedir( this.sourceDirectory ); docbookScanner.setFollowSymlinks( true ); - docbookScanner.setIncludes( new String[] { "**/*.xml" } ); + docbookScanner.setIncludes( new String[] { "**/*.xml", "*.xml" } ); docbookScanner.scan(); String[] docbookFiles = docbookScanner.getIncludedFiles(); @@ -110,13 +152,23 @@ { this.log.info( "Generated docbook files up to date" ); } - try + + if ( this.resourceDirectory.exists() ) { - FileUtils.copyDirectoryStructure( this.resourceDirectory, this.outputDirectory ); + try + { + FileUtils.copyDirectoryStructure( this.resourceDirectory, this.outputDirectory ); + } + catch ( IOException e ) + { + throw new RuntimeException( "Unable to copy directory from " + resourceDirectory + " to " + + outputDirectory, e ); + } } - catch ( IOException e ) + else { - throw new RuntimeException( "Unable to copy directory from " + resourceDirectory + " to " + outputDirectory, e ); + this.outputDirectory.mkdirs(); + this.log.warn( "Specified resource directory does not exist: " + this.resourceDirectory.toString() ); } } @@ -127,6 +179,8 @@ { this.log.debug( "Creating output directories for the following files - " + Arrays.asList( docbookFiles ).toString() ); + this.outputDirectory.mkdirs(); + // TODO: This should be a bit smarter also, shouldn't it? for ( int fileIndex = 0; fileIndex < docbookFiles.length; fileIndex++ ) { @@ -141,56 +195,167 @@ } protected void transformDocuments( Set docbookFiles ) + throws TransformerException { this.log.info( "Transforming " + docbookFiles.size() + " Docbook stale file(s)" ); - Source docbookStyleSheetSource = new StreamSource( this.stylesheetLocation.resolve( "xhtml/docbook.xsl" ) - .toString() ); - Transformer documentTransformer; - try { - documentTransformer = TransformerFactory.newInstance().newTransformer( docbookStyleSheetSource ); + Transformer xhtmlTransformer = null; + Transformer xslfoTransformer = null; + FopFactory fopFactory = null; + URI olinkDBURI = new File( this.databaseDirectory + File.separator + "olinkdb.xml" ).toURI(); + + if ( generateHtml ) + { + xhtmlTransformer = createXHTMLTransformer( olinkDBURI ); } - catch ( TransformerException e ) + if ( generatePdf ) { - throw new RuntimeException( "Unable to get a transformer instance from source " + docbookStyleSheetSource.getSystemId(), e ); + xslfoTransformer = createXSLFOTransformer(olinkDBURI); + fopFactory = FopFactory.newInstance(); + fopFactory.setURIResolver(this.mojoResolver); } - URI olinkDBURI = new File( this.databaseDirectory + File.separator + "olinkdb.xml" ).toURI(); - documentTransformer.setParameter( "target.database.document", olinkDBURI.toString() ); - documentTransformer.setParameter( "generate.toc", "" ); - this.log.debug( "Style sheet loaded." ); - Iterator filesIterator = docbookFiles.iterator(); while ( filesIterator.hasNext() ) { File docbookFile = (File) filesIterator.next(); - this.log.debug( "Processing " + this.sourceDirectory + File.separator + docbookFile ); - Source source = new StreamSource( docbookFile ); - String relativePath = docbookFile.getAbsolutePath().substring( - (int) this.sourceDirectory.getAbsolutePath() - .length() ); - File resultFile = new File( this.outputDirectory, relativePath - .substring( 0, relativePath.lastIndexOf( '.' ) ) - + ".html" ); - Result result = new StreamResult( resultFile.getAbsolutePath() ); - - documentTransformer.setParameter( "current.docid", OLinkDBUpdater.computeFileID( relativePath ) ); - // TODO: Parametrize this !!!! - documentTransformer - .setParameter( "html.stylesheet", this.pathToResources( relativePath ) + "css/xhtml.css" ); - - try { - documentTransformer.transform( source, result ); + if ( generateHtml ) + { + transformXhtml( xhtmlTransformer, docbookFile ); } - catch ( TransformerException e ) + if ( generatePdf ) { - throw new RuntimeException( "Unable to transform from source " + source.getSystemId() + " into " + result.getSystemId(), e ); + transformPdf( xslfoTransformer, docbookFile, fopFactory ); } + } + } - this.log.debug( "Generated " + this.databaseDirectory + File.separator + docbookFile ); + private Transformer createXSLFOTransformer( URI olinkDBURI ) + throws TransformerException + { + Transformer xslfoTransformer; + TransformerFactory xslfoTf = TransformerFactory.newInstance(); + xslfoTf.setURIResolver( this.mojoResolver ); + Source docbookStyleSheetSource; + + if ( this.xslfoCustomization == null ) + { + docbookStyleSheetSource = this.mojoResolver.resolve( "docbook.xsl", this.stylesheetLocation.toASCIIString() + + "fo/" ); } + else + { + docbookStyleSheetSource = this.mojoResolver.resolve( this.xslfoCustomization, this.sourceDirectory.toURI() + .toString() ); + } + xslfoTransformer = xslfoTf.newTransformer( docbookStyleSheetSource ); + xslfoTransformer.setParameter( "target.database.document", olinkDBURI.toString() ); + + this.log.debug( "XSL:FO Style sheet loaded." ); + return xslfoTransformer; } + private Transformer createXHTMLTransformer( URI olinkDBURI ) + throws TransformerException + { + Transformer xhtmlTransformer; + TransformerFactory xhtmlTf = TransformerFactory.newInstance(); + xhtmlTf.setURIResolver( this.mojoResolver ); + Source docbookStyleSheetSource; + if ( this.xhtmlCustomization == null ) + { + docbookStyleSheetSource = this.mojoResolver.resolve( "docbook.xsl", this.stylesheetLocation.toASCIIString() + + "xhtml/" ); + } + else + { + docbookStyleSheetSource = this.mojoResolver.resolve( this.xhtmlCustomization, this.sourceDirectory.toURI() + .toString() ); + } + xhtmlTransformer = xhtmlTf.newTransformer( docbookStyleSheetSource ); + xhtmlTransformer.setParameter( "target.database.document", olinkDBURI.toString() ); + xhtmlTransformer.setParameter( "generate.toc", "" ); + + this.log.debug( "XHTML Style sheet loaded." ); + return xhtmlTransformer; + } + + private void transformXhtml( Transformer documentTransformer, File docbookFile ) + throws TransformerException + { + this.log.debug( "Processing " + this.sourceDirectory + File.separator + docbookFile ); + Source source = this.mojoResolver.resolve( docbookFile.toURI().toString(), null ); + String relativePath = docbookFile.getAbsolutePath().substring( + (int) this.sourceDirectory.getAbsolutePath() + .length() ); + File resultFile = new File( this.outputDirectory, relativePath.substring( 0, relativePath.lastIndexOf( '.' ) ) + + ".html" ); + Result result = new StreamResult( resultFile.getAbsolutePath() ); + + documentTransformer.setParameter( "current.docid", OLinkDBUpdater.computeFileID( relativePath ) ); + // TODO: Parametrize this !!!! + documentTransformer.setParameter( "html.stylesheet", this.pathToResources( relativePath ) + "css/xhtml.css" ); + + try + { + documentTransformer.transform( source, result ); + } + catch ( TransformerException e ) + { + throw new RuntimeException( "Unable to transform from source " + source.getSystemId() + " into " + + result.getSystemId(), e ); + } + + this.log.debug( "Generated " + this.databaseDirectory + File.separator + docbookFile ); + } + + private void transformPdf( Transformer documentTransformer, File docbookFile, FopFactory fopFactory ) + throws TransformerException + { + this.log.debug( "Processing " + this.sourceDirectory + File.separator + docbookFile ); + Source source = this.mojoResolver.resolve( docbookFile.toURI().toString(), null ); + String relativePath = docbookFile.getAbsolutePath().substring( + (int) this.sourceDirectory.getAbsolutePath() + .length() ); + File resultFile = new File( this.outputDirectory, relativePath.substring( 0, relativePath.lastIndexOf( '.' ) ) + + ".pdf" ); + documentTransformer.setParameter( "current.docid", OLinkDBUpdater.computeFileID( relativePath ) ); + + OutputStream out = null; + try + { + out = new BufferedOutputStream( new FileOutputStream( resultFile.getAbsolutePath() ) ); + Fop fop = fopFactory.newFop( MimeConstants.MIME_PDF, out ); + Result intermediate = new SAXResult( fop.getDefaultHandler() ); + + documentTransformer.transform( source, intermediate ); + } + catch ( FileNotFoundException e ) + { + throw new RuntimeException( e ); + } + catch ( FOPException e ) + { + this.log.error( e ); + } + finally + { + if ( out != null ) + { + try + { + out.close(); + } + catch ( IOException e ) + { + // ignore + } + } + } + + this.log.debug( "Generated " + this.databaseDirectory + File.separator + docbookFile ); + } + protected String pathToResources( String relativePath ) { StringBuffer pathToResources = new StringBuffer(); @@ -202,4 +367,21 @@ } return pathToResources.toString(); } + + /** + * Enables a specified output format. + * @param format the format + */ + public void enableOutputFormat( String format ) + { + if ( "xhtml".equalsIgnoreCase( format ) ) + { + generateHtml = true; + } + if ( "pdf".equalsIgnoreCase( format ) ) + { + generatePdf = true; + } + + } } Index: D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/MojoURIResolver.java =================================================================== --- D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/MojoURIResolver.java (revision 0) +++ D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/MojoURIResolver.java (revision 0) @@ -0,0 +1,23 @@ +package org.codehaus.mojo.docbook; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.URIResolver; + +/** + * + * @author Carlos Sanchez + * @version $Id$ + */ +public class MojoURIResolver + implements URIResolver +{ + + public Source resolve( String arg0, String arg1 ) + throws TransformerException + { + // TODO Auto-generated method stub + return null; + } + +} Property changes on: D:\dev\mojo\docbook-maven-plugin\src\main\java\org\codehaus\mojo\docbook\MojoURIResolver.java ___________________________________________________________________ Name: svn:keywords + "Author Date Id Revision" Name: svn:eol-style + native Index: D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/OLinkDBUpdater.java =================================================================== --- D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/OLinkDBUpdater.java (revision 4202) +++ D:/dev/mojo/docbook-maven-plugin/src/main/java/org/codehaus/mojo/docbook/OLinkDBUpdater.java (working copy) @@ -41,6 +41,8 @@ import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; @@ -77,6 +79,7 @@ } public void update() + throws TransformerException { StaleSourceScanner scanner = new StaleSourceScanner( 0, Collections.singleton( "**/*.xml" ), Collections.EMPTY_SET ); @@ -131,24 +134,20 @@ } } - /** - * @param docbookFiles - */ protected void updateOLinkDatabase( Set docbookFiles ) + throws TransformerException { this.log.info( "Loading olink database generation stylesheet" ); - Source docbookStyleSheetSource = new StreamSource( this.stylesheetLocation.resolve( "xhtml/docbook.xsl" ) - .toString() ); - Transformer olinkDBGenerator; - try + TransformerFactory tf = TransformerFactory.newInstance(); + MojoURIResolver resolver = new MojoURIResolver(); + Source docbookStyleSheetSource = resolver.resolve( "docbook.xsl", this.stylesheetLocation.toASCIIString() + + "xhtml/" ); + tf.setURIResolver( resolver ); + if ( tf.getFeature( SAXSource.FEATURE ) ) { - TransformerFactory factory = TransformerFactory.newInstance(); - olinkDBGenerator = factory.newTransformer( docbookStyleSheetSource ); + SAXTransformerFactory stf = ( (SAXTransformerFactory) tf ); } - catch ( TransformerException e ) - { - throw new RuntimeException( "Unable to get a transformer instance from source " + docbookStyleSheetSource.getSystemId(), e ); - } + Transformer olinkDBGenerator = tf.newTransformer( docbookStyleSheetSource ); olinkDBGenerator.setParameter( "collect.xref.targets", "only" ); olinkDBGenerator.setParameter( "generate.toc", "" ); @@ -170,7 +169,7 @@ try { - olinkDBGenerator.transform( source, result ); + olinkDBGenerator.transform( source, result ); } catch ( TransformerException e ) { @@ -190,7 +189,7 @@ this.log.info( "Creating master olink database file " + file ); try { - BufferedWriter masterOlinkDBFile = new BufferedWriter( new FileWriter( file )); + BufferedWriter masterOlinkDBFile = new BufferedWriter( new FileWriter( file ) ); // Write header masterOlinkDBFile.write( "" ); Index: D:/dev/mojo/docbook-maven-plugin/pom.xml =================================================================== --- D:/dev/mojo/docbook-maven-plugin/pom.xml (revision 4202) +++ D:/dev/mojo/docbook-maven-plugin/pom.xml (working copy) @@ -79,6 +79,12 @@ 6.5.3 runtime + + fop + fop + 0.93 + jdk14 +