Index: src/java/org/apache/fop/render/afp/extensions/AFPElement.java
===================================================================
--- src/java/org/apache/fop/render/afp/extensions/AFPElement.java	(revision 558765)
+++ src/java/org/apache/fop/render/afp/extensions/AFPElement.java	(working copy)
@@ -18,11 +18,11 @@
 /* $Id$ */
 
 package org.apache.fop.render.afp.extensions;
+
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.ValidationException;
-import org.apache.fop.fo.XMLObj;
 
 /**
  * This class extends the org.apache.fop.extensions.ExtensionObj class. The
@@ -43,16 +43,6 @@
     }
 
     /** {@inheritDoc} */
-    public String getNamespaceURI() {
-        return AFPElementMapping.NAMESPACE;
-    }
-
-    /** {@inheritDoc} */
-    public String getNormalNamespacePrefix() {
-        return "afp";
-    }
-
-    /** {@inheritDoc} */
     protected void startOfNode() throws FOPException {
         super.startOfNode();
         //if (!AFPElementMapping.NAMESPACE.equals(parent.getNamespaceURI())
Index: src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
===================================================================
--- src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java	(revision 558765)
+++ src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java	(working copy)
@@ -22,12 +22,18 @@
 import java.io.Serializable;
 
 import org.apache.fop.fo.extensions.ExtensionAttachment;
+import org.apache.fop.util.XMLizable;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
 
 /**
  * This is the pass-through value object for the PostScript extension.
  */
-public class AFPPageSetup implements ExtensionAttachment, Serializable {
+public class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizable  {
 
+    private static final long serialVersionUID = 7190606822558332901L;
+
     /** The category URI for this extension attachment. */
     public static final String CATEGORY = "apache:fop:extensions:afp";
 
@@ -37,12 +43,15 @@
 
     private String value;
 
+    private String content;
+
     /**
      * Default constructor.
-     * @param name the name of the setup code object, may be null
+     * 
+     * @param elementName the name of the setup code object, may be null
      */
-    public AFPPageSetup(String name) {
-        this.elementName = name;
+    public AFPPageSetup(String elementName) {
+        this.elementName = elementName;
     }
 
     /** @return the name */
@@ -77,15 +86,49 @@
     public void setValue(String source) {
         this.value = source;
     }
-
+    
     /** {@inheritDoc} */
     public String getCategory() {
         return CATEGORY;
     }
 
+    /**
+     * @return the data
+     */
+    public String getContent() {
+        return content;
+    }
+
+    /**
+     * Sets the data
+     * @param content The byte data to set.
+     */
+    public void setContent(String content) {
+        this.content = content;
+    }
+
     /** {@inheritDoc} */
     public String toString() {
         return "AFPPageSetup(element-name=" + getElementName() + " name=" + getName() + ")";
     }
 
-}
+    private static final String ATT_NAME = "name";
+    private static final String ATT_VALUE = "value";
+
+    /** {@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);
+        }
+        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);
+    }
+}
\ No newline at end of file
Index: src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
===================================================================
--- src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java	(revision 558765)
+++ src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java	(working copy)
@@ -45,6 +45,9 @@
 
     public static final String INCLUDE_PAGE_SEGMENT = "include-page-segment";
 
+    /** NOP */
+    public static final String NO_OPERATION = "no-operation";
+
     /**
      * The namespace used for AFP extensions
      */
@@ -79,6 +82,9 @@
             foObjs.put(
                 INCLUDE_PAGE_OVERLAY,
                 new AFPIncludePageOverlayMaker());
+            foObjs.put(
+                NO_OPERATION,
+                new AFPNoOperationMaker());
         }
 
     }
@@ -107,4 +113,9 @@
         }
     }
 
+    static class AFPNoOperationMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new AFPElement(parent, NO_OPERATION);
+        }
+    }
 }
