Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
     Licensed to Plutext Pty Ltd under one or more contributor license agreements.  
     
   *  This file is part of docx4j.
  
      docx4j is licensed under the Apache License, Version 2.0 (the "License"); 
      you may not use this file except in compliance with the License. 
  
      You may obtain a copy of the License at 
 
         http://www.apache.org/licenses/LICENSE-2.0 
 
     Unless required by applicable law or agreed to in writing, software 
     distributed under the License is distributed on an "AS IS" BASIS, 
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     See the License for the specific language governing permissions and 
     limitations under the License.
 
  */
 package org.docx4j.convert.out.fo.renderers;
 
 import java.net.URI;
 import java.util.List;
 import java.util.Map;
 
 
The Apache FO Renderer uses Apache FOP to render the fo document and is the default FO Renderer
 
 public class FORendererApacheFOP extends AbstractFORenderer { //implements FORenderer {
 	
 	protected static Logger log = LoggerFactory.getLogger(FORendererApacheFOP.class);
 	protected static FORendererApacheFOP instance = null;
 
 	private static String XSL_FO = "http://www.w3.org/1999/XSL/Format";
 	
 	protected static class FopPlaceholderLookup extends AbstractPlaceholderLookup {
 		
 		public FopPlaceholderLookup(List<SectionPageInformationpageNumberInformation) {
 			super(pageNumberInformation);
 		}
 		
 		public void setResults(FormattingResults formattingResultsthrows Docx4JException {
 			
 			List<PageSequenceResultsresultList = null;
 			PageSequenceResults pageSequenceResults = null;
 			
 			if (formattingResults == null) {
 				throw new Docx4JException("Apache fop returned no FormattingResults (null)");
 			}
 			else {
 				resultList = formattingResults.getPageSequences();
 				if (resultList == null) {
 					throw new Docx4JException("Apache fop returned null pageSequences");
 				}
 				else if (resultList.size() != .size()) {
 					throw new Docx4JException("Apache fop returned different count of sections than expected, returned: " + resultList.size() + ", expected: " + .size());
 				}
			}
			putDocumentPageCount(formattingResults.getPageCount());
			for (int i=0; i<formattingResults.getPageSequences().size(); i++) {
				pageSequenceResults = resultList.get(i);
				putSectionPageCount(ipageSequenceResults.getPageCount());
			}
		}
	}
	public void render(String foDocumentFOSettings settings
			boolean twoPass,
			List<SectionPageInformationpageNumberInformation,
			OutputStream outputStreamthrows Docx4JException {
		String apacheFopConfiguration = setupApacheFopConfiguration(settings);
		String apacheFopMime = setupApacheFopMime(settings);
		StreamSource foDocumentSrc = new StreamSource(new StringReader(foDocument));
		FopPlaceholderLookup placeholderLookup = null;
		FormattingResults formattingResults = null;
		FopFactory fopFactory = null;
		try {
			fopFactory = getFopFactory(apacheFopConfiguration);
catch (FOPException e) {
			throw new Docx4JException("Exception creating fop factory for rendering: " + e.getMessage(), e);
		}
		if (twoPass) {
			//1st pass in 2 pass
			.debug("1st pass in 2 pass");
			placeholderLookup = new FopPlaceholderLookup(pageNumberInformation);
			formattingResults = calcResults(fopFactoryapacheFopMimefoDocumentSrcplaceholderLookup);
			placeholderLookup.setResults(formattingResults);
			foDocumentSrc = new StreamSource(new StringReader(foDocument));
		}
		//1st pass in 1 pass or 2nd pass in 2 pass
//			System.out.println("\n\n performing TEXTBOX_POSTPROCESSING \n\n");
			DOMResult result = new DOMResult(); 
			org.docx4j.XmlUtils.transform(foDocumentSrcnullresult);		
			org.w3c.dom.Document docResult = ((org.w3c.dom.Document)result.getNode());
			String modifiedFO = XmlUtils.w3CDomNodeToString(docResult); 
			.debug("After moving! \n" + modifiedFO);	
			foDocumentSrc = new StreamSource(new StringReader(modifiedFO));
		}
		render(fopFactoryapacheFopMimefoDocumentSrcplaceholderLookupoutputStream);
	}
	String ret = settings.getApacheFopConfiguration();
		if (ret == null) {
			ret = FopConfigUtil.createDefaultConfiguration(wmlPackage.getFontMapper(), 
		}
		return ret;
	}
	private String setupApacheFopMime(FOSettings settings) {
	String ret = settings.getApacheFopMime();
		if (ret == null) {
		}
		return ret;
	}
	public static FORenderer getInstance() {
		if ( == null) {
			synchronized (FORendererApacheFOP.class) {
				if ( == null) {
				}
			}
		}
		return ;
	}
	protected void render(FopFactory fopFactoryString outputFormatSource foDocumentSrcPlaceholderReplacementHandler.PlaceholderLookup placeholderLookupOutputStream outputStreamthrows Docx4JException {
		Fop fop = null;
		Result result = null;
		try {
			fop = fopFactory.newFop(outputFormatoutputStream);
			result = (placeholderLookup == null ?
					//1 Pass
					//2 Pass
					new SAXResult(new PlaceholderReplacementHandler(fop.getDefaultHandler(), placeholderLookup)));
catch (FOPException e) {
			throw new Docx4JException("Exception setting up result for fo transformation: " + e.getMessage(), e);
		}
		Transformer transformer;
		try {
			transformer = XmlUtils.getTransformerFactory().newTransformer();
			transformer.transform(foDocumentSrcresult);
			throw new Docx4JException("Exception setting up transformer: " + e.getMessage(), e);
catch (TransformerException e) {
			throw new Docx4JException("Exception executing transformer: " + e.getMessage(), e);
		}
	}


For first pass of two pass process, invoke org.apache.fop.apps.FormattingResults which can tell us the number of pages in each page sequence, and in the document as a whole.

Parameters:
fopFactory
outputFormat
foDocumentSrc
placeholderLookup
Returns:
Throws:
org.docx4j.openpackaging.exceptions.Docx4JException
	protected FormattingResults calcResults(FopFactory fopFactoryString outputFormatSource foDocumentSrcPlaceholderReplacementHandler.PlaceholderLookup placeholderLookupthrows Docx4JException {
		Fop fop = null;
		Result result = null;
		try {
			fop = fopFactory.newFop(outputFormatnew NullOutputStream());
			result = new SAXResult(new PlaceholderReplacementHandler(fop.getDefaultHandler(), placeholderLookup));
catch (FOPException e) {
			throw new Docx4JException("Exception setting up result for fo transformation: " + e.getMessage(), e);
		}
		Transformer transformer;
		try {
			transformer = XmlUtils.getTransformerFactory().newTransformer();
			transformer.transform(foDocumentSrcresult);
			throw new Docx4JException("Exception setting up transformer: " + e.getMessage(), e);
catch (TransformerException e) {
			throw new Docx4JException("Exception executing transformer: " + e.getMessage(), e);
		}
		return fop.getResults();
	}
	protected Fop createFop(String userConfigurationString outputFormatOutputStream outputStreamthrows FOPException {
		FopFactory fopFactory = getFopFactory(userConfiguration);
		return fopFactory.newFop(outputFormat != null ? outputFormat : .outputStream);
	}
	protected FopFactory getFopFactory(String userConfigthrows FOPException {
		//The current implementation doesn't pass the user config to the fop factory 
		//if there is only a factory per Thread, all documents rendered in that  
		//Thread would use the configuration done for the first document.
		//For this reason disable the reuse of the FopFactories until this issue 
		//gets resolved.
		return createFopFactory(userConfig);
//		FopFactory fopFactory = fopFactories.get(Thread.currentThread().getId());
//		if (fopFactory == null) {
//			synchronized(fopFactories) {
//				fopFactory = createFopFactory(userConfig);
//				fopFactories.put(Thread.currentThread().getId(), fopFactory);
//			}
//		}
//		fopFactory.setUserConfig(userConfig);
//		return fopFactory;
	}

Create and configure FopFactory.

Parameters:
userConfig
defaultBaseURI
Returns:
Throws:
org.apache.fop.apps.FOPException
	protected FopFactory createFopFactory(String userConfigthrows FOPException {
		// This class won't compile unless you have some version of FOP on your path. 
		/* 
		 * Unfortunately, <=1.1 requires Configuration object,
		 * and >1.1 requires InputStream.
		 * 
		 * So either we pass Configuration object into this method, 
		 * and use DefaultConfigurationSerializer to get an input stream from it,
		 * or we pass a string, and make it into a Configuration object in the case
		 * where it is required. 
		 * 
		 * I've submitted a patch to FOP allowing configuration
		 * using a Configuration object.  Let's see whether it is applied.
		 * 
		 * In the absence of that, passing a String (or an InputStream) seems better going forward.
		 * So that's what the code accepts for now.
		 */
		InputStream is=null;
		try {
			is = IOUtils.toInputStream(userConfig"UTF-8");
catch (IOException e2) {
		}
		FopFactory fopFactory = null;
		// If FopConfParser is on path, it is post 1.1
		try {
			Class fopConfParserClass = Class.forName("org.apache.fop.apps.FopConfParser");
			URI defaultBaseURI = new URI("http://dummy.domain");
				// Default base URI must not be null, but we don't need it.
				// at org.apache.fop.apps.EnvironmentalProfileFactory$Profile (EnvironmentalProfileFactory.java:92)
			Object o = fopConfParserClass.getConstructor(InputStream.classURI.class).newInstance(isdefaultBaseURI);
			Method method = fopConfParserClass.getDeclaredMethod("getFopFactoryBuilder"new Class[0] );
			Object fopFactoryBuilder = method.invoke(o);
			Class fopFactoryBuilderClass = Class.forName("org.apache.fop.apps.FopFactoryBuilder");
			method = fopFactoryBuilderClass.getDeclaredMethod("build"new Class[0] );
			fopFactory = (FopFactory)method.invoke(fopFactoryBuilder);
catch (Exception e) {
			.warn("Can't set up FOP svn; " + e.getMessage() );
			// eg java.lang.ClassNotFoundException: org.apache.fop.apps.FopConfParser
			// legacy FOP 1.0 or 1.1 config.
			try {
				Method method;
				Class[] params = new Class[1];
				// FopFactory fopFactory = FopFactory.newInstance();
				method = FopFactory.class.getDeclaredMethod("newInstance"new Class[0] );
				fopFactory = (FopFactory)method.invoke(null);
				// fopFactory.setUserConfig(userConfig);
				params[0] = Configuration.class;				
				method = FopFactory.class.getDeclaredMethod("setUserConfig"params );
				// There isn't a method which takes it as a string :-(
				method.invoke(fopFactorycfgBuilder.build(is) );
catch (Exception e1) {
				// java.lang.IllegalAccessException: Class org.docx4j.fonts.fop.util.FopFactoryUtil 
				// can not access a member of class org.apache.fop.apps.FopFactory 
				// with modifiers "protected"
		}
		return fopFactory;
	}
New to GrepCode? Check out our FAQ X