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 me...@apache.org on 2012/07/04 09:04:05 UTC

svn commit: r1357110 - in /xmlgraphics/fop/trunk: src/java/org/apache/fop/afp/util/ test/java/org/apache/fop/afp/

Author: mehdi
Date: Wed Jul  4 07:04:03 2012
New Revision: 1357110

URL: http://svn.apache.org/viewvc?rev=1357110&view=rev
Log:
MODCA end structured field now more conformant with the spec by allowing 0xFFFF match (match any)

Added:
    xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_any_name.afp   (with props)
    xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_name_match.afp   (with props)
    xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_name_mismatch.afp   (with props)
    xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_no_end_name.afp   (with props)
Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java

Modified: 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=1357110&r1=1357109&r2=1357110&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/afp/util/AFPResourceUtil.java Wed Jul  4 07:04:03 2012
@@ -56,8 +56,11 @@ import org.apache.fop.afp.parser.Unparse
  */
 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 byte TYPE_CODE_BEGIN = (byte) (0xA8 & 0xFF);
+
+    private static final byte TYPE_CODE_END = (byte) (0xA9 & 0xFF);
+
+    private static final byte END_FIELD_ANY_NAME = (byte) (0xFF & 0xFF);
 
     private static final Log LOG = LogFactory.getLog(AFPResourceUtil.class);
 
@@ -92,10 +95,13 @@ public final class AFPResourceUtil {
             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;
+
+        byte[] fieldData = field.getData();
+        if (fieldData.length < 8) {
+            throw new IllegalArgumentException("Field data does not contain a resource name");
+        }
+        System.arraycopy(fieldData, 0, nameBytes, 0, 8);
+        return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING);
     }
 
     /**
@@ -128,12 +134,13 @@ public final class AFPResourceUtil {
     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();
+        Collection<String> resourceNames = new java.util.HashSet<String>();
 
         //Find matching "Begin" field
         final UnparsedStructuredField fieldBegin;
         while (true) {
-            UnparsedStructuredField field = parser.readNextStructuredField();
+            final UnparsedStructuredField field = parser.readNextStructuredField();
+
             if (field == null) {
                 throw new IOException("Requested resource '" + name
                         + "' not found. Encountered resource names: " + resourceNames);
@@ -142,8 +149,10 @@ public final class AFPResourceUtil {
             if (field.getSfTypeCode() != TYPE_CODE_BEGIN) { //0xA8=Begin
                 continue; //Not a "Begin" field
             }
-            String resourceName = getResourceName(field);
+            final String resourceName = getResourceName(field);
+
             resourceNames.add(resourceName);
+
             if (resourceName.equals(name)) {
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("Start of requested structured field found:\n"
@@ -170,45 +179,65 @@ public final class AFPResourceUtil {
         if (wrapInResource) {
             ResourceObject resourceObject =  new ResourceObject(name) {
                 protected void writeContent(OutputStream os) throws IOException {
-                    copyStructuredFields(name, fieldBegin, parser, out);
+                    copyNamedStructuredFields(name, fieldBegin, parser, out);
                 }
             };
             resourceObject.setType(ResourceObject.TYPE_PAGE_SEGMENT);
             resourceObject.writeToStream(out);
         } else {
-            copyStructuredFields(name, fieldBegin, parser, out);
+            copyNamedStructuredFields(name, fieldBegin, parser, out);
         }
     }
 
-    private static void copyStructuredFields(String name, UnparsedStructuredField fieldBegin,
+    private static void copyNamedStructuredFields(final 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();
+        UnparsedStructuredField field = fieldBegin;
+        while (true) {
             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
-                }
+                throw new IOException("Ending structured field not found for resource " + name);
             }
             out.write(MODCAParser.CARRIAGE_CONTROL_CHAR);
             field.writeTo(out);
-        } while (inRequestedResource);
-        if (inRequestedResource) {
-            throw new IOException("Ending structured field not found for resource " + name);
+
+            if (isEndOfStructuredField(field, fieldBegin, name)) {
+                break;
+            }
+            field = parser.readNextStructuredField();
         }
     }
 
+    private static boolean isEndOfStructuredField(UnparsedStructuredField field,
+            UnparsedStructuredField fieldBegin, String name) throws UnsupportedEncodingException {
+        return fieldMatchesEndTagType(field)
+                && fieldMatchesBeginCategoryCode(field, fieldBegin)
+                && fieldHasValidName(field, name);
+    }
+
+    private static boolean fieldMatchesEndTagType(UnparsedStructuredField field) {
+        return field.getSfTypeCode() == TYPE_CODE_END;
+    }
+
+    private static boolean fieldMatchesBeginCategoryCode(UnparsedStructuredField field,
+            UnparsedStructuredField fieldBegin) {
+        return fieldBegin.getSfCategoryCode() == field.getSfCategoryCode();
+    }
+
+    /**
+     * The AFP specification states that it is valid for the end structured field to have:
+     *  - No tag name specified, which will cause it to match any existing tag type match.
+     *  - The name has FFFF as its first two bytes
+     *  - The given name matches the previous structured field name
+     */
+    private static boolean fieldHasValidName(UnparsedStructuredField field, String name)
+            throws UnsupportedEncodingException {
+        if (field.getData().length > 0) {
+            if (field.getData()[0] == field.getData()[1]
+                    && field.getData()[0] == END_FIELD_ANY_NAME) {
+                return true;
+            } else {
+                return name.equals(getResourceName(field));
+            }
+        }
+        return true;
+    }
 }