Index: src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java
===================================================================
--- src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java	(revision 558765)
+++ src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java	(working copy)
@@ -33,10 +33,13 @@
  */
 public abstract class AbstractAFPExtensionObject extends FONode {
 
-    private AFPPageSetup setupCode = null;
-
-    private String _name = null;
+    /**
+     * AFP setup code
+     */
+    private AFPPageSetup setupCode;
     
+    private String name;
+            
     /**
      * @see org.apache.fop.fo.FONode#FONode(FONode)
      * @param parent the parent formatting object
@@ -44,14 +47,11 @@
      */
     public AbstractAFPExtensionObject(FONode parent, String name) {
         super(parent);
-        _name = name;
-        setupCode = new AFPPageSetup(name);
+        this.name = name;
+        this.setupCode = new AFPPageSetup(name);
     }
 
-    /**
-     * {@inheritDoc} String, String)
-     * here, blocks XSL FO's from having non-FO parents.
-     */
+    /** {@inheritDoc} */
     protected void validateChildNode(Locator loc, String nsURI, String localName)
                 throws ValidationException {
         if (FO_URI.equals(nsURI)) {
@@ -60,8 +60,9 @@
     }
 
     /** {@inheritDoc} */
-    protected void addCharacters(char[] data, int start, int length,
+    protected void addCharacters(char[] data, int start, int end,
                                  PropertyList pList, Locator locator) {
+        setupCode.setContent(new String(data, start, end - start));       
     }
 
     /** {@inheritDoc} */
@@ -69,7 +70,7 @@
         return AFPElementMapping.NAMESPACE;
     }
 
-    /**{@inheritDoc} */
+    /** {@inheritDoc} */
     public String getNormalNamespacePrefix() {
         return AFPElementMapping.NAMESPACE_PREFIX;
     }
@@ -91,8 +92,7 @@
             } else {
                 throw new FOPException(elementName + " must have a src attribute.");
             }
-        }
-        if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) {
+        } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) {
             name = attlist.getValue("value");
             if (name != null && name.length() > 0) {
                 setupCode.setValue(name);
@@ -114,8 +114,6 @@
 
     /** {@inheritDoc} */
     public String getLocalName() {
-        return _name;
+        return name;
     }
-
 }
-
Index: src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java
===================================================================
--- src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java	(revision 555659)
+++ src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java	(working copy)
@@ -357,6 +357,19 @@
     }
 
     /**
+     * Creates a NoOperation on the page.
+     *
+     * @param data
+     *            the byte data
+     */
+    public void createNoOperation(String content) {
+
+        NoOperation noOp = new NoOperation(content);
+        _objects.add(noOp);
+
+    }
+
+    /**
      * Creates an IncludePageSegment on the current page.
      *
      * @param name
Index: src/java/org/apache/fop/render/afp/modca/AFPDataStream.java
===================================================================
--- src/java/org/apache/fop/render/afp/modca/AFPDataStream.java	(revision 555659)
+++ src/java/org/apache/fop/render/afp/modca/AFPDataStream.java	(working copy)
@@ -571,6 +571,15 @@
     }
 
     /**
+     * Creates a NoOperation item
+     * 
+     * @param data byte data
+     */
+    public void createNoOperation(String content) {
+        _currentPage.createNoOperation(content);
+    }
+
+    /**
      * Start a new page group. When processing has finished on the current page
      * group the {@link #endPageGroup()}method must be invoked to mark the page
      * group ending.
Index: src/java/org/apache/fop/render/afp/modca/NoOperation.java
===================================================================
--- src/java/org/apache/fop/render/afp/modca/NoOperation.java	(revision 0)
+++ src/java/org/apache/fop/render/afp/modca/NoOperation.java	(revision 0)
@@ -0,0 +1,99 @@
+/*
+ * 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.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.render.afp.tools.BinaryUtils;
+
+/**
+ * The No Operation structured field may be used to carry comments
+ * or any other type of unarchitected data. Although not recommended,
+ * it may also be used to carry semantic data in private or exchange data
+ * streams. However, because receivers of interchange data streams should
+ * ignore the content of No Operation structured fields and because
+ * receiver-generator products are not required to propagate
+ * No Operation structured fields, no semantics should be attached to
+ * the data carried by the No Operation structured field in interchange
+ */
+public class NoOperation extends AbstractAFPObject {
+    
+    /** Up to 32759 bytes of data with no architectural definition */
+    private static final int MAX_DATA_LEN = 32759;
+    
+    /**
+     * Byte representation of the comment 
+     */
+    private String content;
+
+    /**
+     * Construct a tag logical element with the name and value specified.
+     * 
+     * @param content the content to record
+     */
+    public NoOperation(String content) {
+        this.content = content;
+    }
+    
+    /**
+     * Accessor method to obtain the byte array AFP datastream for the
+     * NoOperation.
+     * 
+     * @param os The outputsteam stream
+     * @throws java.io.IOException if an I/O exception occurs during processing
+     */
+    public void writeDataStream(OutputStream os) throws IOException {
+        byte[] contentData = content.getBytes();
+        int contentLen = contentData.length;
+        
+        // packet maximum of 32759 bytes
+        if (contentLen > MAX_DATA_LEN) {
+            contentLen = MAX_DATA_LEN;
+        }
+        
+        byte[] data = new byte[9 + contentLen];
+        
+        data[0] = 0x5A;
+        
+        // Set the total record length
+        byte[] rl1 = BinaryUtils.convert(8 + contentLen, 2);
+        
+        //Ignore first byte
+        data[1] = rl1[0];
+        data[2] = rl1[1];
+
+        // Structured field ID for a TLE
+        data[3] = (byte) 0xD3;
+        data[4] = (byte) 0xEE;
+        data[5] = (byte) 0xEE;
+
+        data[6] = 0x00; // Reserved
+        data[7] = 0x00; // Reserved
+        data[8] = 0x00; // Reserved
+
+        int pos = 9;
+        for (int i = 0; i < contentLen; i++) {
+            data[pos++] = contentData[i];
+        }
+        os.write(data);
+    }
+
+}
Index: src/java/org/apache/fop/render/afp/AFPRenderer.java
===================================================================
--- src/java/org/apache/fop/render/afp/AFPRenderer.java	(revision 555659)
+++ src/java/org/apache/fop/render/afp/AFPRenderer.java	(working copy)
@@ -256,10 +256,10 @@
         this.fontInfo = inFontInfo;
         int num = 1;
         if (this.fontList != null && this.fontList.size() > 0) {
-            for (Iterator it = this.fontList.iterator(); it.hasNext(); ) {
+            for (Iterator it = this.fontList.iterator(); it.hasNext();) {
                 AFPFontInfo afi = (AFPFontInfo)it.next();
                 AFPFont bf = (AFPFont)afi.getAFPFont();
-                for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext(); ) {
+                for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) {
                     FontTriplet ft = (FontTriplet)it2.next();
                     this.fontInfo.addFontProperties("F" + num, ft.getName()
                                                     , ft.getStyle(), ft.getWeight());
@@ -271,21 +271,24 @@
             log.warn("No AFP fonts configured - using default setup");
         }
         if (this.fontInfo.fontLookup("sans-serif", "normal", 400) == null) {
-            CharacterSet cs  = new FopCharacterSet("T1V10500", "Cp500", "CZH200  ", 1, new Helvetica());
+            CharacterSet cs  = new FopCharacterSet("T1V10500", "Cp500", "CZH200  ",
+                    1, new Helvetica());
             AFPFont bf = new OutlineFont("Helvetica", cs);
             this.fontInfo.addFontProperties("F" + num, "sans-serif", "normal", 400);
             this.fontInfo.addMetrics("F" + num, bf);
             num++;
         }
         if (this.fontInfo.fontLookup("serif", "normal", 400) == null) {
-            CharacterSet cs  = new FopCharacterSet("T1V10500", "Cp500", "CZN200  ", 1, new TimesRoman());
+            CharacterSet cs  = new FopCharacterSet("T1V10500", "Cp500", "CZN200  ",
+                    1, new TimesRoman());
             AFPFont bf = new OutlineFont("Helvetica", cs);
             this.fontInfo.addFontProperties("F" + num, "serif", "normal", 400);
             this.fontInfo.addMetrics("F" + num, bf);
             num++;
         }
         if (this.fontInfo.fontLookup("monospace", "normal", 400) == null) {
-            CharacterSet cs  = new FopCharacterSet("T1V10500", "Cp500", "CZ4200  ", 1, new Courier());
+            CharacterSet cs  = new FopCharacterSet("T1V10500", "Cp500", "CZ4200  ",
+                    1, new Courier());
             AFPFont bf = new OutlineFont("Helvetica", cs);
             this.fontInfo.addFontProperties("F" + num, "monospace", "normal", 400);
             this.fontInfo.addMetrics("F" + num, bf);
@@ -293,7 +296,8 @@
         }
         if (this.fontInfo.fontLookup("any", "normal", 400) == null) {
             FontTriplet ft = this.fontInfo.fontLookup("sans-serif", "normal", 400);
-            this.fontInfo.addFontProperties(this.fontInfo.getInternalFontKey(ft), "any", "normal", 400);
+            this.fontInfo.addFontProperties(
+                    this.fontInfo.getInternalFontKey(ft), "any", "normal", 400);
         }
     }
 
@@ -340,7 +344,7 @@
      *
      * @see org.apache.fop.render.Renderer#preparePage(PageViewport)
      */
-    public void preparePage(PageViewport page) {
+    public void preparePage(PageViewport pageViewport) {
         // initializeRootExtensions(page);
 
         _currentFontFamily = "";
@@ -349,7 +353,7 @@
         _currentPageFonts.clear();
         _lineCache = new HashSet();
 
-        Rectangle2D bounds = page.getViewArea();
+        Rectangle2D bounds = pageViewport.getViewArea();
 
         _pageWidth = mpts2units(bounds.getWidth());
         _pageHeight = mpts2units(bounds.getHeight());
@@ -358,12 +362,12 @@
 
         _afpDataStream.startPage(_pageWidth, _pageHeight, 0);
 
-        renderPageObjectExtensions(page);
+        renderPageObjectExtensions(pageViewport);
 
         if (_pages == null) {
             _pages = new HashMap();
         }
-        _pages.put(page, _afpDataStream.savePage());
+        _pages.put(pageViewport, _afpDataStream.savePage());
 
     }
 
@@ -548,7 +552,7 @@
     /**
      * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
      */
-    public void renderPage(PageViewport page) {
+    public void renderPage(PageViewport pageViewport) {
 
         // initializeRootExtensions(page);
 
@@ -558,27 +562,27 @@
         _currentPageFonts.clear();
         _lineCache = new HashSet();
 
-        Rectangle2D bounds = page.getViewArea();
+        Rectangle2D bounds = pageViewport.getViewArea();
 
         _pageWidth = mpts2units(bounds.getWidth());
         _pageHeight = mpts2units(bounds.getHeight());
 
-        if (_pages != null && _pages.containsKey(page)) {
+        if (_pages != null && _pages.containsKey(pageViewport)) {
 
-            _afpDataStream.restorePage((PageObject)_pages.remove(page));
+            _afpDataStream.restorePage((PageObject)_pages.remove(pageViewport));
 
         } else {
             // renderPageGroupExtensions(page);
 
             _afpDataStream.startPage(_pageWidth, _pageHeight, 0);
 
-            renderPageObjectExtensions(page);
+            renderPageObjectExtensions(pageViewport);
 
         }
 
         pushViewPortPos(new ViewPortPos());
 
-        renderPageAreas(page.getPage());
+        renderPageAreas(pageViewport.getPage());
 
         Iterator i = _currentPageFonts.values().iterator();
         while (i.hasNext()) {
@@ -1365,40 +1369,50 @@
      * Method to render the page extension.
      * <p>
      *
-     * @param page
+     * @param pageViewport
      *            the page object
      */
-    private void renderPageObjectExtensions(PageViewport page) {
+    private void renderPageObjectExtensions(PageViewport pageViewport) {
 
         _pageSegmentsMap = null;
-        if (page.getExtensionAttachments() != null
-            && page.getExtensionAttachments().size() > 0) {
+        if (pageViewport.getExtensionAttachments() != null
+            && pageViewport.getExtensionAttachments().size() > 0) {
             //Extract all AFPPageSetup instances from the attachment list on the s-p-m
-            Iterator i = page.getExtensionAttachments().iterator();
+            Iterator i = pageViewport.getExtensionAttachments().iterator();
             while (i.hasNext()) {
                 ExtensionAttachment attachment = (ExtensionAttachment)i.next();
                 if (AFPPageSetup.CATEGORY.equals(attachment.getCategory())) {
-                    AFPPageSetup aps = (AFPPageSetup)attachment;
-                    String element = aps.getElementName();
-                    if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) { 
-                        String overlay = aps.getName();
-                        if (overlay != null) {
-                            _afpDataStream.createIncludePageOverlay(overlay);
+                    if (attachment instanceof AFPPageSetup) {
+                        AFPPageSetup aps = (AFPPageSetup)attachment;
+                        if (log.isDebugEnabled()) {
+                            log.debug(aps);
                         }
-                    } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(element)) { 
-                        String name = aps.getName();
-                        String source = aps.getValue();
-                        if (_pageSegmentsMap == null) {
-                            _pageSegmentsMap = new HashMap();
+                        String element = aps.getElementName();
+                        if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) { 
+                            String overlay = aps.getName();
+                            if (overlay != null) {
+                                _afpDataStream.createIncludePageOverlay(overlay);
+                            }
+                        } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(element)) { 
+                            String name = aps.getName();
+                            String source = aps.getValue();
+                            if (_pageSegmentsMap == null) {
+                                _pageSegmentsMap = new HashMap();
+                            }
+                            _pageSegmentsMap.put(source, name);
+                        } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(element)) { 
+                            String name = aps.getName();
+                            String value = aps.getValue();
+                            if (_pageSegmentsMap == null) {
+                                _pageSegmentsMap = new HashMap();
+                            }
+                            _afpDataStream.createTagLogicalElement(name, value);
+                        } else if (AFPElementMapping.NO_OPERATION.equals(element)) { 
+                            String content = aps.getContent();
+                            if (content != null) {
+                                _afpDataStream.createNoOperation(content);
+                            }
                         }
-                        _pageSegmentsMap.put(source, name);
-                    } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(element)) { 
-                        String name = aps.getName();
-                        String value = aps.getValue();
-                        if (_pageSegmentsMap == null) {
-                            _pageSegmentsMap = new HashMap();
-                        }
-                        _afpDataStream.createTagLogicalElement(name, value);
                     }
                 }
             }
Index: src/documentation/content/xdocs/trunk/output.xml
===================================================================
--- src/documentation/content/xdocs/trunk/output.xml	(revision 555659)
+++ src/documentation/content/xdocs/trunk/output.xml	(working copy)
@@ -590,8 +590,7 @@
       </section>
       <section id="afp-tag-logical-element">
         <title>Tag Logical Element Extension</title>
-        <p>The tag-logical-element extension element allows to injects TLEs into the AFP output stream. Example: 
-          Example:</p>
+        <p>The tag-logical-element extension element allows to injects TLEs into the AFP output stream. Example:</p>
       <source><![CDATA[
     <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
      xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp">
@@ -607,6 +606,24 @@
         The name and value attributes are mandatory.
         </p>
       </section>
+      <section id="afp-no-operation">
+        <title>No Operation Extension</title>
+        <p>The no-operation extension provides the ability to carry up to 32K of comments or any other type
+        of unarchitected data into the AFP output stream. Example:</p>
+      <source><![CDATA[
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+     xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="simple">
+          <afp:no-operation name="My NOP">insert up to 32k of character data here!</afp:no-operation>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+]]></source>
+        <p>The no-operation extension element can only occur within a simple-page-master.
+        Multiple no-operation extension elements within a simple-page-master are allowed.
+        The name attribute is mandatory.
+        </p>
+      </section>
     </section>
   </section>
 <section id="rtf">
