Coverage Report - org.apache.maven.doxia.docrenderer.itext.AbstractITextRender
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractITextRender
0%
0/162
0%
0/66
8,125
 
 1  
 package org.apache.maven.doxia.docrenderer.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.IOException;
 24  
 import java.io.Reader;
 25  
 import java.io.Writer;
 26  
 import java.net.URL;
 27  
 import java.net.URLClassLoader;
 28  
 import java.util.Collection;
 29  
 import java.util.Date;
 30  
 import java.util.Iterator;
 31  
 import java.util.LinkedList;
 32  
 import java.util.List;
 33  
 
 34  
 import javax.xml.parsers.DocumentBuilderFactory;
 35  
 import javax.xml.parsers.ParserConfigurationException;
 36  
 import javax.xml.transform.OutputKeys;
 37  
 import javax.xml.transform.Transformer;
 38  
 import javax.xml.transform.TransformerConfigurationException;
 39  
 import javax.xml.transform.TransformerException;
 40  
 import javax.xml.transform.TransformerFactory;
 41  
 import javax.xml.transform.dom.DOMSource;
 42  
 import javax.xml.transform.stream.StreamResult;
 43  
 import javax.xml.transform.stream.StreamSource;
 44  
 
 45  
 import org.apache.maven.doxia.Doxia;
 46  
 import org.apache.maven.doxia.docrenderer.DocRenderer;
 47  
 import org.apache.maven.doxia.docrenderer.DocumentRendererException;
 48  
 import org.apache.maven.doxia.document.DocumentModel;
 49  
 import org.apache.maven.doxia.document.DocumentTOCItem;
 50  
 import org.apache.maven.doxia.document.io.xpp3.DocumentXpp3Reader;
 51  
 import org.apache.maven.doxia.module.itext.ITextSink;
 52  
 import org.apache.maven.doxia.module.itext.ITextSinkFactory;
 53  
 import org.apache.maven.doxia.module.itext.ITextUtil;
 54  
 import org.apache.maven.doxia.module.site.SiteModule;
 55  
 import org.apache.maven.doxia.module.site.manager.SiteModuleManager;
 56  
 import org.apache.maven.doxia.parser.ParseException;
 57  
 import org.apache.maven.doxia.parser.manager.ParserNotFoundException;
 58  
 import org.apache.xml.utils.DefaultErrorHandler;
 59  
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 60  
 import org.codehaus.plexus.util.FileUtils;
 61  
 import org.codehaus.plexus.util.IOUtil;
 62  
 import org.codehaus.plexus.util.ReaderFactory;
 63  
 import org.codehaus.plexus.util.StringUtils;
 64  
 import org.codehaus.plexus.util.WriterFactory;
 65  
 import org.codehaus.plexus.util.xml.XmlUtil;
 66  
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 67  
 import org.w3c.dom.DOMException;
 68  
 import org.w3c.dom.Document;
 69  
 import org.w3c.dom.Node;
 70  
 import org.xml.sax.SAXException;
 71  
 
 72  
 import com.lowagie.text.ElementTags;
 73  
 
 74  
 /**
 75  
  * Abstract <code>document</code> render with the <code>iText</code> framework
 76  
  *
 77  
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 78  
  * @version $Id: AbstractITextRender.java 1087124 2011-03-30 22:45:41Z hboutemy $
 79  
  * @deprecated since 1.1, use an implementation of {@link org.apache.maven.doxia.docrenderer.DocumentRenderer}.
 80  
  */
 81  0
 public abstract class AbstractITextRender
 82  
     extends AbstractLogEnabled
 83  
     implements DocRenderer
 84  
 {
 85  
     private static final String XSLT_RESOURCE = "org/apache/maven/doxia/docrenderer/pdf/itext/TOC.xslt";
 86  
 
 87  0
     private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
 88  
 
 89  0
     private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
 90  
 
 91  
     /**
 92  
      * @plexus.requirement
 93  
      */
 94  
     protected SiteModuleManager siteModuleManager;
 95  
 
 96  
     /**
 97  
      * @plexus.requirement
 98  
      */
 99  
     protected Doxia doxia;
 100  
 
 101  
     static
 102  
     {
 103  0
         TRANSFORMER_FACTORY.setErrorListener( new DefaultErrorHandler() );
 104  0
     }
 105  
 
 106  
     /** {@inheritDoc} */
 107  
     public void render( File siteDirectory, File outputDirectory )
 108  
         throws DocumentRendererException, IOException
 109  
     {
 110  0
         Collection<SiteModule> modules = siteModuleManager.getSiteModules();
 111  0
         for ( SiteModule module : modules )
 112  
         {
 113  0
             File moduleBasedir = new File( siteDirectory, module.getSourceDirectory() );
 114  
 
 115  0
             if ( moduleBasedir.exists() )
 116  
             {
 117  0
                 List<String> docs =
 118  
                     FileUtils.getFileNames( moduleBasedir, "**/*." + module.getExtension(), null, false );
 119  
 
 120  0
                 for ( String doc : docs )
 121  
                 {
 122  0
                     String fullPathDoc = new File( moduleBasedir, doc ).getPath();
 123  
 
 124  0
                     String outputITextName = doc.substring( 0, doc.indexOf( "." ) + 1 ) + "xml";
 125  0
                     File outputITextFile = new File( outputDirectory, outputITextName );
 126  0
                     if ( !outputITextFile.getParentFile().exists() )
 127  
                     {
 128  0
                         outputITextFile.getParentFile().mkdirs();
 129  
                     }
 130  0
                     String iTextOutputName = doc.substring( 0, doc.indexOf( "." ) + 1 ) + getOutputExtension();
 131  0
                     File iTextOutputFile = new File( outputDirectory, iTextOutputName );
 132  0
                     if ( !iTextOutputFile.getParentFile().exists() )
 133  
                     {
 134  0
                         iTextOutputFile.getParentFile().mkdirs();
 135  
                     }
 136  
 
 137  0
                     parse( fullPathDoc, module, outputITextFile );
 138  
 
 139  0
                     generateOutput( outputITextFile, iTextOutputFile );
 140  0
                 }
 141  
             }
 142  0
         }
 143  0
     }
 144  
 
 145  
     /** {@inheritDoc} */
 146  
     public void render( File siteDirectory, File outputDirectory, File documentDescriptor )
 147  
         throws DocumentRendererException, IOException
 148  
     {
 149  0
         if ( ( documentDescriptor == null ) || ( !documentDescriptor.exists() ) )
 150  
         {
 151  0
             if ( getLogger().isInfoEnabled() )
 152  
             {
 153  0
                 getLogger().info( "No documentDescriptor is found. Generate all documents." );
 154  
             }
 155  0
             render( siteDirectory, outputDirectory );
 156  0
             return;
 157  
         }
 158  
 
 159  
         DocumentModel documentModel;
 160  0
         Reader reader = null;
 161  
         try
 162  
         {
 163  0
             reader = ReaderFactory.newXmlReader( documentDescriptor );
 164  0
             documentModel = new DocumentXpp3Reader().read( reader );
 165  
         }
 166  0
         catch ( XmlPullParserException e )
 167  
         {
 168  0
             throw new DocumentRendererException( "Error parsing document descriptor", e );
 169  
         }
 170  0
         catch ( IOException e )
 171  
         {
 172  0
             throw new DocumentRendererException( "Error reading document descriptor", e );
 173  
         }
 174  
         finally
 175  
         {
 176  0
             IOUtil.close( reader );
 177  0
         }
 178  
 
 179  0
         if ( documentModel.getOutputName() == null )
 180  
         {
 181  0
             if ( getLogger().isInfoEnabled() )
 182  
             {
 183  0
                 getLogger().info( "No outputName is defined in the document descriptor. Using 'generated_itext'" );
 184  
             }
 185  0
             documentModel.setOutputName( "generated_itext" );
 186  
         }
 187  
 
 188  0
         if ( ( documentModel.getToc() == null ) || ( documentModel.getToc().getItems() == null ) )
 189  
         {
 190  0
             if ( getLogger().isInfoEnabled() )
 191  
             {
 192  0
                 getLogger().info( "No TOC is defined in the document descriptor. Merging all documents." );
 193  
             }
 194  
         }
 195  
 
 196  0
         List<File> iTextFiles = new LinkedList<File>();
 197  0
         Collection<SiteModule> modules = siteModuleManager.getSiteModules();
 198  0
         for ( SiteModule module : modules )
 199  
         {
 200  0
             File moduleBasedir = new File( siteDirectory, module.getSourceDirectory() );
 201  
 
 202  0
             if ( moduleBasedir.exists() )
 203  
             {
 204  0
                 List<String> docs =
 205  
                     FileUtils.getFileNames( moduleBasedir, "**/*." + module.getExtension(), null, false );
 206  
 
 207  0
                 for ( String doc : docs )
 208  
                 {
 209  0
                     String fullPathDoc = new File( moduleBasedir, doc ).getPath();
 210  
 
 211  0
                     String outputITextName = doc.substring( 0, doc.lastIndexOf( "." ) + 1 ) + "xml";
 212  0
                     File outputITextFile = new File( outputDirectory, outputITextName );
 213  
 
 214  0
                     if ( ( documentModel.getToc() == null ) || ( documentModel.getToc().getItems() == null ) )
 215  
                     {
 216  0
                         iTextFiles.add( outputITextFile );
 217  
 
 218  0
                         if ( !outputITextFile.getParentFile().exists() )
 219  
                         {
 220  0
                             outputITextFile.getParentFile().mkdirs();
 221  
                         }
 222  
 
 223  0
                         parse( fullPathDoc, module, outputITextFile );
 224  
                     }
 225  
                     else
 226  
                     {
 227  0
                         for ( Iterator<DocumentTOCItem> k = documentModel.getToc().getItems().iterator(); k.hasNext(); )
 228  
                         {
 229  0
                             DocumentTOCItem tocItem = k.next();
 230  
 
 231  0
                             if ( tocItem.getRef() == null )
 232  
                             {
 233  0
                                 if ( getLogger().isInfoEnabled() )
 234  
                                 {
 235  0
                                     getLogger().info( "No ref defined for an tocItem in the document descriptor." );
 236  
                                 }
 237  
                                 continue;
 238  
                             }
 239  
 
 240  0
                             String outTmp = StringUtils.replace( outputITextFile.getAbsolutePath(), "\\", "/" );
 241  0
                             outTmp = outTmp.substring( 0, outTmp.lastIndexOf( "." ) );
 242  
 
 243  0
                             String outRef = StringUtils.replace( tocItem.getRef(), "\\", "/" );
 244  0
                             if ( outRef.lastIndexOf( "." ) != -1 )
 245  
                             {
 246  0
                                 outRef = outRef.substring( 0, outRef.lastIndexOf( "." ) );
 247  
                             }
 248  
                             else
 249  
                             {
 250  0
                                 outRef = outRef.substring( 0, outRef.length() );
 251  
                             }
 252  
 
 253  0
                             if ( outTmp.indexOf( outRef ) != -1 )
 254  
                             {
 255  0
                                 iTextFiles.add( outputITextFile );
 256  
 
 257  0
                                 if ( !outputITextFile.getParentFile().exists() )
 258  
                                 {
 259  0
                                     outputITextFile.getParentFile().mkdirs();
 260  
                                 }
 261  
 
 262  0
                                 parse( fullPathDoc, module, outputITextFile );
 263  
                             }
 264  0
                         }
 265  
                     }
 266  0
                 }
 267  
             }
 268  0
         }
 269  
 
 270  0
         File iTextFile = new File( outputDirectory, documentModel.getOutputName() + ".xml" );
 271  0
         File iTextOutput = new File( outputDirectory, documentModel.getOutputName() + "." + getOutputExtension() );
 272  0
         Document document = generateDocument( iTextFiles );
 273  0
         transform( documentModel, document, iTextFile );
 274  0
         generateOutput( iTextFile, iTextOutput );
 275  0
     }
 276  
 
 277  
     /**
 278  
      * Generate an ouput file with the iText framework
 279  
      *
 280  
      * @param iTextFile
 281  
      * @param iTextOutput
 282  
      * @throws org.apache.maven.doxia.docrenderer.DocumentRendererException if any
 283  
      * @throws java.io.IOException if any
 284  
      */
 285  
     public abstract void generateOutput( File iTextFile, File iTextOutput )
 286  
         throws DocumentRendererException, IOException;
 287  
 
 288  
     /**
 289  
      * Parse a sink
 290  
      *
 291  
      * @param fullPathDoc
 292  
      * @param module
 293  
      * @param outputITextFile
 294  
      * @throws org.apache.maven.doxia.docrenderer.DocumentRendererException
 295  
      * @throws java.io.IOException
 296  
      */
 297  
     private void parse( String fullPathDoc, SiteModule module, File outputITextFile )
 298  
         throws DocumentRendererException, IOException
 299  
     {
 300  0
         Writer writer = WriterFactory.newXmlWriter( outputITextFile );
 301  0
         ITextSink sink = (ITextSink) new ITextSinkFactory().createSink( writer );
 302  
 
 303  0
         sink.setClassLoader( new URLClassLoader( new URL[] { outputITextFile.getParentFile().toURI().toURL() } ) );
 304  
 
 305  0
         Reader reader = null;
 306  
         try
 307  
         {
 308  0
             File f = new File( fullPathDoc );
 309  0
             if ( XmlUtil.isXml( f ) )
 310  
             {
 311  0
                 reader = ReaderFactory.newXmlReader( f );
 312  
             }
 313  
             else
 314  
             {
 315  
                 // TODO Platform dependent?
 316  0
                 reader = ReaderFactory.newPlatformReader( f );
 317  
             }
 318  
 
 319  0
             System.setProperty( "itext.basedir", outputITextFile.getParentFile().getAbsolutePath() );
 320  
 
 321  0
             doxia.parse( reader, module.getParserId(), sink );
 322  
         }
 323  0
         catch ( ParserNotFoundException e )
 324  
         {
 325  0
             throw new DocumentRendererException( "Error getting a parser for '"
 326  
                     + fullPathDoc + "': " + e.getMessage() );
 327  
         }
 328  0
         catch ( ParseException e )
 329  
         {
 330  0
             throw new DocumentRendererException( "Error parsing '"
 331  
                     + fullPathDoc + "': line [" + e.getLineNumber() + "] " + e.getMessage(), e );
 332  
         }
 333  
         finally
 334  
         {
 335  0
             IOUtil.close( reader );
 336  
 
 337  0
             sink.flush();
 338  
 
 339  0
             sink.close();
 340  
 
 341  0
             IOUtil.close( writer );
 342  
 
 343  0
             System.getProperties().remove( "itext.basedir" );
 344  0
         }
 345  0
     }
 346  
 
 347  
     /**
 348  
      * Merge all iTextFiles to a single one
 349  
      *
 350  
      * @param iTextFiles
 351  
      * @return a document
 352  
      * @throws org.apache.maven.doxia.docrenderer.DocumentRendererException if any
 353  
      * @throws java.io.IOException if any
 354  
      */
 355  
     private Document generateDocument( List<File> iTextFiles )
 356  
         throws DocumentRendererException, IOException
 357  
     {
 358  
         Document document;
 359  
         try
 360  
         {
 361  0
             document = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().newDocument();
 362  
         }
 363  0
         catch ( ParserConfigurationException e )
 364  
         {
 365  0
             throw new DocumentRendererException( "Error building document :" + e.getMessage() );
 366  0
         }
 367  0
         document.appendChild( document.createElement( ElementTags.ITEXT ) ); // Used only to set a root
 368  
 
 369  0
         for ( File iTextFile : iTextFiles )
 370  
         {
 371  
             Document iTextDocument;
 372  
             try
 373  
             {
 374  0
                 iTextDocument = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse( iTextFile );
 375  
             }
 376  0
             catch ( SAXException e )
 377  
             {
 378  0
                 throw new DocumentRendererException( "SAX Error : " + e.getMessage() );
 379  
             }
 380  0
             catch ( ParserConfigurationException e )
 381  
             {
 382  0
                 throw new DocumentRendererException( "Error parsing configuration : " + e.getMessage() );
 383  0
             }
 384  
 
 385  
             // Only one chapter per doc
 386  0
             Node chapter = iTextDocument.getElementsByTagName( ElementTags.CHAPTER ).item( 0 );
 387  
             try
 388  
             {
 389  0
                 document.getDocumentElement().appendChild( document.importNode( chapter, true ) );
 390  
             }
 391  0
             catch ( DOMException e )
 392  
             {
 393  0
                 throw new DocumentRendererException( "Error appending chapter for "
 394  
                         + iTextFile + " : " + e.getMessage() );
 395  0
             }
 396  0
         }
 397  
 
 398  0
         return document;
 399  
     }
 400  
 
 401  
     /**
 402  
      * Init the transformer object
 403  
      *
 404  
      * @return an instanced transformer object
 405  
      * @throws org.apache.maven.doxia.docrenderer.DocumentRendererException if any
 406  
      */
 407  
     private Transformer initTransformer()
 408  
         throws DocumentRendererException
 409  
     {
 410  
         try
 411  
         {
 412  0
             Transformer transformer = TRANSFORMER_FACTORY.newTransformer( new StreamSource( DefaultPdfRenderer.class
 413  
                 .getResourceAsStream( "/" + XSLT_RESOURCE ) ) );
 414  0
             transformer.setErrorListener( TRANSFORMER_FACTORY.getErrorListener() );
 415  
 
 416  0
             transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "false" );
 417  0
             transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
 418  0
             transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
 419  0
             transformer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
 420  
 
 421  0
             return transformer;
 422  
         }
 423  0
         catch ( TransformerConfigurationException e )
 424  
         {
 425  0
             throw new DocumentRendererException( "Error configuring Transformer for " + XSLT_RESOURCE + ": "
 426  
                 + e.getMessage() );
 427  
         }
 428  0
         catch ( IllegalArgumentException e )
 429  
         {
 430  0
             throw new DocumentRendererException( "Error configuring Transformer for " + XSLT_RESOURCE + ": "
 431  
                 + e.getMessage() );
 432  
         }
 433  
     }
 434  
 
 435  
     /**
 436  
      * Add transformer parameters
 437  
      *
 438  
      * @param transformer
 439  
      * @param documentModel
 440  
      */
 441  
     private void addTransformerParameters( Transformer transformer, DocumentModel documentModel )
 442  
     {
 443  0
         if ( documentModel.getMeta().getTitle() != null )
 444  
         {
 445  0
             transformer.setParameter( "title", documentModel.getMeta().getTitle() );
 446  
         }
 447  0
         if ( documentModel.getMeta().getAuthor() != null )
 448  
         {
 449  0
             transformer.setParameter( "author", documentModel.getMeta().getAuthor() );
 450  
         }
 451  0
         transformer.setParameter( "creationdate", new Date().toString() );
 452  0
         if ( documentModel.getMeta().getSubject() != null )
 453  
         {
 454  0
             transformer.setParameter( "subject", documentModel.getMeta().getSubject() );
 455  
         }
 456  0
         if ( documentModel.getMeta().getKeywords() != null )
 457  
         {
 458  0
             transformer.setParameter( "keywords", documentModel.getMeta().getKeywords() );
 459  
         }
 460  0
         transformer.setParameter( "producer", "Generated with Doxia by " + System.getProperty( "user.name" ) );
 461  0
         if ( ITextUtil.isPageSizeSupported( documentModel.getMeta().getTitle() ) )
 462  
         {
 463  0
             transformer.setParameter( "pagesize", documentModel.getMeta().getPageSize() );
 464  
         }
 465  
         else
 466  
         {
 467  0
             transformer.setParameter( "pagesize", "A4" );
 468  
         }
 469  
 
 470  0
         transformer.setParameter( "frontPageHeader", "" );
 471  0
         if ( documentModel.getMeta().getTitle() != null )
 472  
         {
 473  0
             transformer.setParameter( "frontPageTitle", documentModel.getMeta().getTitle() );
 474  
         }
 475  0
         transformer.setParameter( "frontPageFooter", "Generated date " + new Date().toString() );
 476  0
     }
 477  
 
 478  
     /**
 479  
      * Transform a document to an iTextFile
 480  
      *
 481  
      * @param documentModel
 482  
      * @param document
 483  
      * @param iTextFile
 484  
      * @throws org.apache.maven.doxia.docrenderer.DocumentRendererException if any.
 485  
      */
 486  
     private void transform( DocumentModel documentModel, Document document, File iTextFile )
 487  
         throws DocumentRendererException
 488  
     {
 489  0
         Transformer transformer = initTransformer();
 490  
 
 491  0
         addTransformerParameters( transformer, documentModel );
 492  
 
 493  
         try
 494  
         {
 495  0
             transformer.transform( new DOMSource( document ), new StreamResult( iTextFile ) );
 496  
         }
 497  0
         catch ( TransformerException e )
 498  
         {
 499  0
             throw new DocumentRendererException( "Error transformer Document from "
 500  
                     + document + ": " + e.getMessage() );
 501  0
         }
 502  0
     }
 503  
 }