Modified: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java?rev=1357110&r1=1357109&r2=1357110&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java (original)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java Wed Jul  4 07:04:03 2012
@@ -22,23 +22,34 @@ package org.apache.fop.afp;
 import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.Arrays;
 
+import org.junit.Test;
+
 import org.apache.commons.io.IOUtils;
 import org.apache.fop.afp.util.AFPResourceUtil;
 import org.junit.Test;
 
+import static org.junit.Assert.assertTrue;
+
 /**
  * Tests the {@link AFPResourceUtil} class.
  */
 public class AFPResourceUtilTestCase {
 
     private static final String RESOURCE_FILENAME = "expected_resource.afp";
-
     private static final String NAMED_RESOURCE_FILENAME = "expected_named_resource.afp";
 
-    private static final String PSEG = "XFEATHER";
+    private static final String RESOURCE_ANY_NAME = "resource_any_name.afp";
+    private static final String RESOURCE_NAME_MATCH = "resource_name_match.afp";
+    private static final String RESOURCE_NAME_MISMATCH = "resource_name_mismatch.afp";
+    private static final String RESOURCE_NO_END_NAME = "resource_no_end_name.afp";
+
+    private static final String PSEG_A = "XFEATHER";
+    private static final String PSEG_B = "S1CODEQR";
 
     /**
      * Tests copyResourceFile()
@@ -46,57 +57,105 @@ public class AFPResourceUtilTestCase {
      */
     @Test
     public void testCopyResourceFile() throws Exception {
+        compareResources(new ResourceCopier() {
+            public void copy(InputStream in, OutputStream out) throws IOException {
+                AFPResourceUtil.copyResourceFile(in, out);
+            }
+        }, RESOURCE_FILENAME, RESOURCE_FILENAME);
+    }
 
-        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    /**
+     * Tests copyNamedResource()
+     * @throws Exception -
+     */
+    @Test
+    public void testCopyNamedResource() throws Exception {
+        compareResources(new ResourceCopier() {
+            public void copy(InputStream in, OutputStream out) throws IOException {
+                AFPResourceUtil.copyNamedResource(PSEG_A, in, out);
+            }
+        }, RESOURCE_FILENAME, NAMED_RESOURCE_FILENAME);
+    }
 
-        InputStream in = null;
+    private void compareResources(ResourceCopier copyResource, String resourceA, String resourceB)
+            throws IOException {
+        ByteArrayOutputStream baos = copyResource(resourceA, copyResource);
+        byte[] expectedBytes = resourceAsByteArray(resourceB);
+        assertTrue(Arrays.equals(expectedBytes, baos.toByteArray()));
+    }
 
+    private ByteArrayOutputStream copyResource(String resource, ResourceCopier resourceCopier)
+            throws IOException {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        InputStream in = null;
         try {
-            in = getClass().getResourceAsStream(RESOURCE_FILENAME);
-            AFPResourceUtil.copyResourceFile(in, baos);
+            in = getClass().getResourceAsStream(resource);
+            resourceCopier.copy(in, baos);
         } finally {
             in.close();
         }
+        return baos;
+    }
 
+    private byte[] resourceAsByteArray(String resource) throws IOException {
+        InputStream in = null;
         byte[] expectedBytes = null;
-
         try {
-            in = getClass().getResourceAsStream(RESOURCE_FILENAME);
+            in = getClass().getResourceAsStream(resource);
             expectedBytes = IOUtils.toByteArray(in);
         } finally {
             in.close();
         }
-
-        assertTrue(Arrays.equals(expectedBytes, baos.toByteArray()));
-
+        return expectedBytes;
     }
 
     /**
-     * Tests copyNamedResource()
+     * Tests the validity of a closing structured field having an FF FF name which
+     * allows it to match any existing matching starting field
      * @throws Exception -
      */
     @Test
-    public void testCopyNamedResource() throws Exception {
-        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    public void testResourceAnyName() throws Exception {
+        testResource(RESOURCE_ANY_NAME, PSEG_B);
+    }
 
-        InputStream in = null;
+    /**
+     * Tests a matching end structured field name
+     * @throws Exception -
+     */
+    @Test
+    public void testResourceNameMatch() throws Exception {
+        testResource(RESOURCE_NAME_MATCH, PSEG_B);
+    }
 
-        try {
-            in = getClass().getResourceAsStream(RESOURCE_FILENAME);
-            AFPResourceUtil.copyNamedResource(PSEG, in, baos);
-        } finally {
-            in.close();
-        }
+    /**
+     * Tests to see whether a matching structured field pair with mismatching
+     * names fails.
+     * @throws Exception -
+     */
+    @Test(expected=Exception.class)
+    public void testResourceNameMismatch() throws Exception {
+        testResource(RESOURCE_NAME_MISMATCH, PSEG_B);
+    }
 
-        byte[] expectedBytes = null;
+    /**
+     * Tests a matching structured end field with no name
+     * @throws Exception -
+     */
+    @Test
+    public void testResourceNoEndName() throws Exception {
+        testResource(RESOURCE_NO_END_NAME, PSEG_B);
+    }
 
-        try {
-            in = getClass().getResourceAsStream(NAMED_RESOURCE_FILENAME);
-            expectedBytes = IOUtils.toByteArray(in);
-        } finally {
-            in.close();
-        }
+    private void testResource(String resource, final String pseg) throws Exception {
+        copyResource(resource, new ResourceCopier() {
+            public void copy(InputStream in, OutputStream out) throws IOException {
+                AFPResourceUtil.copyNamedResource(pseg, in, out);
+            }
+        });
+    }
 
-        assertTrue(Arrays.equals(expectedBytes, baos.toByteArray()));
+    private interface ResourceCopier {
+        public void copy(InputStream in, OutputStream out) throws IOException;
     }
 }

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_any_name.afp
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_any_name.afp?rev=1357110&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_any_name.afp
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_name_match.afp
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_name_match.afp?rev=1357110&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_name_match.afp
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_name_mismatch.afp
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_name_mismatch.afp?rev=1357110&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_name_mismatch.afp
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_no_end_name.afp
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_no_end_name.afp?rev=1357110&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop/trunk/test/java/org/apache/fop/afp/resource_no_end_name.afp
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream



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


Re: svn commit: r1357110 - in /xmlgraphics/fop/trunk: src/java/org/apache/fop/afp/util/ test/java/org/apache/fop/afp/

Posted by Vincent Hennebert <vh...@gmail.com>.
Mehdi,

When applying a patch submitted by a contributor, you must put his name
in the log message. Also, it’s good practice to refer to the Bugzilla
number.

And also add an entry to the status.xml file.

Thanks,
Vincent

On 04/07/12 08:04, mehdi wrote:
> Author: mehdi
> Date: Wed Jul  4 07:04:03 2012
> New Revision: 1357110
> 
> URL: http://svn.apache.org/viewvc?rev=1357110&view=rev
> Log:
> MODCA end structured field now more conformant with the spec by allowing 0xFFFF match (match any)
<snip/>