Coverage Report - org.apache.maven.doxia.docrenderer.pdf.itext.ITextPdfRenderer
 
Classes in this File Line Coverage Branch Coverage Complexity
ITextPdfRenderer
73%
163/223
62%
46/74
5,133
 
 1  
 package org.apache.maven.doxia.docrenderer.pdf.itext;
 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.FileInputStream;
 24  
 import java.io.FileOutputStream;
 25  
 import java.io.IOException;
 26  
 import java.io.Writer;
 27  
 import java.net.MalformedURLException;
 28  
 import java.net.URL;
 29  
 import java.net.URLClassLoader;
 30  
 import java.text.SimpleDateFormat;
 31  
 import java.util.Collection;
 32  
 import java.util.Date;
 33  
 import java.util.Iterator;
 34  
 import java.util.LinkedList;
 35  
 import java.util.List;
 36  
 import java.util.Locale;
 37  
 import java.util.Map;
 38  
 
 39  
 import javax.xml.parsers.DocumentBuilder;
 40  
 import javax.xml.parsers.DocumentBuilderFactory;
 41  
 import javax.xml.parsers.ParserConfigurationException;
 42  
 import javax.xml.transform.OutputKeys;
 43  
 import javax.xml.transform.Transformer;
 44  
 import javax.xml.transform.TransformerConfigurationException;
 45  
 import javax.xml.transform.TransformerException;
 46  
 import javax.xml.transform.TransformerFactory;
 47  
 import javax.xml.transform.dom.DOMSource;
 48  
 import javax.xml.transform.stream.StreamResult;
 49  
 import javax.xml.transform.stream.StreamSource;
 50  
 
 51  
 import org.apache.maven.doxia.docrenderer.DocumentRendererContext;
 52  
 import org.apache.maven.doxia.docrenderer.DocumentRendererException;
 53  
 import org.apache.maven.doxia.docrenderer.pdf.AbstractPdfRenderer;
 54  
 import org.apache.maven.doxia.document.DocumentCover;
 55  
 import org.apache.maven.doxia.document.DocumentMeta;
 56  
 import org.apache.maven.doxia.document.DocumentModel;
 57  
 import org.apache.maven.doxia.document.DocumentTOCItem;
 58  
 import org.apache.maven.doxia.module.itext.ITextSink;
 59  
 import org.apache.maven.doxia.module.itext.ITextSinkFactory;
 60  
 import org.apache.maven.doxia.module.itext.ITextUtil;
 61  
 import org.apache.maven.doxia.module.site.SiteModule;
 62  
 import org.apache.xml.utils.DefaultErrorHandler;
 63  
 import org.codehaus.plexus.util.IOUtil;
 64  
 import org.codehaus.plexus.util.StringUtils;
 65  
 import org.codehaus.plexus.util.WriterFactory;
 66  
 import org.w3c.dom.DOMException;
 67  
 import org.w3c.dom.Document;
 68  
 import org.w3c.dom.Node;
 69  
 import org.xml.sax.SAXException;
 70  
 
 71  
 import com.lowagie.text.ElementTags;
 72  
 
 73  
 /**
 74  
  * Abstract <code>document</code> render with the <code>iText</code> framework
 75  
  *
 76  
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 77  
  * @author ltheussl
 78  
  * @version $Id: ITextPdfRenderer.java 1187064 2011-10-20 21:41:24Z rfscholte $
 79  
  * @since 1.1
 80  
  * @plexus.component role="org.apache.maven.doxia.docrenderer.pdf.PdfRenderer" role-hint="itext"
 81  
  */
 82  4
 public class ITextPdfRenderer
 83  
     extends AbstractPdfRenderer
 84  
 {
 85  
     /** The xslt style sheet used to transform a Document to an iText file. */
 86  
     private static final String XSLT_RESOURCE = "TOC.xslt";
 87  
 
 88  
     /** The TransformerFactory. */
 89  2
     private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
 90  
 
 91  
     /** The DocumentBuilderFactory. */
 92  2
     private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
 93  
 
 94  
     /** The DocumentBuilder. */
 95  
     private static final DocumentBuilder DOCUMENT_BUILDER;
 96  
 
 97  
     static
 98  
     {
 99  2
         TRANSFORMER_FACTORY.setErrorListener( new DefaultErrorHandler() );
 100  
 
 101  
         try
 102  
         {
 103  2
             DOCUMENT_BUILDER = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder();
 104  
         }
 105  0
         catch ( ParserConfigurationException e )
 106  
         {
 107  0
             throw new RuntimeException( "Error building document :" + e.getMessage() );
 108  2
         }
 109  2
     }
 110  
 
 111  
     /** {@inheritDoc} */
 112  
     public void generatePdf( File inputFile, File pdfFile )
 113  
         throws DocumentRendererException
 114  
     {
 115  14
         if ( getLogger().isDebugEnabled() )
 116  
         {
 117  0
             getLogger().debug( "Generating : " + pdfFile );
 118  
         }
 119  
 
 120  
         try
 121  
         {
 122  14
             ITextUtil.writePdf( new FileInputStream( inputFile ), new FileOutputStream( pdfFile ) );
 123  
         }
 124  0
         catch ( IOException e )
 125  
         {
 126  0
             throw new DocumentRendererException( "Cannot create PDF from " + inputFile + ": " + e.getMessage(), e );
 127  
         }
 128  0
         catch ( RuntimeException e )
 129  
         {
 130  0
             throw new DocumentRendererException( "Error creating PDF from " + inputFile + ": " + e.getMessage(), e );
 131  14
         }
 132  14
     }
 133  
 
 134  
     /** {@inheritDoc} */
 135  
     @Override
 136  
     public void render( Map<String, SiteModule> filesToProcess, File outputDirectory, DocumentModel documentModel )
 137  
         throws DocumentRendererException, IOException
 138  
     {
 139  0
         render( filesToProcess, outputDirectory, documentModel, null );
 140  0
     }
 141  
 
 142  
     /** {@inheritDoc} */
 143  
     @Override
 144  
     public void render( Map<String, SiteModule> filesToProcess, File outputDirectory, DocumentModel documentModel,
 145  
                         DocumentRendererContext context )
 146  
         throws DocumentRendererException, IOException
 147  
     {
 148  
         // copy resources, images, etc.
 149  4
         copyResources( outputDirectory );
 150  
 
 151  4
         if ( documentModel == null )
 152  
         {
 153  2
             getLogger().debug( "No document model, generating all documents individually." );
 154  
 
 155  2
             renderIndividual( filesToProcess, outputDirectory, context );
 156  2
             return;
 157  
         }
 158  
 
 159  2
         String outputName = getOutputName( documentModel );
 160  
 
 161  2
         File outputITextFile = new File( outputDirectory, outputName + ".xml" );
 162  2
         if ( !outputITextFile.getParentFile().exists() )
 163  
         {
 164  0
             outputITextFile.getParentFile().mkdirs();
 165  
         }
 166  
 
 167  2
         File pdfOutputFile = new File( outputDirectory, outputName + ".pdf" );
 168  2
         if ( !pdfOutputFile.getParentFile().exists() )
 169  
         {
 170  0
             pdfOutputFile.getParentFile().mkdirs();
 171  
         }
 172  
 
 173  
         List<File> iTextFiles;
 174  2
         if ( ( documentModel.getToc() == null ) || ( documentModel.getToc().getItems() == null ) )
 175  
         {
 176  0
             getLogger().info( "No TOC is defined in the document descriptor. Merging all documents." );
 177  
 
 178  0
             iTextFiles = parseAllFiles( filesToProcess, outputDirectory, context );
 179  
         }
 180  
         else
 181  
         {
 182  2
             getLogger().debug( "Using TOC defined in the document descriptor." );
 183  
 
 184  2
             iTextFiles = parseTOCFiles( outputDirectory, documentModel, context );
 185  
         }
 186  
 
 187  2
         String generateTOC =
 188  
             ( context != null && context.get( "generateTOC" ) != null ? context.get( "generateTOC" ).toString()
 189  
                             : "start" );
 190  
 
 191  2
         File iTextFile = new File( outputDirectory, outputName + ".xml" );
 192  2
         File iTextOutput = new File( outputDirectory, outputName + "." + getOutputExtension() );
 193  2
         Document document = generateDocument( iTextFiles );
 194  2
         transform( documentModel, document, iTextFile, generateTOC );
 195  2
         generatePdf( iTextFile, iTextOutput );
 196  2
     }
 197  
 
 198  
     /** {@inheritDoc} */
 199  
     @Override
 200  
     public void renderIndividual( Map<String, SiteModule> filesToProcess, File outputDirectory )
 201  
         throws DocumentRendererException, IOException
 202  
     {
 203  0
         renderIndividual( filesToProcess, outputDirectory, null );
 204  0
     }
 205  
 
 206  
     /** {@inheritDoc} */
 207  
     @Override
 208  
     public void renderIndividual( Map<String, SiteModule> filesToProcess, File outputDirectory,
 209  
                                   DocumentRendererContext context )
 210  
         throws DocumentRendererException, IOException
 211  
     {
 212  2
         for ( Map.Entry<String, SiteModule> entry : filesToProcess.entrySet() )
 213  
         {
 214  12
             String key = entry.getKey();
 215  12
             SiteModule module = entry.getValue();
 216  12
             File fullDoc = new File( getBaseDir(), module.getSourceDirectory() + File.separator + key );
 217  
 
 218  12
             String output = key;
 219  12
             String lowerCaseExtension = module.getExtension().toLowerCase( Locale.ENGLISH );
 220  12
             if ( output.toLowerCase( Locale.ENGLISH ).indexOf( "." + lowerCaseExtension ) != -1 )
 221  
             {
 222  12
                 output =
 223  
                     output.substring( 0, output.toLowerCase( Locale.ENGLISH ).indexOf( "." + lowerCaseExtension ) );
 224  
             }
 225  
 
 226  12
             File outputITextFile = new File( outputDirectory, output + ".xml" );
 227  12
             if ( !outputITextFile.getParentFile().exists() )
 228  
             {
 229  2
                 outputITextFile.getParentFile().mkdirs();
 230  
             }
 231  
 
 232  12
             File pdfOutputFile = new File( outputDirectory, output + ".pdf" );
 233  12
             if ( !pdfOutputFile.getParentFile().exists() )
 234  
             {
 235  0
                 pdfOutputFile.getParentFile().mkdirs();
 236  
             }
 237  
 
 238  12
             parse( fullDoc, module, outputITextFile, context );
 239  
 
 240  12
             generatePdf( outputITextFile, pdfOutputFile );
 241  12
         }
 242  2
     }
 243  
 
 244  
       //--------------------------------------------
 245  
      //
 246  
     //--------------------------------------------
 247  
 
 248  
 
 249  
     /**
 250  
      * Parse a source document and emit results into a sink.
 251  
      *
 252  
      * @param fullDocPath file to the source document.
 253  
      * @param module the site module associated with the source document (determines the parser to use).
 254  
      * @param iTextFile the resulting iText xml file.
 255  
      * @throws DocumentRendererException in case of a parsing problem.
 256  
      * @throws IOException if the source and/or target document cannot be opened.
 257  
      */
 258  
     private void parse( File fullDoc, SiteModule module, File iTextFile, DocumentRendererContext context )
 259  
         throws DocumentRendererException, IOException
 260  
     {
 261  24
         if ( getLogger().isDebugEnabled() )
 262  
         {
 263  0
             getLogger().debug( "Parsing file " + fullDoc.getAbsolutePath() );
 264  
         }
 265  
 
 266  24
         System.setProperty( "itext.basedir", iTextFile.getParentFile().getAbsolutePath() );
 267  
 
 268  24
         Writer writer = null;
 269  24
         ITextSink sink = null;
 270  
         try
 271  
         {
 272  24
             writer = WriterFactory.newXmlWriter( iTextFile );
 273  24
             sink = (ITextSink) new ITextSinkFactory().createSink( writer );
 274  
 
 275  24
             sink.setClassLoader( new URLClassLoader( new URL[] { iTextFile.getParentFile().toURI().toURL() } ) );
 276  
 
 277  24
             parse( fullDoc.getAbsolutePath(), module.getParserId(), sink, context );
 278  
         }
 279  
         finally
 280  
         {
 281  24
             if ( sink != null )
 282  
             {
 283  24
                 sink.flush();
 284  24
                 sink.close();
 285  
             }
 286  24
             IOUtil.close( writer );
 287  24
             System.getProperties().remove( "itext.basedir" );
 288  24
         }
 289  24
     }
 290  
 
 291  
     /**
 292  
      * Merge all iTextFiles to a single one.
 293  
      *
 294  
      * @param iTextFiles list of iText xml files.
 295  
      * @return Document.
 296  
      * @throws DocumentRendererException if any.
 297  
      * @throws IOException if any.
 298  
      */
 299  
     private Document generateDocument( List<File> iTextFiles )
 300  
         throws DocumentRendererException, IOException
 301  
     {
 302  2
         Document document = DOCUMENT_BUILDER.newDocument();
 303  2
         document.appendChild( document.createElement( ElementTags.ITEXT ) ); // Used only to set a root
 304  
 
 305  2
         for ( File iTextFile : iTextFiles )
 306  
         {
 307  
             Document iTextDocument;
 308  
 
 309  
             try
 310  
             {
 311  12
                 iTextDocument = DOCUMENT_BUILDER.parse( iTextFile );
 312  
             }
 313  0
             catch ( SAXException e )
 314  
             {
 315  0
                 throw new DocumentRendererException( "SAX Error : " + e.getMessage() );
 316  12
             }
 317  
 
 318  
             // Only one chapter per doc
 319  12
             Node chapter = iTextDocument.getElementsByTagName( ElementTags.CHAPTER ).item( 0 );
 320  
 
 321  
             try
 322  
             {
 323  12
                 document.getDocumentElement().appendChild( document.importNode( chapter, true ) );
 324  
             }
 325  0
             catch ( DOMException e )
 326  
             {
 327  0
                 throw new DocumentRendererException( "Error appending chapter for "
 328  
                         + iTextFile + " : " + e.getMessage() );
 329  12
             }
 330  12
         }
 331  
 
 332  2
         return document;
 333  
     }
 334  
 
 335  
     /**
 336  
      * Initialize the transformer object.
 337  
      *
 338  
      * @return an instance of a transformer object.
 339  
      * @throws DocumentRendererException if any.
 340  
      */
 341  
     private Transformer initTransformer()
 342  
         throws DocumentRendererException
 343  
     {
 344  
         try
 345  
         {
 346  2
             Transformer transformer = TRANSFORMER_FACTORY.newTransformer( new StreamSource( ITextPdfRenderer.class
 347  
                 .getResourceAsStream( XSLT_RESOURCE ) ) );
 348  
 
 349  2
             transformer.setErrorListener( TRANSFORMER_FACTORY.getErrorListener() );
 350  
 
 351  2
             transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "false" );
 352  
 
 353  2
             transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
 354  
 
 355  2
             transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
 356  
 
 357  2
             transformer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
 358  
 
 359  
             // No doctype since itext doctype is not up to date!
 360  
 
 361  2
             return transformer;
 362  
         }
 363  0
         catch ( TransformerConfigurationException e )
 364  
         {
 365  0
             throw new DocumentRendererException( "Error configuring Transformer for " + XSLT_RESOURCE + ": "
 366  
                 + e.getMessage() );
 367  
         }
 368  0
         catch ( IllegalArgumentException e )
 369  
         {
 370  0
             throw new DocumentRendererException( "Error configuring Transformer for " + XSLT_RESOURCE + ": "
 371  
                 + e.getMessage() );
 372  
         }
 373  
     }
 374  
 
 375  
     /**
 376  
      * Add transformer parameters from a DocumentModel.
 377  
      *
 378  
      * @param transformer the Transformer to set the parameters.
 379  
      * @param documentModel the DocumentModel to take the parameters from, could be null.
 380  
      * @param iTextFile the iTextFile not null for the relative paths.
 381  
      * @param generateTOC not null, possible values are: 'none', 'start' and 'end'.
 382  
      */
 383  
     private void addTransformerParameters( Transformer transformer, DocumentModel documentModel, File iTextFile,
 384  
                                            String generateTOC )
 385  
     {
 386  2
         if ( documentModel == null )
 387  
         {
 388  0
             return;
 389  
         }
 390  
 
 391  
         // TOC
 392  2
         addTransformerParameter( transformer, "toc.position", generateTOC );
 393  
 
 394  
         // Meta parameters
 395  2
         boolean hasNullMeta = false;
 396  2
         if ( documentModel.getMeta() == null )
 397  
         {
 398  0
             hasNullMeta = true;
 399  0
             documentModel.setMeta( new DocumentMeta() );
 400  
         }
 401  2
         addTransformerParameter( transformer, "meta.author", documentModel.getMeta().getAllAuthorNames(),
 402  
                                  System.getProperty( "user.name", "null" ) );
 403  2
         addTransformerParameter( transformer, "meta.creator", documentModel.getMeta().getCreator(),
 404  
                                  System.getProperty( "user.name", "null" ) );
 405  
         // see com.lowagie.text.Document#addCreationDate()
 406  2
         SimpleDateFormat sdf = new SimpleDateFormat( "EEE MMM dd HH:mm:ss zzz yyyy" );
 407  2
         addTransformerParameter( transformer, "meta.creationdate", documentModel.getMeta().getCreationdate(),
 408  
                                  sdf.format( new Date() ) );
 409  2
         addTransformerParameter( transformer, "meta.keywords", documentModel.getMeta().getAllKeyWords() );
 410  2
         addTransformerParameter( transformer, "meta.pagesize", documentModel.getMeta().getPageSize(),
 411  
                                  ITextUtil.getPageSize( ITextUtil.getDefaultPageSize() ) );
 412  2
         addTransformerParameter( transformer, "meta.producer", documentModel.getMeta().getGenerator(),
 413  
                                  "Apache Doxia iText" );
 414  2
         addTransformerParameter( transformer, "meta.subject", documentModel.getMeta().getSubject(),
 415  
                                  ( documentModel.getMeta().getTitle() != null ? documentModel.getMeta().getTitle()
 416  
                                                  : "" ) );
 417  2
         addTransformerParameter( transformer, "meta.title", documentModel.getMeta().getTitle() );
 418  2
         if ( hasNullMeta )
 419  
         {
 420  0
             documentModel.setMeta( null );
 421  
         }
 422  
 
 423  
         // cover parameter
 424  2
         boolean hasNullCover = false;
 425  2
         if ( documentModel.getCover() == null )
 426  
         {
 427  0
             hasNullCover = true;
 428  0
             documentModel.setCover( new DocumentCover() );
 429  
         }
 430  2
         addTransformerParameter( transformer, "cover.author", documentModel.getCover().getAllAuthorNames(),
 431  
                                  System.getProperty( "user.name", "null" ) );
 432  2
         String companyLogo = getLogoURL( documentModel.getCover().getCompanyLogo(), iTextFile.getParentFile() );
 433  2
         addTransformerParameter( transformer, "cover.companyLogo", companyLogo );
 434  2
         addTransformerParameter( transformer, "cover.companyName", documentModel.getCover().getCompanyName() );
 435  2
         if ( documentModel.getCover().getCoverdate() == null )
 436  
         {
 437  2
             documentModel.getCover().setCoverDate( new Date() );
 438  2
             addTransformerParameter( transformer, "cover.date", documentModel.getCover().getCoverdate() );
 439  2
             documentModel.getCover().setCoverDate( null );
 440  
         }
 441  
         else
 442  
         {
 443  0
             addTransformerParameter( transformer, "cover.date", documentModel.getCover().getCoverdate() );
 444  
         }
 445  2
         addTransformerParameter( transformer, "cover.subtitle", documentModel.getCover().getCoverSubTitle() );
 446  2
         addTransformerParameter( transformer, "cover.title", documentModel.getCover().getCoverTitle() );
 447  2
         addTransformerParameter( transformer, "cover.type", documentModel.getCover().getCoverType() );
 448  2
         addTransformerParameter( transformer, "cover.version", documentModel.getCover().getCoverVersion() );
 449  2
         String projectLogo = getLogoURL( documentModel.getCover().getProjectLogo(), iTextFile.getParentFile() );
 450  2
         addTransformerParameter( transformer, "cover.projectLogo", projectLogo );
 451  2
         addTransformerParameter( transformer, "cover.projectName", documentModel.getCover().getProjectName() );
 452  2
         if ( hasNullCover )
 453  
         {
 454  0
             documentModel.setCover( null );
 455  
         }
 456  2
     }
 457  
 
 458  
     /**
 459  
      * @param transformer not null
 460  
      * @param name not null
 461  
      * @param value could be empty
 462  
      * @param defaultValue could be empty
 463  
      * @since 1.1.1
 464  
      */
 465  
     private void addTransformerParameter( Transformer transformer, String name, String value, String defaultValue )
 466  
     {
 467  14
         if ( StringUtils.isEmpty( value ) )
 468  
         {
 469  12
             addTransformerParameter( transformer, name, defaultValue );
 470  
         }
 471  
         else
 472  
         {
 473  2
             addTransformerParameter( transformer, name, value );
 474  
         }
 475  14
     }
 476  
 
 477  
     /**
 478  
      * @param transformer not null
 479  
      * @param name not null
 480  
      * @param value could be empty
 481  
      * @since 1.1.1
 482  
      */
 483  
     private void addTransformerParameter( Transformer transformer, String name, String value )
 484  
     {
 485  38
         if ( StringUtils.isEmpty( value ) )
 486  
         {
 487  4
             return;
 488  
         }
 489  
 
 490  34
         transformer.setParameter( name, value );
 491  34
     }
 492  
 
 493  
     /**
 494  
      * Transform a document to an iTextFile.
 495  
      *
 496  
      * @param documentModel the DocumentModel to take the parameters from, could be null.
 497  
      * @param document the Document to transform.
 498  
      * @param iTextFile the resulting iText xml file.
 499  
      * @param generateTOC not null, possible values are: 'none', 'start' and 'end'.
 500  
      * @throws DocumentRendererException in case of a transformation error.
 501  
      */
 502  
     private void transform( DocumentModel documentModel, Document document, File iTextFile, String generateTOC )
 503  
         throws DocumentRendererException
 504  
     {
 505  2
         Transformer transformer = initTransformer();
 506  
 
 507  2
         addTransformerParameters( transformer, documentModel, iTextFile, generateTOC );
 508  
 
 509  
         // need a writer for StreamResult to prevent FileNotFoundException when iTextFile contains spaces
 510  2
         Writer writer = null;
 511  
         try
 512  
         {
 513  2
             writer = WriterFactory.newXmlWriter( iTextFile );
 514  2
             transformer.transform( new DOMSource( document ), new StreamResult( writer ) );
 515  
         }
 516  0
         catch ( TransformerException e )
 517  
         {
 518  0
             throw new DocumentRendererException(
 519  
                                                  "Error transforming Document " + document + ": " + e.getMessage(),
 520  
                                                  e );
 521  
         }
 522  0
         catch ( IOException e )
 523  
         {
 524  0
             throw new DocumentRendererException(
 525  
                                                  "Error transforming Document " + document + ": " + e.getMessage(),
 526  
                                                  e );
 527  
         }
 528  
         finally
 529  
         {
 530  2
             IOUtil.close( writer );
 531  2
         }
 532  2
     }
 533  
 
 534  
     /**
 535  
      * @param filesToProcess not null
 536  
      * @param outputDirectory not null
 537  
      * @return a list of all parsed files.
 538  
      * @throws DocumentRendererException if any
 539  
      * @throws IOException if any
 540  
      * @since 1.1.1
 541  
      */
 542  
     private List<File> parseAllFiles( Map<String, SiteModule> filesToProcess, File outputDirectory,
 543  
                                       DocumentRendererContext context )
 544  
         throws DocumentRendererException, IOException
 545  
     {
 546  0
         List<File> iTextFiles = new LinkedList<File>();
 547  0
         for ( Map.Entry<String, SiteModule> entry : filesToProcess.entrySet() )
 548  
         {
 549  0
             String key = entry.getKey();
 550  0
             SiteModule module = entry.getValue();
 551  0
             File fullDoc = new File( getBaseDir(), module.getSourceDirectory() + File.separator + key );
 552  
 
 553  0
             String outputITextName = key.substring( 0, key.lastIndexOf( '.') + 1 ) + "xml";
 554  0
             File outputITextFileTmp = new File( outputDirectory, outputITextName );
 555  0
             outputITextFileTmp.deleteOnExit();
 556  0
             if ( !outputITextFileTmp.getParentFile().exists() )
 557  
             {
 558  0
                 outputITextFileTmp.getParentFile().mkdirs();
 559  
             }
 560  
 
 561  0
             iTextFiles.add( outputITextFileTmp );
 562  0
             parse( fullDoc, module, outputITextFileTmp, context );
 563  0
         }
 564  
 
 565  0
         return iTextFiles;
 566  
     }
 567  
 
 568  
     /**
 569  
      * @param filesToProcess not null
 570  
      * @param outputDirectory not null
 571  
      * @return a list of all parsed files.
 572  
      * @throws DocumentRendererException if any
 573  
      * @throws IOException if any
 574  
      * @since 1.1.1
 575  
      */
 576  
     private List<File> parseTOCFiles( File outputDirectory, DocumentModel documentModel, DocumentRendererContext context )
 577  
         throws DocumentRendererException, IOException
 578  
     {
 579  2
         List<File> iTextFiles = new LinkedList<File>();
 580  2
         for ( Iterator<DocumentTOCItem> it = documentModel.getToc().getItems().iterator(); it.hasNext(); )
 581  
         {
 582  12
             DocumentTOCItem tocItem = it.next();
 583  
 
 584  12
             if ( tocItem.getRef() == null )
 585  
             {
 586  0
                 getLogger().debug(
 587  
                                    "No ref defined for the tocItem '" + tocItem.getName()
 588  
                                        + "' in the document descriptor. IGNORING" );
 589  0
                 continue;
 590  
             }
 591  
 
 592  12
             String href = StringUtils.replace( tocItem.getRef(), "\\", "/" );
 593  12
             if ( href.lastIndexOf( '.') != -1 )
 594  
             {
 595  12
                 href = href.substring( 0, href.lastIndexOf( '.') );
 596  
             }
 597  
 
 598  12
             Collection<SiteModule> modules = siteModuleManager.getSiteModules();
 599  12
             for ( SiteModule module : modules )
 600  
             {
 601  48
                 File moduleBasedir = new File( getBaseDir(), module.getSourceDirectory() );
 602  
 
 603  48
                 if ( moduleBasedir.exists() )
 604  
                 {
 605  36
                     String doc = href + "." + module.getExtension();
 606  36
                     File source = new File( moduleBasedir, doc );
 607  
 
 608  
                     // Velocity file?
 609  36
                     if ( !source.exists() )
 610  
                     {
 611  24
                         if ( href.indexOf( "." + module.getExtension() ) != -1 )
 612  
                         {
 613  0
                             doc = href + ".vm";
 614  
                         }
 615  
                         else
 616  
                         {
 617  24
                             doc = href + "." + module.getExtension() + ".vm";
 618  
                         }
 619  24
                         source = new File( moduleBasedir, doc );
 620  
                     }
 621  
 
 622  36
                     if ( source.exists() )
 623  
                     {
 624  12
                         String outputITextName = doc.substring( 0, doc.lastIndexOf( '.') + 1 ) + "xml";
 625  12
                         File outputITextFileTmp = new File( outputDirectory, outputITextName );
 626  12
                         outputITextFileTmp.deleteOnExit();
 627  12
                         if ( !outputITextFileTmp.getParentFile().exists() )
 628  
                         {
 629  2
                             outputITextFileTmp.getParentFile().mkdirs();
 630  
                         }
 631  
 
 632  12
                         iTextFiles.add( outputITextFileTmp );
 633  12
                         parse( source, module, outputITextFileTmp, context );
 634  
                     }
 635  
                 }
 636  48
             }
 637  12
         }
 638  
 
 639  2
         return iTextFiles;
 640  
     }
 641  
 
 642  
     /**
 643  
      * @param logo
 644  
      * @param parentFile
 645  
      * @return the logo url or null if unable to create it.
 646  
      * @since 1.1.1
 647  
      */
 648  
     private String getLogoURL( String logo, File parentFile )
 649  
     {
 650  4
         if ( logo == null )
 651  
         {
 652  0
             return null;
 653  
         }
 654  
 
 655  
         try
 656  
         {
 657  4
             return new URL( logo ).toString();
 658  
         }
 659  4
         catch ( MalformedURLException e )
 660  
         {
 661  
             try
 662  
             {
 663  4
                 File f = new File( parentFile, logo );
 664  4
                 if ( !f.exists() )
 665  
                 {
 666  0
                     getLogger().warn( "The logo " + f.getAbsolutePath() + " doesnt exist. IGNORING" );
 667  
                 }
 668  
                 else
 669  
                 {
 670  4
                     return f.toURI().toURL().toString();
 671  
                 }
 672  
             }
 673  0
             catch ( MalformedURLException e1 )
 674  
             {
 675  0
                 getLogger().debug( "Failed to convert to URL: " + logo, e1 );
 676  0
             }
 677  
         }
 678  
 
 679  0
         return null;
 680  
     }
 681  
 }