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 1187064 2011-10-20 21:41:24Z rfscholte $
 55  
  * @since 1.1
 56  
  * @plexus.component role="org.apache.maven.doxia.docrenderer.pdf.PdfRenderer" role-hint="fo"
 57  
  */
 58  4
 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  
     @Override
 74  
     public void render( Map<String, SiteModule> filesToProcess, File outputDirectory, DocumentModel documentModel )
 75  
         throws DocumentRendererException, IOException
 76  
     {
 77  0
         render( filesToProcess, outputDirectory, documentModel, null );
 78  0
     }
 79  
 
 80  
     /** {@inheritDoc} */
 81  
     @Override
 82  
     public void render( Map<String, SiteModule> filesToProcess, File outputDirectory, DocumentModel documentModel,
 83  
                         DocumentRendererContext context )
 84  
         throws DocumentRendererException, IOException
 85  
     {
 86  
         // copy resources, images, etc.
 87  4
         copyResources( outputDirectory );
 88  
 
 89  4
         if ( documentModel == null )
 90  
         {
 91  2
             getLogger().debug( "No document model, generating all documents individually." );
 92  
 
 93  2
             renderIndividual( filesToProcess, outputDirectory, context );
 94  2
             return;
 95  
         }
 96  
 
 97  2
         String outputName = getOutputName( documentModel );
 98  
 
 99  2
         File outputFOFile = new File( outputDirectory, outputName + ".fo" );
 100  2
         if ( !outputFOFile.getParentFile().exists() )
 101  
         {
 102  0
             outputFOFile.getParentFile().mkdirs();
 103  
         }
 104  
 
 105  2
         File pdfOutputFile = new File( outputDirectory, outputName + ".pdf" );
 106  2
         if ( !pdfOutputFile.getParentFile().exists() )
 107  
         {
 108  0
             pdfOutputFile.getParentFile().mkdirs();
 109  
         }
 110  
 
 111  2
         Writer writer = null;
 112  
         try
 113  
         {
 114  2
             writer = WriterFactory.newXmlWriter( outputFOFile );
 115  
 
 116  2
             FoAggregateSink sink = new FoAggregateSink( writer );
 117  
 
 118  2
             File fOConfigFile = new File( outputDirectory, "pdf-config.xml" );
 119  
 
 120  2
             if ( fOConfigFile.exists() )
 121  
             {
 122  0
                 sink.load( fOConfigFile );
 123  0
                 getLogger().debug( "Loaded pdf config file: " + fOConfigFile.getAbsolutePath() );
 124  
             }
 125  
 
 126  2
             String generateTOC =
 127  
                 ( context != null && context.get( "generateTOC" ) != null ? context.get( "generateTOC" ).toString().trim()
 128  
                                 : "start" );
 129  2
             int tocPosition = 0;
 130  2
             if ( "start".equalsIgnoreCase( generateTOC ) )
 131  
             {
 132  2
                 tocPosition = FoAggregateSink.TOC_START;
 133  
             }
 134  0
             else if ( "end".equalsIgnoreCase( generateTOC ) )
 135  
             {
 136  0
                 tocPosition = FoAggregateSink.TOC_END;
 137  
             }
 138  
             else
 139  
             {
 140  0
                 tocPosition = FoAggregateSink.TOC_NONE;
 141  
             }
 142  2
             sink.setDocumentModel( documentModel, tocPosition );
 143  
 
 144  2
             sink.beginDocument();
 145  
 
 146  2
             sink.coverPage();
 147  
 
 148  2
             if ( tocPosition == FoAggregateSink.TOC_START )
 149  
             {
 150  2
                 sink.toc();
 151  
             }
 152  
 
 153  2
             if ( ( documentModel.getToc() == null ) || ( documentModel.getToc().getItems() == null ) )
 154  
             {
 155  0
                 getLogger().info( "No TOC is defined in the document descriptor. Merging all documents." );
 156  
 
 157  0
                 mergeAllSources( filesToProcess, sink, context );
 158  
             }
 159  
             else
 160  
             {
 161  2
                 getLogger().debug( "Using TOC defined in the document descriptor." );
 162  
 
 163  2
                 mergeSourcesFromTOC( documentModel.getToc(), sink, context );
 164  
             }
 165  
 
 166  2
             if ( tocPosition == FoAggregateSink.TOC_END )
 167  
             {
 168  0
                 sink.toc();
 169  
             }
 170  
 
 171  2
             sink.endDocument();
 172  
         }
 173  
         finally
 174  
         {
 175  2
             IOUtil.close( writer );
 176  2
         }
 177  
 
 178  2
         generatePdf( outputFOFile, pdfOutputFile, documentModel );
 179  2
     }
 180  
 
 181  
     /** {@inheritDoc} */
 182  
     @Override
 183  
     public void renderIndividual( Map<String, SiteModule> filesToProcess, File outputDirectory )
 184  
         throws DocumentRendererException, IOException
 185  
     {
 186  0
         renderIndividual( filesToProcess, outputDirectory, null );
 187  0
     }
 188  
 
 189  
     /** {@inheritDoc} */
 190  
     @Override
 191  
     public void renderIndividual( Map<String, SiteModule> filesToProcess, File outputDirectory,
 192  
                                   DocumentRendererContext context )
 193  
         throws DocumentRendererException, IOException
 194  
     {
 195  2
         for ( Map.Entry<String, SiteModule> entry : filesToProcess.entrySet() )
 196  
         {
 197  12
             String key = entry.getKey();
 198  12
             SiteModule module = entry.getValue();
 199  
 
 200  12
             File fullDoc = new File( getBaseDir(), module.getSourceDirectory() + File.separator + key );
 201  
 
 202  12
             String output = key;
 203  12
             String lowerCaseExtension = module.getExtension().toLowerCase( Locale.ENGLISH );
 204  12
             if ( output.toLowerCase( Locale.ENGLISH ).indexOf( "." + lowerCaseExtension ) != -1 )
 205  
             {
 206  12
                 output =
 207  
                     output.substring( 0, output.toLowerCase( Locale.ENGLISH ).indexOf( "." + lowerCaseExtension ) );
 208  
             }
 209  
 
 210  12
             File outputFOFile = new File( outputDirectory, output + ".fo" );
 211  12
             if ( !outputFOFile.getParentFile().exists() )
 212  
             {
 213  2
                 outputFOFile.getParentFile().mkdirs();
 214  
             }
 215  
 
 216  12
             File pdfOutputFile = new File( outputDirectory, output + ".pdf" );
 217  12
             if ( !pdfOutputFile.getParentFile().exists() )
 218  
             {
 219  0
                 pdfOutputFile.getParentFile().mkdirs();
 220  
             }
 221  
 
 222  12
             FoSink sink =
 223  
                 (FoSink) new FoSinkFactory().createSink( outputFOFile.getParentFile(), outputFOFile.getName() );
 224  12
             sink.beginDocument();
 225  12
             parse( fullDoc.getAbsolutePath(), module.getParserId(), sink, context );
 226  12
             sink.endDocument();
 227  
 
 228  12
             generatePdf( outputFOFile, pdfOutputFile, null );
 229  12
         }
 230  2
     }
 231  
 
 232  
     private void mergeAllSources( Map<String, SiteModule> filesToProcess, FoAggregateSink sink,
 233  
                                   DocumentRendererContext context )
 234  
         throws DocumentRendererException, IOException
 235  
     {
 236  0
         for ( Map.Entry<String, SiteModule> entry : filesToProcess.entrySet() )
 237  
         {
 238  0
             String key = entry.getKey();
 239  0
             SiteModule module = entry.getValue();
 240  0
             sink.setDocumentName( key );
 241  0
             File fullDoc = new File( getBaseDir(), module.getSourceDirectory() + File.separator + key );
 242  
 
 243  0
             parse( fullDoc.getAbsolutePath(), module.getParserId(), sink, context );
 244  0
         }
 245  0
     }
 246  
 
 247  
     private void mergeSourcesFromTOC( DocumentTOC toc, FoAggregateSink sink, DocumentRendererContext context )
 248  
         throws IOException, DocumentRendererException
 249  
     {
 250  2
         parseTocItems( toc.getItems(), sink, context );
 251  2
     }
 252  
 
 253  
     private void parseTocItems( List<DocumentTOCItem> items, FoAggregateSink sink, DocumentRendererContext context )
 254  
         throws IOException, DocumentRendererException
 255  
     {
 256  16
         for ( DocumentTOCItem tocItem : items )
 257  
         {
 258  14
             if ( tocItem.getRef() == null )
 259  
             {
 260  0
                 if ( getLogger().isInfoEnabled() )
 261  
                 {
 262  0
                     getLogger().info( "No ref defined for tocItem " + tocItem.getName() );
 263  
                 }
 264  
 
 265  
                 continue;
 266  
             }
 267  
 
 268  14
             String href = StringUtils.replace( tocItem.getRef(), "\\", "/" );
 269  14
             if ( href.lastIndexOf( '.') != -1 )
 270  
             {
 271  14
                 href = href.substring( 0, href.lastIndexOf( '.') );
 272  
             }
 273  
 
 274  14
             renderModules( href, sink, tocItem, context );
 275  
 
 276  14
             if ( tocItem.getItems() != null )
 277  
             {
 278  14
                 parseTocItems( tocItem.getItems(), sink, context );
 279  
             }
 280  14
         }
 281  16
     }
 282  
 
 283  
     private void renderModules( String href, FoAggregateSink sink, DocumentTOCItem tocItem,
 284  
                                 DocumentRendererContext context )
 285  
         throws DocumentRendererException, IOException
 286  
     {
 287  14
         Collection<SiteModule> modules = siteModuleManager.getSiteModules();
 288  14
         for ( SiteModule module : modules )
 289  
         {
 290  56
             File moduleBasedir = new File( getBaseDir(), module.getSourceDirectory() );
 291  
 
 292  56
             if ( moduleBasedir.exists() )
 293  
             {
 294  42
                 String doc = href + "." + module.getExtension();
 295  42
                 File source = new File( moduleBasedir, doc );
 296  
 
 297  
                 // Velocity file?
 298  42
                 if ( !source.exists() )
 299  
                 {
 300  30
                     if ( href.indexOf( "." + module.getExtension() ) != -1 )
 301  
                     {
 302  0
                         doc = href + ".vm";
 303  
                     }
 304  
                     else
 305  
                     {
 306  30
                         doc = href + "." + module.getExtension() + ".vm";
 307  
                     }
 308  30
                     source = new File( moduleBasedir, doc );
 309  
                 }
 310  
 
 311  42
                 if ( source.exists() )
 312  
                 {
 313  12
                     sink.setDocumentName( doc );
 314  12
                     sink.setDocumentTitle( tocItem.getName() );
 315  
 
 316  12
                     parse( source.getPath(), module.getParserId(), sink, context );
 317  
                 }
 318  
             }
 319  56
         }
 320  14
     }
 321  
 
 322  
     /**
 323  
      * @param inputFile
 324  
      * @param pdfFile
 325  
      * @param documentModel could be null
 326  
      * @throws DocumentRendererException if any
 327  
      * @since 1.1.1
 328  
      */
 329  
     private void generatePdf( File inputFile, File pdfFile, DocumentModel documentModel )
 330  
         throws DocumentRendererException
 331  
     {
 332  14
         if ( getLogger().isDebugEnabled() )
 333  
         {
 334  0
             getLogger().debug( "Generating: " + pdfFile );
 335  
         }
 336  
 
 337  
         try
 338  
         {
 339  14
             FoUtils.convertFO2PDF( inputFile, pdfFile, null, documentModel );
 340  
         }
 341  0
         catch ( TransformerException e )
 342  
         {
 343  0
             if ( ( e.getCause() != null ) && ( e.getCause() instanceof SAXParseException ) )
 344  
             {
 345  0
                 SAXParseException sax = (SAXParseException) e.getCause();
 346  
 
 347  0
                 StringBuilder sb = new StringBuilder();
 348  0
                 sb.append( "Error creating PDF from " ).append( inputFile.getAbsolutePath() ).append( ":" )
 349  
                   .append( sax.getLineNumber() ).append( ":" ).append( sax.getColumnNumber() ).append( "\n" );
 350  0
                 sb.append( e.getMessage() );
 351  
 
 352  0
                 throw new DocumentRendererException( sb.toString() );
 353  
             }
 354  
 
 355  0
             throw new DocumentRendererException( "Error creating PDF from " + inputFile + ": " + e.getMessage() );
 356  14
         }
 357  14
     }
 358  
 }