Coverage Report - org.apache.maven.doxia.docrenderer.pdf.fo.FoPdfRenderer
 
Classes in this File Line Coverage Branch Coverage Complexity
FoPdfRenderer
69%
86/123
53%
32/60
4,4
 
 1  
 package org.apache.maven.doxia.docrenderer.pdf.fo;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.File;
 23  
 import java.io.IOException;
 24  
 import java.io.Writer;
 25  
 import java.util.Collection;
 26  
 import java.util.List;
 27  
 import java.util.Locale;
 28  
 import java.util.Map;
 29  
 
 30  
 import javax.xml.transform.TransformerException;
 31  
 
 32  
 import org.apache.maven.doxia.docrenderer.DocumentRendererContext;
 33  
 import org.apache.maven.doxia.docrenderer.DocumentRendererException;
 34  
 import org.apache.maven.doxia.docrenderer.pdf.AbstractPdfRenderer;
 35  
 import org.apache.maven.doxia.document.DocumentModel;
 36  
 import org.apache.maven.doxia.document.DocumentTOC;
 37  
 import org.apache.maven.doxia.document.DocumentTOCItem;
 38  
 import org.apache.maven.doxia.module.fo.FoAggregateSink;
 39  
 import org.apache.maven.doxia.module.fo.FoSink;
 40  
 import org.apache.maven.doxia.module.fo.FoSinkFactory;
 41  
 import org.apache.maven.doxia.module.fo.FoUtils;
 42  
 import org.apache.maven.doxia.module.site.SiteModule;
 43  
 
 44  
 import org.codehaus.plexus.util.IOUtil;
 45  
 import org.codehaus.plexus.util.StringUtils;
 46  
 import org.codehaus.plexus.util.WriterFactory;
 47  
 
 48  
 import org.xml.sax.SAXParseException;
 49  
 
 50  
 /**
 51  
  * PDF renderer that uses Doxia's FO module.
 52  
  *
 53  
  * @author ltheussl
 54  
  * @version $Id: FoPdfRenderer.java 1087124 2011-03-30 22:45:41Z hboutemy $
 55  
  * @since 1.1
 56  
  * @plexus.component role="org.apache.maven.doxia.docrenderer.pdf.PdfRenderer" role-hint="fo"
 57  
  */
 58  12
 public class FoPdfRenderer
 59  
     extends AbstractPdfRenderer
 60  
 {
 61  
     /**
 62  
      * {@inheritDoc}
 63  
      * @see org.apache.maven.doxia.module.fo.FoUtils#convertFO2PDF(File, File, String)
 64  
      */
 65  
     public void generatePdf( File inputFile, File pdfFile )
 66  
         throws DocumentRendererException
 67  
     {
 68  
         // Should take care of the document model for the metadata...
 69  0
         generatePdf( inputFile, pdfFile, null );
 70  0
     }
 71  
 
 72  
     /** {@inheritDoc} */
 73  
     public void render( Map<String, SiteModule> filesToProcess, File outputDirectory, DocumentModel documentModel )
 74  
         throws DocumentRendererException, IOException
 75  
     {
 76  0
         render( filesToProcess, outputDirectory, documentModel, null );
 77  0
     }
 78  
 
 79  
     /** {@inheritDoc} */
 80  
     public void render( Map<String, SiteModule> filesToProcess, File outputDirectory, DocumentModel documentModel,
 81  
                         DocumentRendererContext context )
 82  
         throws DocumentRendererException, IOException
 83  
     {
 84  
         // copy resources, images, etc.
 85  12
         copyResources( outputDirectory );
 86  
 
 87  12
         if ( documentModel == null )
 88  
         {
 89  6
             getLogger().debug( "No document model, generating all documents individually." );
 90  
 
 91  6
             renderIndividual( filesToProcess, outputDirectory, context );
 92  6
             return;
 93  
         }
 94  
 
 95  6
         String outputName = getOutputName( documentModel );
 96  
 
 97  6
         File outputFOFile = new File( outputDirectory, outputName + ".fo" );
 98  6
         if ( !outputFOFile.getParentFile().exists() )
 99  
         {
 100  0
             outputFOFile.getParentFile().mkdirs();
 101  
         }
 102  
 
 103  6
         File pdfOutputFile = new File( outputDirectory, outputName + ".pdf" );
 104  6
         if ( !pdfOutputFile.getParentFile().exists() )
 105  
         {
 106  0
             pdfOutputFile.getParentFile().mkdirs();
 107  
         }
 108  
 
 109  6
         Writer writer = null;
 110  
         try
 111  
         {
 112  6
             writer = WriterFactory.newXmlWriter( outputFOFile );
 113  
 
 114  6
             FoAggregateSink sink = new FoAggregateSink( writer );
 115  
 
 116  6
             File fOConfigFile = new File( outputDirectory, "pdf-config.xml" );
 117  
 
 118  6
             if ( fOConfigFile.exists() )
 119  
             {
 120  0
                 sink.load( fOConfigFile );
 121  0
                 getLogger().debug( "Loaded pdf config file: " + fOConfigFile.getAbsolutePath() );
 122  
             }
 123  
 
 124  6
             String generateTOC =
 125  
                 ( context != null && context.get( "generateTOC" ) != null ? context.get( "generateTOC" ).toString().trim()
 126  
                                 : "start" );
 127  6
             int tocPosition = 0;
 128  6
             if ( "start".equalsIgnoreCase( generateTOC ) )
 129  
             {
 130  6
                 tocPosition = FoAggregateSink.TOC_START;
 131  
             }
 132  0
             else if ( "end".equalsIgnoreCase( generateTOC ) )
 133  
             {
 134  0
                 tocPosition = FoAggregateSink.TOC_END;
 135  
             }
 136  
             else
 137  
             {
 138  0
                 tocPosition = FoAggregateSink.TOC_NONE;
 139  
             }
 140  6
             sink.setDocumentModel( documentModel, tocPosition );
 141  
 
 142  6
             sink.beginDocument();
 143  
 
 144  6
             sink.coverPage();
 145  
 
 146  6
             if ( tocPosition == FoAggregateSink.TOC_START )
 147  
             {
 148  6
                 sink.toc();
 149  
             }
 150  
 
 151  6
             if ( ( documentModel.getToc() == null ) || ( documentModel.getToc().getItems() == null ) )
 152  
             {
 153  0
                 getLogger().info( "No TOC is defined in the document descriptor. Merging all documents." );
 154  
 
 155  0
                 mergeAllSources( filesToProcess, sink, context );
 156  
             }
 157  
             else
 158  
             {
 159  6
                 getLogger().debug( "Using TOC defined in the document descriptor." );
 160  
 
 161  6
                 mergeSourcesFromTOC( documentModel.getToc(), sink, context );
 162  
             }
 163  
 
 164  6
             if ( tocPosition == FoAggregateSink.TOC_END )
 165  
             {
 166  0
                 sink.toc();
 167  
             }
 168  
 
 169  6
             sink.endDocument();
 170  
         }
 171  
         finally
 172  
         {
 173  6
             IOUtil.close( writer );
 174  6
         }
 175  
 
 176  6
         generatePdf( outputFOFile, pdfOutputFile, documentModel );
 177  6
     }
 178  
 
 179  
     /** {@inheritDoc} */
 180  
     public void renderIndividual( Map<String, SiteModule> filesToProcess, File outputDirectory )
 181  
         throws DocumentRendererException, IOException
 182  
     {
 183  0
         renderIndividual( filesToProcess, outputDirectory, null );
 184  0
     }
 185  
 
 186  
     /** {@inheritDoc} */
 187  
     public void renderIndividual( Map<String, SiteModule> filesToProcess, File outputDirectory,
 188  
                                   DocumentRendererContext context )
 189  
         throws DocumentRendererException, IOException
 190  
     {
 191  6
         for ( Map.Entry<String, SiteModule> entry : filesToProcess.entrySet() )
 192  
         {
 193  36
             String key = entry.getKey();
 194  36
             SiteModule module = entry.getValue();
 195  
 
 196  36
             File fullDoc = new File( getBaseDir(), module.getSourceDirectory() + File.separator + key );
 197  
 
 198  36
             String output = key;
 199  36
             String lowerCaseExtension = module.getExtension().toLowerCase( Locale.ENGLISH );
 200  36
             if ( output.toLowerCase( Locale.ENGLISH ).indexOf( "." + lowerCaseExtension ) != -1 )
 201  
             {
 202  36
                 output =
 203  
                     output.substring( 0, output.toLowerCase( Locale.ENGLISH ).indexOf( "." + lowerCaseExtension ) );
 204  
             }
 205  
 
 206  36
             File outputFOFile = new File( outputDirectory, output + ".fo" );
 207  36
             if ( !outputFOFile.getParentFile().exists() )
 208  
             {
 209  6
                 outputFOFile.getParentFile().mkdirs();
 210  
             }
 211  
 
 212  36
             File pdfOutputFile = new File( outputDirectory, output + ".pdf" );
 213  36
             if ( !pdfOutputFile.getParentFile().exists() )
 214  
             {
 215  0
                 pdfOutputFile.getParentFile().mkdirs();
 216  
             }
 217  
 
 218  36
             FoSink sink =
 219  
                 (FoSink) new FoSinkFactory().createSink( outputFOFile.getParentFile(), outputFOFile.getName() );
 220  36
             sink.beginDocument();
 221  36
             parse( fullDoc.getAbsolutePath(), module.getParserId(), sink, context );
 222  36
             sink.endDocument();
 223  
 
 224  36
             generatePdf( outputFOFile, pdfOutputFile, null );
 225  36
         }
 226  6
     }
 227  
 
 228  
     private void mergeAllSources( Map<String, SiteModule> filesToProcess, FoAggregateSink sink,
 229  
                                   DocumentRendererContext context )
 230  
         throws DocumentRendererException, IOException
 231  
     {
 232  0
         for ( Map.Entry<String, SiteModule> entry : filesToProcess.entrySet() )
 233  
         {
 234  0
             String key = entry.getKey();
 235  0
             SiteModule module = entry.getValue();
 236  0
             sink.setDocumentName( key );
 237  0
             File fullDoc = new File( getBaseDir(), module.getSourceDirectory() + File.separator + key );
 238  
 
 239  0
             parse( fullDoc.getAbsolutePath(), module.getParserId(), sink, context );
 240  0
         }
 241  0
     }
 242  
 
 243  
     private void mergeSourcesFromTOC( DocumentTOC toc, FoAggregateSink sink, DocumentRendererContext context )
 244  
         throws IOException, DocumentRendererException
 245  
     {
 246  6
         parseTocItems( toc.getItems(), sink, context );
 247  6
     }
 248  
 
 249  
     private void parseTocItems( List<DocumentTOCItem> items, FoAggregateSink sink, DocumentRendererContext context )
 250  
         throws IOException, DocumentRendererException
 251  
     {
 252  48
         for ( DocumentTOCItem tocItem : items )
 253  
         {
 254  42
             if ( tocItem.getRef() == null )
 255  
             {
 256  0
                 if ( getLogger().isInfoEnabled() )
 257  
                 {
 258  0
                     getLogger().info( "No ref defined for tocItem " + tocItem.getName() );
 259  
                 }
 260  
 
 261  
                 continue;
 262  
             }
 263  
 
 264  42
             String href = StringUtils.replace( tocItem.getRef(), "\\", "/" );
 265  42
             if ( href.lastIndexOf( "." ) != -1 )
 266  
             {
 267  42
                 href = href.substring( 0, href.lastIndexOf( "." ) );
 268  
             }
 269  
 
 270  42
             renderModules( href, sink, tocItem, context );
 271  
 
 272  42
             if ( tocItem.getItems() != null )
 273  
             {
 274  42
                 parseTocItems( tocItem.getItems(), sink, context );
 275  
             }
 276  42
         }
 277  48
     }
 278  
 
 279  
     private void renderModules( String href, FoAggregateSink sink, DocumentTOCItem tocItem,
 280  
                                 DocumentRendererContext context )
 281  
         throws DocumentRendererException, IOException
 282  
     {
 283  42
         Collection<SiteModule> modules = siteModuleManager.getSiteModules();
 284  42
         for ( SiteModule module : modules )
 285  
         {
 286  168
             File moduleBasedir = new File( getBaseDir(), module.getSourceDirectory() );
 287  
 
 288  168
             if ( moduleBasedir.exists() )
 289  
             {
 290  126
                 String doc = href + "." + module.getExtension();
 291  126
                 File source = new File( moduleBasedir, doc );
 292  
 
 293  
                 // Velocity file?
 294  126
                 if ( !source.exists() )
 295  
                 {
 296  90
                     if ( href.indexOf( "." + module.getExtension() ) != -1 )
 297  
                     {
 298  0
                         doc = href + ".vm";
 299  
                     }
 300  
                     else
 301  
                     {
 302  90
                         doc = href + "." + module.getExtension() + ".vm";
 303  
                     }
 304  90
                     source = new File( moduleBasedir, doc );
 305  
                 }
 306  
 
 307  126
                 if ( source.exists() )
 308  
                 {
 309  36
                     sink.setDocumentName( doc );
 310  36
                     sink.setDocumentTitle( tocItem.getName() );
 311  
 
 312  36
                     parse( source.getPath(), module.getParserId(), sink, context );
 313  
                 }
 314  
             }
 315  168
         }
 316  42
     }
 317  
 
 318  
     /**
 319  
      * @param inputFile
 320  
      * @param pdfFile
 321  
      * @param documentModel could be null
 322  
      * @throws DocumentRendererException if any
 323  
      * @since 1.1.1
 324  
      */
 325  
     private void generatePdf( File inputFile, File pdfFile, DocumentModel documentModel )
 326  
         throws DocumentRendererException
 327  
     {
 328  42
         if ( getLogger().isDebugEnabled() )
 329  
         {
 330  0
             getLogger().debug( "Generating: " + pdfFile );
 331  
         }
 332  
 
 333  
         try
 334  
         {
 335  42
             FoUtils.convertFO2PDF( inputFile, pdfFile, null, documentModel );
 336  
         }
 337  0
         catch ( TransformerException e )
 338  
         {
 339  0
             if ( ( e.getCause() != null ) && ( e.getCause() instanceof SAXParseException ) )
 340  
             {
 341  0
                 SAXParseException sax = (SAXParseException) e.getCause();
 342  
 
 343  0
                 StringBuffer sb = new StringBuffer();
 344  0
                 sb.append( "Error creating PDF from " ).append( inputFile.getAbsolutePath() ).append( ":" )
 345  
                   .append( sax.getLineNumber() ).append( ":" ).append( sax.getColumnNumber() ).append( "\n" );
 346  0
                 sb.append( e.getMessage() );
 347  
 
 348  0
                 throw new DocumentRendererException( sb.toString() );
 349  
             }
 350  
 
 351  0
             throw new DocumentRendererException( "Error creating PDF from " + inputFile + ": " + e.getMessage() );
 352  42
         }
 353  42
     }
 354  
 }