You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2010/10/07 09:41:49 UTC

svn commit: r1005350 - in /xmlgraphics/fop/trunk: ./ src/documentation/content/xdocs/trunk/ src/java/org/apache/fop/afp/ src/java/org/apache/fop/afp/modca/ src/java/org/apache/fop/afp/parser/ src/java/org/apache/fop/afp/util/ src/java/org/apache/fop/re...

Author: jeremias
Date: Thu Oct  7 07:41:48 2010
New Revision: 1005350

URL: http://svn.apache.org/viewvc?rev=1005350&view=rev
Log:
Bugzilla #49379:
Added ability to embed an external AFP page segment resource file (AFP output only).
Submitted by: Peter Hancock <peter.hancock.at.gmail.com>

Changes to patch:
- Replaced AFP parsing code with a more universal MO:DCA parser (as discussed).
- AFPDocumentHandler: addressed a TODO (clearing of the page segment map was not necessary for each page)
- AFPDocumentHandler: merged pageSegmentMap and pageSegmentUriMap by creating a combined object: PageSegmentDescriptor

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/PageSegmentDescriptor.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPPageSegmentElement.java   (with props)
Modified:
    xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/output.xml
    xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPResourceManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPStreamer.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/parser/MODCAParser.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/StructuredFieldReader.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPPainter.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
    xmlgraphics/fop/trunk/status.xml

Modified: xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/output.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/output.xml?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/output.xml (original)
+++ xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/output.xml Thu Oct  7 07:41:48 2010
@@ -885,6 +885,13 @@ Note that the value of the encoding attr
           segment in the generated file. Please also note that page segments cannot be scaled.
           They are always rendered in their intrinsic size.
         </p>
+        <p>
+          The include-page-segment extension element has the optional attribute
+          <i>resource-file</i>. The value of this is a URI to a resource containing a page
+          segment with the declared name. In this case FOP embeds the page segment into the
+          generated document so that the external resource does not have to be supplied in the
+          print job.
+        </p>
       </section>
       <section id="afp-tag-logical-element">
         <title>Tag Logical Element (TLE) Extension</title>

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPResourceManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPResourceManager.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPResourceManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPResourceManager.java Thu Oct  7 07:41:48 2010
@@ -19,12 +19,15 @@
 
 package org.apache.fop.afp;
 
+import java.io.BufferedInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Map;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -38,6 +41,7 @@ import org.apache.fop.afp.modca.PageSegm
 import org.apache.fop.afp.modca.Registry;
 import org.apache.fop.afp.modca.ResourceGroup;
 import org.apache.fop.afp.modca.ResourceObject;
