diff options
-rw-r--r-- | src/java/org/apache/fop/fo/pagination/PageSequence.java | 8 | ||||
-rw-r--r-- | src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java | 1 | ||||
-rw-r--r-- | status.xml | 4 | ||||
-rw-r--r-- | test/java/org/apache/fop/memory/MemoryEater.java | 108 | ||||
-rw-r--r-- | test/xsl/fo-replicator.xsl | 72 |
5 files changed, 193 insertions, 0 deletions
diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java index 56796f0da..386ed694b 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java @@ -539,4 +539,12 @@ public class PageSequence extends FObj { return this.language; } + /** + * Releases a page-sequence's children after the page-sequence has been fully processed. + */ + public void releasePageSequence() { + this.mainFlow = null; + this.flowMap.clear(); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java index 567153aea..9a06896f3 100644 --- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java @@ -168,6 +168,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { (currentPageNum - startPageNum) + 1); areaTreeHandler.notifyPageSequenceFinished(pageSeq, (currentPageNum - startPageNum) + 1); + pageSeq.releasePageSequence(); log.debug("Ending layout"); } diff --git a/status.xml b/status.xml index a12885ecd..408dba617 100644 --- a/status.xml +++ b/status.xml @@ -29,6 +29,10 @@ <changes> <release version="FOP Trunk"> <action context="Code" dev="JM" type="fix"> + Fixed a memory-leak: The FO tree part of a page-sequence was not released when a + page-sequence was finished. + </action> + <action context="Code" dev="JM" type="fix"> Bugfix: Table headers and footers were swallowed when a table was nested in a list-block. </action> <action context="Code" dev="JM" type="fix"> diff --git a/test/java/org/apache/fop/memory/MemoryEater.java b/test/java/org/apache/fop/memory/MemoryEater.java new file mode 100644 index 000000000..ed8f46441 --- /dev/null +++ b/test/java/org/apache/fop/memory/MemoryEater.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/* $Id$ */ + +package org.apache.fop.memory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; + +/** + * Debug tool to create and process large FO files by replicating them a specified number of times. + */ +public class MemoryEater { + + private static void eatMemory(File foFile, int replicatorRepeats) throws Exception { + + SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + FopFactory fopFactory = FopFactory.newInstance(); + + File xsltFile = new File("test/xsl/fo-replicator.xsl"); + Source xslt = new StreamSource(xsltFile); + + Source src = new StreamSource(foFile); + + Transformer transformer = tFactory.newTransformer(xslt); + transformer.setParameter("repeats", new Integer(replicatorRepeats)); + + OutputStream out = new NullOutputStream(); //write to /dev/nul + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out); + Result res = new SAXResult(fop.getDefaultHandler()); + + transformer.transform(src, res); + + System.out.println("Generated " + fop.getResults().getPageCount() + " pages."); + + } + + private static void prompt() throws IOException { + BufferedReader in = new BufferedReader(new java.io.InputStreamReader(System.in)); + System.out.print("Press return to continue..."); + in.readLine(); + } + + /** + * Main method. + * @param args the command-line arguments + */ + public static void main(String[] args) { + boolean doPrompt = true; //true if you want a chance to start the monitoring console + try { + int replicatorRepeats = 2; + if (args.length > 0) { + replicatorRepeats = Integer.parseInt(args[0]); + } + File testFile = new File("examples/fo/basic/readme.fo"); + + System.out.println("MemoryEater! About to replicate the test file " + + replicatorRepeats + " times..."); + if (doPrompt) { + prompt(); + } + + System.out.println("Processing..."); + long start = System.currentTimeMillis(); + + eatMemory(testFile, replicatorRepeats); + + long duration = System.currentTimeMillis() - start; + System.out.println("Success! Job took " + duration + " ms"); + + if (doPrompt) { + prompt(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/test/xsl/fo-replicator.xsl b/test/xsl/fo-replicator.xsl new file mode 100644 index 000000000..0f2736cd0 --- /dev/null +++ b/test/xsl/fo-replicator.xsl @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. +--> +<!-- $Id$ --> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <xsl:param name="repeats" select="2"/> + <xsl:template match="@*|node()"> + <xsl:param name="run"/> + <xsl:copy> + <xsl:apply-templates select="@*|node()"> + <xsl:with-param name="run" select="$run"/> + </xsl:apply-templates> + </xsl:copy> + </xsl:template> + <xsl:template match="fo:root"> + <fo:root> + <xsl:apply-templates select="@*|fo:layout-master-set|fo:declarations"> + <xsl:with-param name="run" select="0"/> + </xsl:apply-templates> + <xsl:call-template name="repeat"> + <xsl:with-param name="n" select="$repeats"/> + <xsl:with-param name="what" select="fo:page-sequence"/> + </xsl:call-template> + </fo:root> + </xsl:template> + <xsl:template name="repeat"> + <xsl:param name="n"/> + <xsl:param name="what"/> + <xsl:if test="number($n) > 0"> + <xsl:apply-templates select="$what"> + <xsl:with-param name="run" select="$n"/> + </xsl:apply-templates> + <xsl:call-template name="repeat"> + <xsl:with-param name="n" select="number($n) - 1"/> + <xsl:with-param name="what" select="$what"/> + </xsl:call-template> + </xsl:if> + </xsl:template> + <xsl:template match="@id"> + <xsl:param name="run"/> + <xsl:attribute name="id"><xsl:value-of select="."/>-<xsl:value-of select="$run"/></xsl:attribute> + </xsl:template> + <xsl:template match="@ref-id"> + <xsl:param name="run"/> + <xsl:attribute name="ref-id"><xsl:value-of select="."/>-<xsl:value-of select="$run"/></xsl:attribute> + </xsl:template> + <xsl:template match="@internal-destination"> + <xsl:param name="run"/> + <xsl:attribute name="internal-destination"><xsl:value-of select="."/>-<xsl:value-of select="$run"/></xsl:attribute> + </xsl:template> + <xsl:template match="fo:page-number-citation"> + <xsl:param name="run"/> + <fo:inline><xsl:value-of select="@ref-id"/></fo:inline> + </xsl:template> + <xsl:template match="fo:retrieve-marker|fo:marker"> + <xsl:param name="run"/> + </xsl:template> +</xsl:stylesheet> |