+import org.apache.fop.afp.util.AFPResourceUtil;
 import org.apache.fop.afp.util.ResourceAccessor;
 
 /**
@@ -314,6 +318,57 @@ public class AFPResourceManager {
     }
 
     /**
+     * Creates an included resource extracting the named resource from an external source.
+     * @param resourceName the name of the resource
+     * @param uri the URI for the resource
+     * @param accessor resource accessor to access the resource with
+     * @throws IOException if an I/O error occurs while loading the resource
+     */
+    public void createIncludedResourceFromExternal(final String resourceName,
+            final URI uri, final ResourceAccessor accessor) throws IOException {
+
+        AFPResourceLevel resourceLevel = new AFPResourceLevel(AFPResourceLevel.PRINT_FILE);
+
+        AFPResourceInfo resourceInfo = new AFPResourceInfo();
+        resourceInfo.setLevel(resourceLevel);
+        resourceInfo.setName(resourceName);
+        resourceInfo.setUri(uri.toASCIIString());
+
+        String resource = (String)includeNameMap.get(resourceInfo);
+        if (resource == null) {
+
+            ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel);
+
+            //resourceObject delegates write commands to copyNamedResource()
+            //The included resource may already be wrapped in a resource object
+            AbstractNamedAFPObject resourceObject = new AbstractNamedAFPObject(null) {
+
+                protected void writeContent(OutputStream os) throws IOException {
+                    InputStream inputStream = null;
+                    try {
+                        inputStream = accessor.createInputStream(uri);
+                        BufferedInputStream bin = new BufferedInputStream(inputStream);
+                        AFPResourceUtil.copyNamedResource(resourceName, bin, os);
+                    } finally {
+                        IOUtils.closeQuietly(inputStream);
+                    }
+                }
+
+                //bypass super.writeStart
+                protected void writeStart(OutputStream os) throws IOException { }
+                //bypass super.writeEnd
+                protected void writeEnd(OutputStream os) throws IOException { }
+            };
+
+            resourceGroup.addObject(resourceObject);
+
+            includeNameMap.put(resourceInfo, resourceName);
+
+        }
+    }
+
+
+    /**
      * Sets resource level defaults. The existing defaults over merged with the ones passed in
      * as parameter.
      * @param defaults the new defaults

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPStreamer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPStreamer.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPStreamer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/AFPStreamer.java Thu Oct  7 07:41:48 2010
@@ -158,7 +158,7 @@ public class AFPStreamer implements Stre
      */
         // write out any external resource groups
     public void close() throws IOException {
-        Iterator it = pathResourceGroupMap.entrySet().iterator();
+        Iterator it = pathResourceGroupMap.values().iterator();
         while (it.hasNext()) {
             StreamedResourceGroup resourceGroup = (StreamedResourceGroup)it.next();
             resourceGroup.close();

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java Thu Oct  7 07:41:48 2010
@@ -26,6 +26,7 @@ import java.net.URI;
 
 import org.apache.commons.io.IOUtils;
 
+import org.apache.fop.afp.util.AFPResourceUtil;
 import org.apache.fop.afp.util.ResourceAccessor;
 
 
@@ -54,7 +55,7 @@ public class IncludedResourceObject exte
     public void writeToStream(OutputStream os) throws IOException {
         InputStream in = resourceAccessor.createInputStream(this.uri);
         try {
-            IOUtils.copy(in, os);
+            AFPResourceUtil.copyResourceFile(in, os);
         } finally {
             IOUtils.closeQuietly(in);
         }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/parser/MODCAParser.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/parser/MODCAParser.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/parser/MODCAParser.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/parser/MODCAParser.java Thu Oct  7 07:41:48 2010
@@ -29,6 +29,9 @@ import java.io.InputStream;
  */
 public class MODCAParser {
 
+    /** The carriage control character (0x5A) used to indicate the start of a structured field. */
+    public static final byte CARRIAGE_CONTROL_CHAR = (byte)(0x5A & 0xFF);
+
     private DataInputStream din;
 
     /**
@@ -61,10 +64,11 @@ public class MODCAParser {
         try {
             while (true) {
                 byte b = din.readByte(); //Skip 0x5A character if necessary (ex. AFP)
-                if (b == 0x0D || b == 0x0A) { //CR and LF may be used as field delimiters
+                if (b == 0x0D || b == 0x0A) {
+                    //CR and LF may be used as field delimiters
                     continue;
-                } else if (b == 0x5A) { //Carriage Control Character
-                    break;
+                } else if (b == CARRIAGE_CONTROL_CHAR) {
+                    break; //Signals the start of a new structured field
                 }
             }
         } catch (EOFException eof) {

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java?rev=1005350&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java Thu Oct  7 07:41:48 2010
@@ -0,0 +1,214 @@
+/*
+ * 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.afp.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.modca.ResourceObject;
+import org.apache.fop.afp.modca.AbstractAFPObject.Category;
+import org.apache.fop.afp.parser.MODCAParser;
+import org.apache.fop.afp.parser.UnparsedStructuredField;
+
+/**
+ * TODO better docs
+ * Utility for AFP resource handling
+ *
+ *
+ * A utility class to read structured fields from a MO:DCA document. Each
+ * component of a mixed object document is explicitly defined and delimited
+ * in the data. This is accomplished through the use of MO:DCA data structures,
+ * called structured fields. Structured fields are used to envelop document
+ * components and to provide commands and information to applications using
+ * the data. Structured fields may contain one or more parameters. Each
+ * parameter provides one value from a set of values defined by the architecture.
+ * <p/>
+ * MO:DCA structured fields consist of two parts: an introducer that identifies
+ * the length and type of the structured field, and data that provides the
+ * structured field's effect. The data is contained in a set of parameters,
+ * which can consist of other data structures and data elements. The maximum
+ * length of a structured field is 32767 bytes.
+ * <p/>
+ */
+public final class AFPResourceUtil {
+
+    private static final byte TYPE_CODE_BEGIN = (byte)(0xA8 & 0xFF);
+    private static final byte TYPE_CODE_END = (byte)(0xA9 & 0xFF);
+
+    private static final Log LOG = LogFactory.getLog(AFPResourceUtil.class);
+
+    private AFPResourceUtil() {
+        //nop
+    }
+
+    /**
+     * Get the next structured field as identified by the identifier
+     * parameter (this must be a valid MO:DCA structured field).
+     * @param identifier the three byte identifier
+     * @param inputStream the inputStream
+     * @throws IOException if an I/O exception occurred
+     * @return the next structured field or null when there are no more
+     */
+    public static byte[] getNext(byte[] identifier, InputStream inputStream) throws IOException {
+        MODCAParser parser = new MODCAParser(inputStream);
+        while (true) {
+            UnparsedStructuredField field = parser.readNextStructuredField();
+            if (field == null) {
+                return null;
+            }
+            if (field.getSfClassCode() == identifier[0]
+                    && field.getSfTypeCode() == identifier[1]
+                    && field.getSfCategoryCode() == identifier[2]) {
+                return field.getCompleteFieldAsBytes();
+            }
+        }
+    }
+
+    private static String getResourceName(UnparsedStructuredField field)
+            throws UnsupportedEncodingException {
+        //The first 8 bytes of the field data represent the resource name
+        byte[] nameBytes = new byte[8];
+        System.arraycopy(field.getData(), 0, nameBytes, 0, 8);
+        String asciiName;
+        asciiName = new String(nameBytes, AFPConstants.EBCIDIC_ENCODING);
+        return asciiName;
+    }
+
+    /**
+     * Copy a complete resource file to a given {@link OutputStream}.
+     * @param in external resource input
+     * @param out output destination
+     * @throws IOException if an I/O error occurs
+     */
+    public static void copyResourceFile(final InputStream in, OutputStream out)
+                throws IOException {
+        MODCAParser parser = new MODCAParser(in);
+        while (true) {
+            UnparsedStructuredField field = parser.readNextStructuredField();
+            if (field == null) {
+                break;
+            }
+            out.write(MODCAParser.CARRIAGE_CONTROL_CHAR);
+            field.writeTo(out);
+        }
+    }
+
+    /**
+     * Copy a named resource to a given {@link OutputStream}. The MO:DCA fields read from the
+     * {@link InputStream} are scanned for the resource with the given name.
+     * @param name name of structured field
+     * @param in external resource input
+     * @param out output destination
+     * @throws IOException if an I/O error occurs
+     */
+    public static void copyNamedResource(String name,
+            final InputStream in, final OutputStream out) throws IOException {
+        final MODCAParser parser = new MODCAParser(in);
+        Collection resourceNames = new java.util.HashSet();
+
+        //Find matching "Begin" field
+        final UnparsedStructuredField fieldBegin;
+        while (true) {
+            UnparsedStructuredField field = parser.readNextStructuredField();
+            if (field == null) {
+                throw new IOException("Requested resource '" + name
+                        + "' not found. Encountered resource names: " + resourceNames);
+            }
+
+            if (field.getSfTypeCode() != TYPE_CODE_BEGIN) { //0xA8=Begin
+                continue; //Not a "Begin" field
+            }
+            String resourceName = getResourceName(field);
+            resourceNames.add(resourceName);
+            if (resourceName.equals(name)) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Start of requested structured field found:\n"
+                            + field);
+                }
+                fieldBegin = field;
+                break; //Name doesn't match
+            }
+        }
+
+        //Decide whether the resource file has to be wrapped in a resource object
+        boolean wrapInResource;
+        if (fieldBegin.getSfCategoryCode() == Category.PAGE_SEGMENT) {
+            //A naked page segment must be wrapped in a resource object
+            wrapInResource = true;
+        } else if (fieldBegin.getSfCategoryCode() == Category.NAME_RESOURCE) {
+            //A resource object can be copied directly
+            wrapInResource = false;
+        } else {
+            throw new IOException("Cannot handle resource: " + fieldBegin);
+        }
+
+        //Copy structured fields (wrapped or as is)
+        if (wrapInResource) {
+            ResourceObject resourceObject =  new ResourceObject(name) {
+                protected void writeContent(OutputStream os) throws IOException {
+                    copyStructuredFields(name, fieldBegin, parser, out);
+                }
+            };
+            resourceObject.setType(ResourceObject.TYPE_PAGE_SEGMENT);
+            resourceObject.writeToStream(out);
+        } else {
+            copyStructuredFields(name, fieldBegin, parser, out);
+        }
+    }
+
+    private static void copyStructuredFields(String name, UnparsedStructuredField fieldBegin,
+            MODCAParser parser, OutputStream out) throws IOException {
+        boolean inRequestedResource;
+
+        //The "Begin" field first
+        out.write(MODCAParser.CARRIAGE_CONTROL_CHAR);
+        fieldBegin.writeTo(out);
+        UnparsedStructuredField field;
+
+        //Then the rest of the fields until the corresponding "End" field
+        inRequestedResource = true;
+        do {
+            field = parser.readNextStructuredField();
+            if (field == null) {
+                break; //Unexpected EOF
+            }
+
+            if (field.getSfTypeCode() == TYPE_CODE_END) {
+                String resourceName = getResourceName(field);
+                if (resourceName.equals(name)) {
+                    inRequestedResource = false; //Signal end of loop
+                }
+            }
+            out.write(MODCAParser.CARRIAGE_CONTROL_CHAR);
+            field.writeTo(out);
+        } while (inRequestedResource);
+        if (inRequestedResource) {
+            throw new IOException("Ending structured field not found for resource " + name);
+        }
+    }
+
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/StructuredFieldReader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/StructuredFieldReader.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/StructuredFieldReader.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/StructuredFieldReader.java Thu Oct  7 07:41:48 2010
@@ -54,80 +54,27 @@ public class StructuredFieldReader {
     }
 
     /**
-     * Get the next structured field as identified by the identifer
-     * parameter (this must be a valid MO:DCA structured field.
+     * Get the next structured field as identified by the identifier
+     * parameter (this must be a valid MO:DCA structured field).
+     * Note: The returned data does not include the field length and identifier!
      * @param identifier the three byte identifier
      * @throws IOException if an I/O exception occurred
      * @return the next structured field or null when there are no more
      */
     public byte[] getNext(byte[] identifier) throws IOException {
 
-        int bufferPointer = 0;
-        byte[] bufferData = new byte[identifier.length + 2];
-        for (int x = 0; x < identifier.length; x++) {
-            bufferData[x] = 0x00;
-        }
-
-        int c;
-        while ((c = inputStream.read()) > -1) {
-
-            bufferData[bufferPointer] = (byte) c;
-
-            // Check the last characters in the buffer
-            int index = 0;
-            boolean found = true;
-
-            for (int i = identifier.length - 1; i > -1; i--) {
-
-                int p = bufferPointer - index;
-                if (p < 0) {
-                    p = bufferData.length + p;
-                }
-
-                index++;
-
-                if (identifier[i] != bufferData[p]) {
-                    found = false;
-                    break;
-                }
-
-            }
-
-            if (found) {
-
-                byte[] length = new byte[2];
-
-                int a = bufferPointer - identifier.length;
-                if (a < 0) {
-                    a = bufferData.length + a;
-                }
-
-                int b = bufferPointer - identifier.length - 1;
-                if (b < 0) {
-                    b = bufferData.length + b;
-                }
-
-                length[0] = bufferData[b];
-                length[1] = bufferData[a];
-
-                int reclength = ((length[0] & 0xFF) << 8)
-                                + (length[1] & 0xFF) - identifier.length - 2;
-
-                byte[] retval = new byte[reclength];
-
-                inputStream.read(retval, 0, reclength);
-
-                return retval;
-
-            }
-
-            bufferPointer++;
-            if (bufferPointer >= bufferData.length) {
-                bufferPointer = 0;
-            }
+        byte[] bytes = AFPResourceUtil.getNext(identifier, this.inputStream);
 
+        if (bytes != null) {
+            //Users of this class expect the field data without length and identifier
+            int srcPos = 2 + identifier.length;
+            byte[] tmp = new byte[bytes.length - srcPos];
+            System.arraycopy(bytes, srcPos, tmp, 0, tmp.length);
+            bytes = tmp;
         }
 
-        return null;
+        return bytes;
+
     }
+
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java Thu Oct  7 07:41:48 2010
@@ -47,6 +47,7 @@ import org.apache.fop.render.afp.extensi
 import org.apache.fop.render.afp.extensions.AFPIncludeFormMap;
 import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap;
 import org.apache.fop.render.afp.extensions.AFPPageOverlay;
+import org.apache.fop.render.afp.extensions.AFPPageSegmentElement;
 import org.apache.fop.render.afp.extensions.AFPPageSetup;
 import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
 import org.apache.fop.render.intermediate.IFDocumentHandler;
@@ -76,8 +77,8 @@ public class AFPDocumentHandler extends 
     private DataStream dataStream;
 
     /** the map of page segments */
-    private Map/*<String,String>*/pageSegmentMap
-        = new java.util.HashMap/*<String,String>*/();
+    private Map/*<String,PageSegmentDescriptor>*/pageSegmentMap
+        = new java.util.HashMap/*<String,PageSegmentDescriptor>*/();
 
     /** Medium Map referenced on previous page **/
     private String lastMediumMap;
@@ -213,7 +214,6 @@ public class AFPDocumentHandler extends 
                 throws IFException {
         this.location = LOC_ELSEWHERE;
         paintingState.clear();
-        pageSegmentMap.clear();
 
         AffineTransform baseTransform = getBaseTransform();
         paintingState.concatenate(baseTransform);
@@ -288,9 +288,12 @@ public class AFPDocumentHandler extends 
                         null);
                 }
                 if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(element)) {
-                    String name = aps.getName();
-                    String source = aps.getValue();
-                    pageSegmentMap.put(source, name);
+                    AFPPageSegmentElement.AFPPageSegmentSetup apse
+                        = (AFPPageSegmentElement.AFPPageSegmentSetup)aps;
+                    String name = apse.getName();
+                    String source = apse.getValue();
+                    String uri = apse.getResourceSrc();
+                    pageSegmentMap.put(source, new PageSegmentDescriptor(name, uri));
                 } else if (AFPElementMapping.NO_OPERATION.equals(element)) {
                     String content = aps.getContent();
                     if (content != null) {
@@ -392,13 +395,13 @@ public class AFPDocumentHandler extends 
     }
 
     /**
-     * Returns the page segment name for a given URI if it actually represents a page segment.
+     * Returns the page segment descriptor for a given URI if it actually represents a page segment.
      * Otherwise, it just returns null.
      * @param uri the URI that identifies the page segment
-     * @return the page segment name or null if there's no page segment for the given URI
+     * @return the page segment descriptor or null if there's no page segment for the given URI
      */
-    String getPageSegmentNameFor(String uri) {
-        return (String)pageSegmentMap.get(uri);
+    PageSegmentDescriptor getPageSegmentNameFor(String uri) {
+        return (PageSegmentDescriptor)pageSegmentMap.get(uri);
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPPainter.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPPainter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPPainter.java Thu Oct  7 07:41:48 2010
@@ -26,6 +26,8 @@ import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.geom.AffineTransform;
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.Map;
 
 import org.w3c.dom.Document;
@@ -48,6 +50,8 @@ import org.apache.fop.afp.modca.Abstract
 import org.apache.fop.afp.modca.PresentationTextObject;
 import org.apache.fop.afp.ptoca.PtocaBuilder;
 import org.apache.fop.afp.ptoca.PtocaProducer;
+import org.apache.fop.afp.util.DefaultFOPResourceAccessor;
+import org.apache.fop.afp.util.ResourceAccessor;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontTriplet;
@@ -183,14 +187,34 @@ public class AFPPainter extends Abstract
 
     /** {@inheritDoc} */
     public void drawImage(String uri, Rectangle rect) throws IFException {
-        String name = documentHandler.getPageSegmentNameFor(uri);
-        if (name != null) {
+        PageSegmentDescriptor pageSegment = documentHandler.getPageSegmentNameFor(uri);
+
+        if (pageSegment != null) {
             float[] srcPts = {rect.x, rect.y};
             int[] coords = unitConv.mpts2units(srcPts);
             int width = Math.round(unitConv.mpt2units(rect.width));
             int height = Math.round(unitConv.mpt2units(rect.height));
 
-            getDataStream().createIncludePageSegment(name, coords[X], coords[Y], width, height);
+            getDataStream().createIncludePageSegment(pageSegment.getName(),
+                    coords[X], coords[Y], width, height);
+
+            //Do we need to embed an external page segment?
+            if (pageSegment.getURI() != null) {
+                ResourceAccessor accessor = new DefaultFOPResourceAccessor (
+                        documentHandler.getUserAgent(), null, null);
+                try {
+                    URI resourceUri = new URI(pageSegment.getURI());
+                    documentHandler.getResourceManager().createIncludedResourceFromExternal(
+                            pageSegment.getName(), resourceUri, accessor);
+
+                } catch (URISyntaxException urie) {
+                    throw new IFException("Could not handle resource url"
+                            + pageSegment.getURI(), urie);
+                } catch (IOException ioe) {
+                    throw new IFException("Could not handle resource" + pageSegment.getURI(), ioe);
+                }
+            }
+
         } else {
             drawImageUsingURI(uri, rect);
         }

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/PageSegmentDescriptor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/PageSegmentDescriptor.java?rev=1005350&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/PageSegmentDescriptor.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/PageSegmentDescriptor.java Thu Oct  7 07:41:48 2010
@@ -0,0 +1,57 @@
+/*
+ * 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.render.afp;
+
+/**
+ * Class holding information on a page segment.
+ */
+class PageSegmentDescriptor {
+
+    private String name;
+    private String uri;
+
+    /**
+     * Creates a new page segment descriptor.
+     * @param name the page segment name
+     * @param uri the URI identifying the external resource file (may be null if the page segment
+     *                  shall be referenced rather than embedded)
+     */
+    public PageSegmentDescriptor(String name, String uri) {
+        this.name = name;
+        this.uri = uri;
+    }
+
+    /**
+     * Returns the name of the page segment (usually 8 upper case letters).
+     * @return the name of the page segment
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Returns the URI of the external resource containing the page segment.
+     * @return the URI of the external resource (or null if the resource is not to be embedded)
+     */
+    public String getURI() {
+        return this.uri;
+    }
+
+}
\ No newline at end of file

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/PageSegmentDescriptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/PageSegmentDescriptor.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java Thu Oct  7 07:41:48 2010
@@ -103,7 +103,7 @@ public class AFPElementMapping extends E
 
     static class AFPIncludePageSegmentMaker extends ElementMapping.Maker {
         public FONode make(FONode parent) {
-            return new AFPPageSetupElement(parent, INCLUDE_PAGE_SEGMENT);
+            return new AFPPageSegmentElement(parent, INCLUDE_PAGE_SEGMENT);
         }
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java Thu Oct  7 07:41:48 2010
@@ -29,6 +29,7 @@ import org.xml.sax.helpers.DefaultHandle
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.apache.fop.render.afp.extensions.AFPPageSegmentElement.AFPPageSegmentSetup;
 import org.apache.fop.util.ContentHandlerFactory;
 import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener;
 
@@ -96,6 +97,30 @@ public class AFPExtensionHandler extends
                 if (name != null) {
                     returnedObject.setName(name);
                 }
+            } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(localName)) {
+                AFPPageSegmentSetup pageSetupExtn = null;
+
+                pageSetupExtn = new AFPPageSegmentSetup(localName);
+                this.returnedObject = pageSetupExtn;
+
+                String name = lastAttributes.getValue("name");
+                if (name != null) {
+                    returnedObject.setName(name);
+                }
+                String value = lastAttributes.getValue("value");
+                if (value != null && pageSetupExtn != null) {
+                    pageSetupExtn.setValue(value);
+                }
+
+                String resourceSrc = lastAttributes.getValue("resource-file");
+                if (resourceSrc != null && pageSetupExtn != null) {
+                    pageSetupExtn.setResourceSrc(resourceSrc);
+                }
+
+                if (content.length() > 0 && pageSetupExtn != null) {
+                    pageSetupExtn.setContent(content.toString());
+                    content.setLength(0); //Reset text buffer (see characters())
+                }
             } else {
                 AFPPageSetup pageSetupExtn = null;
                 if (AFPElementMapping.INVOKE_MEDIUM_MAP.equals(localName)) {
@@ -117,6 +142,7 @@ public class AFPExtensionHandler extends
                     content.setLength(0); //Reset text buffer (see characters())
                 }
             }
+
         }
     }
 

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPPageSegmentElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPPageSegmentElement.java?rev=1005350&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPPageSegmentElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPPageSegmentElement.java Thu Oct  7 07:41:48 2010
@@ -0,0 +1,149 @@
+/*
+ * 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.render.afp.extensions;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.extensions.ExtensionAttachment;
+
+/**
+ * This class extends the org.apache.fop.extensions.ExtensionObj class. The
+ * object faciliates extraction of elements from formatted objects based on
+ * the static list as defined in the AFPElementMapping implementation.
+ * <p/>
+ */
+public class AFPPageSegmentElement extends AFPPageSetupElement {
+
+    private static final String ATT_RESOURCE_SRC = "resource-file";
+
+    /**
+     * Constructs an AFP object (called by Maker).
+     *
+     * @param parent the parent formatting object
+     * @param name the name of the afp element
+     */
+    public AFPPageSegmentElement(FONode parent, String name) {
+        super(parent, name);
+    }
+
+
+    private AFPPageSegmentSetup getPageSetupAttachment() {
+        return (AFPPageSegmentSetup)getExtensionAttachment();
+    }
+
+
+    /** {@inheritDoc} */
+    public void processNode(String elementName, Locator locator,
+                            Attributes attlist, PropertyList propertyList)
+                                throws FOPException {
+
+        AFPPageSegmentSetup pageSetup = getPageSetupAttachment();
+        super.processNode(elementName, locator, attlist, propertyList);
+
+
+        String attr = attlist.getValue(ATT_RESOURCE_SRC);
+
+        if (attr != null && attr.length() > 0) {
+            pageSetup.setResourceSrc(attr);
+        }
+
+    }
+
+    /** {@inheritDoc} */
+    protected ExtensionAttachment instantiateExtensionAttachment() {
+        return new AFPPageSegmentSetup(getLocalName());
+    }
+
+    /**
+     * This is the pass-through value object for the AFP extension.
+     */
+    public static class AFPPageSegmentSetup extends AFPPageSetup {
+
+        private static final long serialVersionUID = 1L;
+
+        private String resourceSrc;
+
+        /**
+         * Default constructor.
+         *
+         * @param elementName the name of the setup code object, may be null
+         */
+        public AFPPageSegmentSetup(String elementName) {
+            super(elementName);
+        }
+
+        /**
+         * Returns the source URI for the page segment.
+         * @return the source URI
+         */
+        public String getResourceSrc() {
+            return resourceSrc;
+        }
+
+        /**
+         * Sets the source URI for the page segment.
+         * @param resourceSrc the source URI
+         */
+        public void setResourceSrc(String resourceSrc) {
+            this.resourceSrc = resourceSrc.trim();
+        }
+
+
+        /** {@inheritDoc} */
+        public void toSAX(ContentHandler handler) throws SAXException {
+            AttributesImpl atts = new AttributesImpl();
+            if (name != null && name.length() > 0) {
+                atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name);
+            }
+            if (value != null && value.length() > 0) {
+                atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value);
+            }
+
+            if (resourceSrc != null && resourceSrc.length() > 0) {
+                atts.addAttribute(null, ATT_RESOURCE_SRC, ATT_RESOURCE_SRC, "CDATA", resourceSrc);
+            }
+
+            handler.startElement(CATEGORY, elementName, elementName, atts);
+            if (content != null && content.length() > 0) {
+                char[] chars = content.toCharArray();
+                handler.characters(chars, 0, chars.length);
+            }
+            handler.endElement(CATEGORY, elementName, elementName);
+        }
+
+        /** {@inheritDoc} */
+        public String toString() {
+            return "AFPPageSegmentSetup(element-name=" + getElementName()
+                + " name=" + getName()
+                + " value=" + getValue()
+                + " resource=" + getResourceSrc() + ")";
+        }
+
+    }
+
+
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPPageSegmentElement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/extensions/AFPPageSegmentElement.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=1005350&r1=1005349&r2=1005350&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Thu Oct  7 07:41:48 2010
@@ -58,6 +58,9 @@
       documents. Example: the fix of marks layering will be such a case when it's done.
     -->
     <release version="FOP Trunk" date="TBD">
+      <action context="Renderers" dev="JM" type="add" fixes-bug="49379" due-to="Peter Hancock">
+        Added ability to embed an external AFP page segment resource file (AFP output only).
+      </action>
       <action context="Renderers" dev="JM" type="fix" fixes-bug="46360" due-to="Alexis Giotis">
         Fixed a multi-threading issue when rendering SVG.
       </action>



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org