[dna-commits] DNA SVN: r598 - in trunk: dna-graph/src/main/java/org/jboss/dna/graph and 29 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Wed Oct 29 14:23:01 EDT 2008


Author: rhauch
Date: 2008-10-29 14:23:01 -0400 (Wed, 29 Oct 2008)
New Revision: 598

Added:
   trunk/extensions/dna-sequencer-xml/
   trunk/extensions/dna-sequencer-xml/.classpath
   trunk/extensions/dna-sequencer-xml/.project
   trunk/extensions/dna-sequencer-xml/pom.xml
   trunk/extensions/dna-sequencer-xml/src/
   trunk/extensions/dna-sequencer-xml/src/main/
   trunk/extensions/dna-sequencer-xml/src/main/java/
   trunk/extensions/dna-sequencer-xml/src/main/java/org/
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaDtdLexicon.java
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaXmlLexicon.java
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerI18n.java
   trunk/extensions/dna-sequencer-xml/src/main/resources/
   trunk/extensions/dna-sequencer-xml/src/main/resources/org/
   trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/
   trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/
   trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/
   trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/
   trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/XmlSequencerI18n.properties
   trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/xml.cnd
   trunk/extensions/dna-sequencer-xml/src/test/
   trunk/extensions/dna-sequencer-xml/src/test/java/
   trunk/extensions/dna-sequencer-xml/src/test/java/org/
   trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/
   trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/
   trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/
   trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/
   trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java
   trunk/extensions/dna-sequencer-xml/src/test/resources/
   trunk/extensions/dna-sequencer-xml/src/test/resources/CurrencyFormatterExample.mxml
   trunk/extensions/dna-sequencer-xml/src/test/resources/Descriptor.1.0.xsd
   trunk/extensions/dna-sequencer-xml/src/test/resources/jackrabbitInMemoryTestRepositoryConfig.xml
   trunk/extensions/dna-sequencer-xml/src/test/resources/log4j.properties
   trunk/extensions/dna-sequencer-xml/src/test/resources/master.xml
   trunk/extensions/dna-sequencer-xml/src/test/resources/plugin.xml
Removed:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/DnaDtdLexicon.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/DnaXmlLexicon.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlSequencer.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlSequencerTest.java
   trunk/dna-graph/src/test/resources/CurrencyFormatterExample.mxml
   trunk/dna-graph/src/test/resources/Descriptor.1.0.xsd
   trunk/dna-graph/src/test/resources/jackrabbitInMemoryTestRepositoryConfig.xml
   trunk/dna-graph/src/test/resources/master.xml
   trunk/dna-graph/src/test/resources/plugin.xml
Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java
   trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java
   trunk/pom.xml
Log:
DNA-243 - Change (and move) XML Sequencer to use more general-purpose XML importer
http://jira.jboss.com/jira/browse/DNA-243

Moved the XmlSequencer into a separate extension project.

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -75,13 +75,6 @@
     public static I18n actualNewLocationMustHaveSameParentAsOldLocation;
     public static I18n actualNewLocationMustHaveSameNameAsRequest;
 
-    // XML Sequencer
-    public static I18n errorSequencingXmlDocument;
-    public static I18n fatalErrorSequencingXmlDocument;
-    public static I18n sequencingXmlDocument;
-    public static I18n canceledSequencingXmlDocument;
-    public static I18n warningSequencingXmlDocument;
-
     public static I18n errorImportingContent;
     public static I18n unableToFindRepositorySourceWithName;
 

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/DnaDtdLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/DnaDtdLexicon.java	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/DnaDtdLexicon.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,42 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.xml;
-
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
-
-/**
- * @author Randall Hauch
- */
-public class DnaDtdLexicon {
-
-    public static class Namespace {
-        public static final String URI = "http://www.jboss.org/dna/dtd/1.0";
-        public static final String PREFIX = "dnadtd";
-    }
-
-    public static final Name NAME = new BasicName(Namespace.URI, "name");
-    public static final Name PUBLIC_ID = new BasicName(Namespace.URI, "publicId");
-    public static final Name SYSTEM_ID = new BasicName(Namespace.URI, "systemId");
-    public static final Name VALUE = new BasicName(Namespace.URI, "value");
-    public static final Name ENTITY = new BasicName(Namespace.URI, "entity");
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/DnaXmlLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/DnaXmlLexicon.java	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/DnaXmlLexicon.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,46 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.xml;
-
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
-
-/**
- * @author Randall Hauch
- */
-public class DnaXmlLexicon {
-
-    public static class Namespace {
-        public static final String URI = "http://www.jboss.org/dna/xml/1.0";
-        public static final String PREFIX = "dnaxml";
-    }
-
-    public static final Name CDATA = new BasicName(Namespace.URI, "cData");
-    public static final Name CDATA_CONTENT = new BasicName(Namespace.URI, "cDataContent");
-    public static final Name COMMENT = new BasicName(Namespace.URI, "comment");
-    public static final Name COMMENT_CONTENT = new BasicName(Namespace.URI, "commentContent");
-    public static final Name DOCUMENT = new BasicName(Namespace.URI, "document");
-    public static final Name ELEMENT_CONTENT = new BasicName(Namespace.URI, "elementContent");
-    public static final Name PROCESSING_INSTRUCTION = new BasicName(Namespace.URI, "processingInstruction");
-    public static final Name PROCESSING_INSTRUCTION_CONTENT = new BasicName(Namespace.URI, "processingInstructionContent");
-    public static final Name TARGET = new BasicName(Namespace.URI, "target");
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlSequencer.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlSequencer.java	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlSequencer.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,703 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.xml;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import org.jboss.dna.common.monitor.ProgressMonitor;
-import org.jboss.dna.common.util.StringUtil;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.JcrLexicon;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXNotRecognizedException;
-import org.xml.sax.SAXNotSupportedException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.ext.DefaultHandler2;
-import org.xml.sax.helpers.XMLReaderFactory;
-
-/**
- * @author John Verhaeg
- */
-public class XmlSequencer implements StreamSequencer {
-
-    private static final String DEFAULT_PRIMARY_TYPE = "nt:unstructured";
-    private static final String DECL_HANDLER_FEATURE = "http://xml.org/sax/properties/declaration-handler";
-    private static final String ENTITY_RESOLVER_2_FEATURE = "http://xml.org/sax/features/use-entity-resolver2";
-    private static final String LEXICAL_HANDLER_FEATURE = "http://xml.org/sax/properties/lexical-handler";
-    private static final String RESOLVE_DTD_URIS_FEATURE = "http://xml.org/sax/features/resolve-dtd-uris";
-    private static final String LOAD_EXTERNAL_DTDS_FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.StreamSequencer#sequence(InputStream, SequencerOutput, SequencerContext,
-     *      ProgressMonitor)
-     */
-    public void sequence( InputStream stream,
-                          SequencerOutput output,
-                          SequencerContext context,
-                          ProgressMonitor monitor ) {
-        monitor.beginTask(100.0, GraphI18n.sequencingXmlDocument);
-        XMLReader reader;
-        try {
-            reader = XMLReaderFactory.createXMLReader();
-            Handler handler = new Handler(output, context, monitor);
-            reader.setContentHandler(handler);
-            reader.setErrorHandler(handler);
-            // Ensure handler acting as entity resolver 2
-            reader.setProperty(DECL_HANDLER_FEATURE, handler);
-            // Ensure handler acting as lexical handler
-            reader.setProperty(LEXICAL_HANDLER_FEATURE, handler);
-            // Ensure handler acting as entity resolver 2
-            setFeature(reader, ENTITY_RESOLVER_2_FEATURE, true);
-            // Prevent loading of external DTDs
-            setFeature(reader, LOAD_EXTERNAL_DTDS_FEATURE, false);
-            // Prevent the resolving of DTD entities into fully-qualified URIS
-            setFeature(reader, RESOLVE_DTD_URIS_FEATURE, false);
-            // Parse XML document
-            reader.parse(new InputSource(stream));
-        } catch (Exception error) {
-            context.getLogger(getClass()).error(error, GraphI18n.fatalErrorSequencingXmlDocument, error);
-            monitor.getProblems().addError(error, GraphI18n.fatalErrorSequencingXmlDocument, error);
-        } finally {
-            monitor.done();
-        }
-    }
-
-    /**
-     * Sets the reader's named feature to the supplied value, only if the feature is not already set to that value. This method
-     * does nothing if the feature is not known to the reader.
-     * 
-     * @param reader the reader; may not be null
-     * @param featureName the name of the feature; may not be null
-     * @param value the value for the feature
-     */
-    private void setFeature( XMLReader reader,
-                             String featureName,
-                             boolean value ) {
-        try {
-            if (reader.getFeature(featureName) != value) {
-                reader.setFeature(featureName, value);
-            }
-        } catch (SAXNotRecognizedException meansFeatureNotRecognized) {
-        } catch (SAXNotSupportedException meansFeatureNotSupported) {
-        }
-    }
-
-    private final class Handler extends DefaultHandler2 {
-
-        private final SequencerOutput output;
-        private final SequencerContext context;
-        private final ProgressMonitor monitor;
-
-        private double progress;
-
-        private Path path; // The DNA path of the node representing the current XML element
-
-        // Cached instances of the name factory and commonly referenced names
-        private final NameFactory nameFactory;
-        private Name defaultPrimaryType;
-
-        // Recursive map used to track the number of occurrences of names for elements under a particular path
-        private Map<Name, List<IndexedName>> nameToIndexedNamesMap = new HashMap<Name, List<IndexedName>>();
-
-        // The stack of recursive maps being processed, with the head entry being the map for the current path
-        private final LinkedList<Map<Name, List<IndexedName>>> nameToIndexedNamesMapStack = new LinkedList<Map<Name, List<IndexedName>>>();
-
-        // The stack of XML namespace in scope, with the head entry being namespace of the closest ancestor element declaring a
-        // namespace.
-        private final LinkedList<String> nsStack = new LinkedList<String>();
-
-        // Builder used to concatenate concurrent lines of CDATA into a single value.
-        private StringBuilder cDataBuilder;
-
-        // Builder used to concatenate concurrent lines of element content and entity evaluations into a single value.
-        private StringBuilder contentBuilder;
-
-        // The entity being processed
-        private String entity;
-
-        Handler( SequencerOutput output,
-                 SequencerContext context,
-                 ProgressMonitor monitor ) {
-            assert output != null;
-            assert monitor != null;
-            assert context != null;
-            this.output = output;
-            this.context = context;
-            this.monitor = monitor;
-            // Initialize path to a an empty path relative to the SequencerOutput's target path.
-            path = context.getValueFactories().getPathFactory().createRelativePath();
-            // Cache name factory since it is frequently used
-            nameFactory = context.getValueFactories().getNameFactory();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#attributeDecl(java.lang.String, java.lang.String, java.lang.String,
-         *      java.lang.String, java.lang.String)
-         */
-        @Override
-        public void attributeDecl( String name,
-                                   String name2,
-                                   String type,
-                                   String mode,
-                                   String value ) throws SAXException {
-            stopIfCancelled();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
-         */
-        @Override
-        public void characters( char[] ch,
-                                int start,
-                                int length ) throws SAXException {
-            stopIfCancelled();
-            String content = String.valueOf(ch, start, length);
-            // Check if data should be appended to previously parsed CDATA
-            if (cDataBuilder == null) {
-                // If content is for an entity, replace with entity reference
-                if (entity != null) {
-                    content = '&' + entity + ';';
-                }
-                // Check if first line of content
-                if (contentBuilder == null) {
-                    contentBuilder = new StringBuilder(content);
-                } else {
-                    // Append additional lines or entity evaluations to previous content, separated by a space
-                    if (entity == null) {
-                        contentBuilder.append(' ');
-                    }
-                    contentBuilder.append(content);
-                    // Text within builder will be output when another element or CDATA is encountered
-                }
-            } else {
-                cDataBuilder.append(ch, start, length);
-                // Text within builder will be output at the end of CDATA
-            }
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#comment(char[], int, int)
-         */
-        @Override
-        public void comment( char[] ch,
-                             int start,
-                             int length ) throws SAXException {
-            stopIfCancelled();
-            // Output separate nodes for each comment since multiple are allowed
-            startElement(DnaXmlLexicon.COMMENT);
-            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.COMMENT);
-            output.setProperty(path, DnaXmlLexicon.COMMENT_CONTENT, String.valueOf(ch, start, length));
-            endElement();
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#elementDecl(java.lang.String, java.lang.String)
-         */
-        @Override
-        public void elementDecl( String name,
-                                 String model ) throws SAXException {
-            stopIfCancelled();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#endCDATA()
-         */
-        @Override
-        public void endCDATA() throws SAXException {
-            stopIfCancelled();
-            // Output CDATA built in characters() method
-            output.setProperty(path, DnaXmlLexicon.CDATA_CONTENT, cDataBuilder.toString());
-            endElement();
-            // Null-out builder to free memory
-            cDataBuilder = null;
-            updateProgress();
-        }
-
-        private void endContent() {
-            if (contentBuilder != null) {
-                // Normalize content
-                String content = StringUtil.normalize(contentBuilder.toString());
-                // Null-out builder to setup for subsequent content.
-                // Must be done before call to startElement below to prevent infinite loop.
-                contentBuilder = null;
-                // Skip if nothing in content but whitespace
-                if (content.length() > 0) {
-                    // Create separate node for each content entry since entries can be interspersed amongst child elements
-                    startElement(DnaXmlLexicon.ELEMENT_CONTENT);
-                    output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.ELEMENT_CONTENT);
-                    output.setProperty(path, DnaXmlLexicon.ELEMENT_CONTENT, content);
-                    endElement();
-                }
-            }
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#endDocument()
-         */
-        @Override
-        public void endDocument() throws SAXException {
-            stopIfCancelled();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#endDTD()
-         */
-        @Override
-        public void endDTD() throws SAXException {
-            stopIfCancelled();
-        }
-
-        private void endElement() {
-            // Recover parent's path, namespace, and indexedName map, clearing the ended element's map to free memory
-            path = path.getParent();
-            nameToIndexedNamesMap.clear();
-            nameToIndexedNamesMap = nameToIndexedNamesMapStack.removeFirst();
-            nsStack.removeFirst();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
-         */
-        @Override
-        public void endElement( String uri,
-                                String localName,
-                                String name ) throws SAXException {
-            stopIfCancelled();
-            // Check if content still needs to be output
-            endContent();
-            endElement();
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#endEntity(java.lang.String)
-         */
-        @Override
-        public void endEntity( String name ) throws SAXException {
-            stopIfCancelled();
-            entity = null;
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
-         */
-        @Override
-        public void error( SAXParseException error ) {
-            context.getLogger(XmlSequencer.class).error(error, GraphI18n.errorSequencingXmlDocument, error);
-            monitor.getProblems().addError(error, GraphI18n.errorSequencingXmlDocument, error);
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#externalEntityDecl(java.lang.String, java.lang.String, java.lang.String)
-         */
-        @Override
-        public void externalEntityDecl( String name,
-                                        String publicId,
-                                        String systemId ) throws SAXException {
-            stopIfCancelled();
-            // Add "synthetic" entity container to path to help prevent name collisions with XML elements
-            Name entityName = DnaDtdLexicon.ENTITY;
-            startElement(entityName);
-            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, entityName);
-            output.setProperty(path, nameFactory.create(DnaDtdLexicon.NAME), name);
-            output.setProperty(path, nameFactory.create(DnaDtdLexicon.PUBLIC_ID), publicId);
-            output.setProperty(path, nameFactory.create(DnaDtdLexicon.SYSTEM_ID), systemId);
-            endElement();
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException)
-         */
-        @Override
-        public void fatalError( SAXParseException error ) {
-            context.getLogger(XmlSequencer.class).error(error, GraphI18n.fatalErrorSequencingXmlDocument, error);
-            monitor.getProblems().addError(error, GraphI18n.fatalErrorSequencingXmlDocument, error);
-        }
-
-        private Name getDefaultPrimaryType() {
-            if (defaultPrimaryType == null) {
-                defaultPrimaryType = nameFactory.create(DEFAULT_PRIMARY_TYPE);
-            }
-            return defaultPrimaryType;
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#ignorableWhitespace(char[], int, int)
-         */
-        @Override
-        public void ignorableWhitespace( char[] ch,
-                                         int start,
-                                         int length ) throws SAXException {
-            stopIfCancelled();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#internalEntityDecl(java.lang.String, java.lang.String)
-         */
-        @Override
-        public void internalEntityDecl( String name,
-                                        String value ) throws SAXException {
-            stopIfCancelled();
-            // Add "synthetic" entity container to path to help prevent name collisions with XML elements
-            Name entityName = DnaDtdLexicon.ENTITY;
-            startElement(entityName);
-            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, entityName);
-            output.setProperty(path, DnaDtdLexicon.NAME, name);
-            output.setProperty(path, DnaDtdLexicon.VALUE, value);
-            endElement();
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#notationDecl(java.lang.String, java.lang.String, java.lang.String)
-         */
-        @Override
-        public void notationDecl( String name,
-                                  String publicId,
-                                  String systemId ) throws SAXException {
-            stopIfCancelled();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#processingInstruction(java.lang.String, java.lang.String)
-         */
-        @Override
-        public void processingInstruction( String target,
-                                           String data ) throws SAXException {
-            stopIfCancelled();
-            // Output separate nodes for each instruction since multiple are allowed
-            Name name = DnaXmlLexicon.PROCESSING_INSTRUCTION;
-            startElement(name);
-            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, name);
-            output.setProperty(path, DnaXmlLexicon.TARGET, target);
-            output.setProperty(path, DnaXmlLexicon.PROCESSING_INSTRUCTION_CONTENT, data);
-            endElement();
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#skippedEntity(java.lang.String)
-         */
-        @Override
-        public void skippedEntity( String name ) throws SAXException {
-            stopIfCancelled();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#startCDATA()
-         */
-        @Override
-        public void startCDATA() throws SAXException {
-            stopIfCancelled();
-            // Output separate nodes for each CDATA since multiple are allowed
-            startElement(DnaXmlLexicon.CDATA);
-            // Prepare builder for concatenating consecutive lines of CDATA
-            cDataBuilder = new StringBuilder();
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#startDocument()
-         */
-        @Override
-        public void startDocument() throws SAXException {
-            stopIfCancelled();
-            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.DOCUMENT);
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#startDTD(java.lang.String, java.lang.String, java.lang.String)
-         */
-        @Override
-        public void startDTD( String name,
-                              String publicId,
-                              String systemId ) throws SAXException {
-            stopIfCancelled();
-            output.setProperty(path, DnaDtdLexicon.NAME, name);
-            output.setProperty(path, DnaDtdLexicon.PUBLIC_ID, publicId);
-            output.setProperty(path, DnaDtdLexicon.SYSTEM_ID, systemId);
-            updateProgress();
-        }
-
-        private void startElement( Name name ) {
-            // Check if content still needs to be output
-            endContent();
-            // Add name to list of indexed names for this element to ensure we use the correct index (which is the size of the
-            // list)
-            List<IndexedName> indexedNames = nameToIndexedNamesMap.get(name);
-            if (indexedNames == null) {
-                indexedNames = new ArrayList<IndexedName>();
-                nameToIndexedNamesMap.put(name, indexedNames);
-            }
-            IndexedName indexedName = new IndexedName();
-            indexedNames.add(indexedName);
-            // Add element name and the appropriate index to the path.
-            // Per the JCR spec, the index must be relative to same-name sibling nodes
-            path = context.getValueFactories().getPathFactory().create(path, name, indexedNames.size());
-            path = path.getNormalizedPath();
-            // Add the indexed name map to the stack and set the current map to the new element's map
-            nameToIndexedNamesMapStack.addFirst(nameToIndexedNamesMap);
-            nameToIndexedNamesMap = indexedName.nameToIndexedNamesMap;
-            // Set the current namespace to whatever is declared by this element, or if not declared, to its nearest ancestor that
-            // does declare a namespace.
-            String ns = name.getNamespaceUri();
-            if (ns.length() == 0) {
-                nsStack.addFirst(nsStack.isEmpty() ? "" : nsStack.getFirst());
-            } else {
-                nsStack.addFirst(ns);
-            }
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String,
-         *      org.xml.sax.Attributes)
-         */
-        @Override
-        public void startElement( String uri,
-                                  String localName,
-                                  String name,
-                                  Attributes attributes ) throws SAXException {
-            stopIfCancelled();
-            // Look for the "jcr:name" attribute, and use that if it's there
-            Name type = getDefaultPrimaryType();
-            Name nameObj = nameFactory.create(name);
-            for (int ndx = 0, len = attributes.getLength(); ndx < len; ++ndx) {
-                String ns = attributes.getURI(ndx);
-                String attrLocalName = attributes.getLocalName(ndx);
-                Object value = attributes.getValue(ndx);
-                String jcrNsUri = context.getNamespaceRegistry().getNamespaceForPrefix("jcr");
-                if (jcrNsUri != null && jcrNsUri.equals(ns) && attrLocalName.equals("name")) {
-                    nameObj = nameFactory.create(value);
-                    break;
-                }
-            }
-            startElement(nameObj);
-            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, type);
-            // Output this element's attributes using the attribute's namespace, if supplied, or the current namespace in scope.
-            String inheritedNs = nsStack.getFirst();
-            for (int ndx = 0, len = attributes.getLength(); ndx < len; ++ndx) {
-                String ns = attributes.getURI(ndx);
-                String attrLocalName = attributes.getLocalName(ndx);
-                Object value = attributes.getValue(ndx);
-                String jcrNsUri = context.getNamespaceRegistry().getNamespaceForPrefix("jcr");
-                if (jcrNsUri != null && jcrNsUri.equals(ns) && attrLocalName.equals("primaryType")) {
-                    value = nameFactory.create(value);
-                }
-                if (jcrNsUri != null && jcrNsUri.equals(ns) && attrLocalName.equals("name")) {
-                    continue;
-                }
-                output.setProperty(path, nameFactory.create(ns.length() == 0 ? inheritedNs : ns, attrLocalName), value);
-            }
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.ext.DefaultHandler2#startEntity(java.lang.String)
-         */
-        @Override
-        public void startEntity( String name ) throws SAXException {
-            stopIfCancelled();
-            entity = name;
-            updateProgress();
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#startPrefixMapping(java.lang.String, java.lang.String)
-         */
-        @Override
-        public void startPrefixMapping( String prefix,
-                                        String uri ) throws SAXException {
-            stopIfCancelled();
-            // Register any unregistered namespaces
-            NamespaceRegistry registry = context.getNamespaceRegistry();
-            if (!registry.isRegisteredNamespaceUri(uri)) {
-                registry.register(prefix, uri);
-            }
-            updateProgress();
-        }
-
-        private void stopIfCancelled() throws SAXException {
-            if (monitor.isCancelled()) {
-                throw new SAXException(GraphI18n.canceledSequencingXmlDocument.text());
-            }
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String,
-         *      java.lang.String)
-         */
-        @Override
-        public void unparsedEntityDecl( String name,
-                                        String publicId,
-                                        String systemId,
-                                        String notationName ) throws SAXException {
-            stopIfCancelled();
-        }
-
-        private void updateProgress() {
-            if (progress == 100.0) {
-                progress = 1;
-            } else {
-                progress++;
-            }
-            monitor.worked(progress);
-        }
-
-        /**
-         * <p>
-         * {@inheritDoc}
-         * </p>
-         * 
-         * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException)
-         */
-        @Override
-        public void warning( SAXParseException warning ) {
-            context.getLogger(XmlSequencer.class).warn(warning, GraphI18n.warningSequencingXmlDocument);
-            monitor.getProblems().addWarning(warning, GraphI18n.warningSequencingXmlDocument, warning);
-        }
-    }
-
-    private class IndexedName {
-
-        Map<Name, List<IndexedName>> nameToIndexedNamesMap = new HashMap<Name, List<IndexedName>>();
-
-        IndexedName() {
-        }
-    }
-}

Modified: trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties
===================================================================
--- trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties	2008-10-29 18:23:01 UTC (rev 598)
@@ -62,12 +62,6 @@
 actualNewLocationMustHaveSameParentAsOldLocation = The new location of {0} must be a sibling of the old location of {1}
 actualNewLocationMustHaveSameNameAsRequest = The new location of {0} must have the same name as in the request ({1})
 
-errorSequencingXmlDocument = An error was received while sequencing XML: {0}
-fatalErrorSequencingXmlDocument = A fatal error was received while sequencing XML: {0}
-sequencingXmlDocument = Sequencing XML
-canceledSequencingXmlDocument = Canceled sequencing XML
-warningSequencingXmlDocument = A warning was received while sequencing XML: {0}
-
 errorImportingContent = Error importing {0} content from {1}
 unableToFindRepositorySourceWithName = Unable to find a repository source named "{0}"
 

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -47,8 +47,6 @@
 import org.jboss.dna.graph.requests.CompositeRequest;
 import org.jboss.dna.graph.requests.CreateNodeRequest;
 import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.xml.DnaDtdLexicon;
-import org.jboss.dna.graph.xml.DnaXmlLexicon;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;
@@ -76,8 +74,6 @@
         xmlContent = new File("src/test/resources/repositoryImporterTestData1.xml").toURI();
         context = new BasicExecutionContext();
         context.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
-        context.getNamespaceRegistry().register(DnaXmlLexicon.Namespace.PREFIX, DnaXmlLexicon.Namespace.URI);
-        context.getNamespaceRegistry().register(DnaDtdLexicon.Namespace.PREFIX, DnaDtdLexicon.Namespace.URI);
         context.getNamespaceRegistry().register("jcr", "http://www.jcp.org/jcr/1.0");
         context.getNamespaceRegistry().register("nt", "http://www.jcp.org/jcr/nt/1.0");
         sourceName = "sourceA";

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlSequencerTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlSequencerTest.java	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlSequencerTest.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,221 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.xml;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import org.jboss.dna.common.monitor.ProgressMonitor;
-import org.jboss.dna.common.monitor.SimpleProgressMonitor;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.sequencers.MockSequencerContext;
-import org.jboss.dna.graph.sequencers.MockSequencerOutput;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author John Verhaeg
- */
-public class XmlSequencerTest {
-
-    private static final String CDATA = "dnaxml:cData";
-    private static final String CDATA_CONTENT = "dnaxml:cDataContent";
-    private static final String COMMENT = "dnaxml:comment";
-    private static final String COMMENT_CONTENT = "dnaxml:commentContent";
-    private static final String DOCUMENT = "dnaxml:document";
-    private static final String DTD_NAME = "dnadtd:name";
-    private static final String DTD_PUBLIC_ID = "dnadtd:publicId";
-    private static final String DTD_SYSTEM_ID = "dnadtd:systemId";
-    private static final String DTD_VALUE = "dnadtd:value";
-    private static final String ELEMENT_CONTENT = "dnaxml:elementContent";
-    private static final String ENTITY = "dnadtd:entity";
-    private static final String PI = "dnaxml:processingInstruction";
-    private static final String PI_CONTENT = "dnaxml:processingInstructionContent";
-    private static final String TARGET = "dnaxml:target";
-
-    private XmlSequencer sequencer;
-    private InputStream stream;
-    private MockSequencerOutput output;
-    private ProgressMonitor monitor;
-    private URL xml1;
-    private URL xml2;
-    private URL xml3;
-    private URL xml4;
-    private URL xsd;
-    private SequencerContext context;
-
-    @Before
-    public void beforeEach() {
-        sequencer = new XmlSequencer();
-        context = new MockSequencerContext();
-        output = new MockSequencerOutput(context);
-        monitor = new SimpleProgressMonitor("Test activity");
-        xml1 = this.getClass().getClassLoader().getResource("jackrabbitInMemoryTestRepositoryConfig.xml");
-        assertThat(xml1, is(notNullValue()));
-        xml2 = this.getClass().getClassLoader().getResource("master.xml");
-        assertThat(xml2, is(notNullValue()));
-        xml3 = this.getClass().getClassLoader().getResource("CurrencyFormatterExample.mxml");
-        assertThat(xml3, is(notNullValue()));
-        xml4 = this.getClass().getClassLoader().getResource("plugin.xml");
-        assertThat(xml4, is(notNullValue()));
-        xsd = this.getClass().getClassLoader().getResource("Descriptor.1.0.xsd");
-        assertThat(xsd, is(notNullValue()));
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        if (stream != null) {
-            try {
-                stream.close();
-            } finally {
-                stream = null;
-            }
-        }
-    }
-
-    @Test
-    public void shouldSequenceXml() throws IOException {
-        verifyDocument(xml1);
-        verifyName(COMMENT + "[1]", "jcr:primaryType", COMMENT);
-        String text = verify(COMMENT + "[1]", COMMENT_CONTENT, String.class);
-        assertThat(text.startsWith("\n   Licensed to the Apache Software Foundation (ASF)"), is(true));
-        assertThat(text.endsWith("   limitations under the License.\n"), is(true));
-        verifyString("/", DTD_NAME, "Repository");
-        verifyString("/", DTD_PUBLIC_ID, "-//The Apache Software Foundation//DTD Jackrabbit 1.2//EN");
-        verifyString("/", DTD_SYSTEM_ID, "http://jackrabbit.apache.org/dtd/repository-1.2.dtd");
-        verifyName(COMMENT + "[2]", "jcr:primaryType", COMMENT);
-        verifyString(COMMENT + "[2]", COMMENT_CONTENT, " Example Repository Configuration File ");
-        verifyName("Repository[1]", "jcr:primaryType", "nt:unstructured");
-        verifyName("Repository[1]/" + COMMENT + "[1]", "jcr:primaryType", COMMENT);
-    }
-
-    @Test
-    public void shouldHandleNamespaces() throws IOException {
-        verifyDocument(xml2);
-        verifyName("book[1]/bookinfo[1]/xi:include[1]", "jcr:primaryType", "nt:unstructured");
-        verifyString("book[1]/bookinfo[1]/xi:include[1]", "xi:href", "Author_Group.xml");
-        verifyName("book[1]/bookinfo[1]/xi:include[2]", "jcr:primaryType", "nt:unstructured");
-        verifyString("book[1]/bookinfo[1]/xi:include[2]", "xi:href", "Legal_Notice.xml");
-    }
-
-    @Test
-    public void shouldSequenceEntityDeclarations() throws IOException {
-        verifyDocument(xml2);
-        verifyName(ENTITY + "[1]", "jcr:primaryType", ENTITY);
-        verifyString(ENTITY + "[1]", DTD_NAME, "%RH-ENTITIES");
-        verifyString(ENTITY + "[1]", DTD_SYSTEM_ID, "Common_Config/rh-entities.ent");
-        verifyName(ENTITY + "[2]", "jcr:primaryType", ENTITY);
-        verifyString(ENTITY + "[2]", DTD_NAME, "versionNumber");
-        verifyString(ENTITY + "[2]", DTD_VALUE, "0.1");
-        verifyName(ENTITY + "[3]", "jcr:primaryType", ENTITY);
-        verifyString(ENTITY + "[3]", DTD_NAME, "copyrightYear");
-        verifyString(ENTITY + "[3]", DTD_VALUE, "2008");
-    }
-
-    @Test
-    public void shouldSequenceElementContent() throws IOException {
-        verifyDocument(xml2);
-        verifyString("book[1]/chapter[4]/sect1[1]/para[8]/" + ELEMENT_CONTENT + "[1]",
-                     ELEMENT_CONTENT,
-                     "The path expression is more complicated."
-                     + " Sequencer path expressions are used by the sequencing service to determine whether a particular changed node should be sequenced."
-                     + " The expressions consist of two parts: a selection criteria and an output expression."
-                     + " Here's a simple example:");
-        verifyString("book[1]/chapter[4]/sect1[1]/para[8]/programlisting[1]/" + ELEMENT_CONTENT + "[1]",
-                     ELEMENT_CONTENT,
-                     "/a/b/c at title =&gt; /d/e/f");
-    }
-
-    @Test
-    public void shouldSequenceCData() throws IOException {
-        verifyDocument(xml3);
-        verifyString("mx:Application[1]/mx:Script[1]/" + CDATA + "[1]",
-                     CDATA_CONTENT,
-                     "\n\n" + "              import mx.events.ValidationResultEvent;\t\t\t\n"
-                     + "              private var vResult:ValidationResultEvent;\n" + "\t\t\t\n"
-                     + "              // Event handler to validate and format input.\n"
-                     + "              private function Format():void {\n" + "              \n"
-                     + "                    vResult = numVal.validate();\n\n"
-                     + "                    if (vResult.type==ValidationResultEvent.VALID) {\n"
-                     + "                        var temp:Number=Number(priceUS.text); \n"
-                     + "                        formattedUSPrice.text= usdFormatter.format(temp);\n" + "                    }\n"
-                     + "                    \n" + "                    else {\n"
-                     + "                       formattedUSPrice.text=\"\";\n" + "                    }\n" + "              }\n"
-                     + "        ");
-    }
-
-    @Test
-    public void shouldSequenceProcessingInstructions() throws IOException {
-        verifyDocument(xml4);
-        verifyName(PI + "[1]", "jcr:primaryType", PI);
-        verifyString(PI + "[1]", TARGET, "eclipse");
-        verifyString(PI + "[1]", PI_CONTENT, "version=\"3.0\"");
-    }
-
-    @Test
-    public void shouldSequenceXsds() throws IOException {
-        verifyDocument(xsd);
-        verifyName("xs:schema[1]", "jcr:primaryType", "nt:unstructured");
-        verifyString("xs:schema[1]", "xs:targetNamespace", "http://ns.adobe.com/air/application/1.0");
-        verifyString("xs:schema[1]", "xs:elementFormDefault", "qualified");
-        verifyName("xs:schema[1]/xs:element[1]", "jcr:primaryType", "nt:unstructured");
-        verifyString("xs:schema[1]/xs:element[1]", "xs:name", "application");
-    }
-
-    private <T> T verify( String nodePath,
-                          String property,
-                          Class<T> expectedClass ) {
-        Object[] values = output.getPropertyValues(nodePath.length() == 0 ? "." : nodePath, property);
-        assertThat(values, notNullValue());
-        assertThat(values.length, is(1));
-        Object value = values[0];
-        assertThat(value, instanceOf(expectedClass));
-        return expectedClass.cast(value);
-    }
-
-    private void verifyDocument( URL url ) throws IOException {
-        stream = url.openStream();
-        assertThat(stream, is(notNullValue()));
-        sequencer.sequence(stream, output, context, monitor);
-        verifyName("", "jcr:primaryType", DOCUMENT);
-    }
-
-    private void verifyName( String nodePath,
-                             String property,
-                             String expectedName ) {
-        Name name = verify(nodePath, property, Name.class);
-        assertThat(name, is(context.getValueFactories().getNameFactory().create(expectedName)));
-    }
-
-    private void verifyString( String nodePath,
-                               String property,
-                               String expectedString ) {
-        String string = verify(nodePath, property, String.class);
-        assertThat(string, is(expectedString));
-    }
-}

Deleted: trunk/dna-graph/src/test/resources/CurrencyFormatterExample.mxml
===================================================================
--- trunk/dna-graph/src/test/resources/CurrencyFormatterExample.mxml	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/test/resources/CurrencyFormatterExample.mxml	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Simple example to demonstrate the CurrencyFormatter. -->
-<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
-
-    <mx:Script>
-        <![CDATA[
-
-              import mx.events.ValidationResultEvent;			
-              private var vResult:ValidationResultEvent;
-			
-              // Event handler to validate and format input.
-              private function Format():void {
-              
-                    vResult = numVal.validate();
-
-                    if (vResult.type==ValidationResultEvent.VALID) {
-                        var temp:Number=Number(priceUS.text); 
-                        formattedUSPrice.text= usdFormatter.format(temp);
-                    }
-                    
-                    else {
-                       formattedUSPrice.text="";
-                    }
-              }
-        ]]>
-    </mx:Script>
-
-    <mx:CurrencyFormatter id="usdFormatter" precision="2" 
-        currencySymbol="$" decimalSeparatorFrom="."
-        decimalSeparatorTo="." useNegativeSign="true" 
-        useThousandsSeparator="true" alignSymbol="left"/>
-
-    <mx:NumberValidator id="numVal" source="{priceUS}" property="text" 
-        allowNegative="true" domain="real"/>
-
-    <mx:Panel title="CurrencyFormatter Example" width="75%" height="75%" 
-        paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
-
-        <mx:Form>
-            <mx:FormItem label="Enter U.S. dollar amount:">
-                <mx:TextInput id="priceUS" text="" width="50%"/>
-            </mx:FormItem>
-
-            <mx:FormItem label="Formatted amount: ">
-                <mx:TextInput id="formattedUSPrice" text="" width="50%" editable="false"/>
-            </mx:FormItem>
-
-            <mx:FormItem>
-                <mx:Button label="Validate and Format" click="Format();"/>
-            </mx:FormItem>
-        </mx:Form>
-
-    </mx:Panel>
-</mx:Application>

Deleted: trunk/dna-graph/src/test/resources/Descriptor.1.0.xsd
===================================================================
--- trunk/dna-graph/src/test/resources/Descriptor.1.0.xsd	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/test/resources/Descriptor.1.0.xsd	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,127 +0,0 @@
-<?xml version="1.0"?>
-<xs:schema 
-    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
-    targetNamespace="http://ns.adobe.com/air/application/1.0" 
-    xmlns="http://ns.adobe.com/air/application/1.0" 
-    elementFormDefault="qualified"
->
-  <xs:element name="application">
-    <xs:complexType>
-      <xs:all>
-        <!-- About this application -->
-        <xs:element name="id">
-          <xs:simpleType>
-            <xs:restriction base="xs:string">
-              <xs:pattern value="[A-Za-z0-9\-\.]{1,212}"/>
-            </xs:restriction>
-          </xs:simpleType>
-        </xs:element>
-        <xs:element name="name"           type="xs:string" minOccurs="0"/>
-        <xs:element name="version"        type="xs:string"/>
-        <xs:element name="filename">
-          <xs:simpleType>
-            <xs:restriction base="xs:string">
-              <!-- name cannot begin with a ' ' (space), have any of these characters: *"/:<>?\|, and end with a . (dot) or ' ' (space) -->
-              <xs:pattern value='[^\*"/:&gt;&lt;\?\\\|\. ]|[^\*"/:&gt;&lt;\?\\\| ][^\*"/:&gt;&lt;\?\\\|]*[^\*"/:&gt;&lt;\?\\\|\. ]'/>
-            </xs:restriction>
-          </xs:simpleType>
-        </xs:element>
-        <xs:element name="description"    type="xs:string" minOccurs="0"/>
-        <xs:element name="copyright"      type="xs:string" minOccurs="0"/>
-        <xs:element name="icon" type="IconType" minOccurs="0"/>
-
-        <!-- How to start this application -->
-        <xs:element name="initialWindow">
-          <xs:complexType>
-            <xs:all>
-              <xs:element name="content" type="xs:anyURI" minOccurs="1" />
-              <xs:element name="title" type="xs:string" minOccurs="0" />
-
-              <xs:element name="systemChrome" minOccurs="0" >
-                <xs:simpleType>
-                  <xs:restriction base="xs:string">
-                    <xs:enumeration value="none"/>
-                    <xs:enumeration value="standard"/>
-                  </xs:restriction>
-                </xs:simpleType>
-              </xs:element>
-              <xs:element name="transparent" type="xs:boolean" minOccurs="0" />
-              <xs:element name="visible" type="xs:boolean" minOccurs="0" />
-
-              <xs:element name="minimizable" type="xs:boolean" minOccurs="0" />
-              <xs:element name="maximizable" type="xs:boolean" minOccurs="0" />
-              <xs:element name="resizable" type="xs:boolean" minOccurs="0" />
-
-              <xs:element name="x" type="xs:int" minOccurs="0" />
-              <xs:element name="y" type="xs:int" minOccurs="0" />
-              <xs:element name="width" type="xs:unsignedInt" minOccurs="0" />
-              <xs:element name="height" type="xs:unsignedInt" minOccurs="0" />
-              <xs:element name="minSize" type="BoundsSizeType" minOccurs="0" />
-              <xs:element name="maxSize" type="BoundsSizeType" minOccurs="0" />
-            </xs:all>
-          </xs:complexType>
-        </xs:element>
-        
-        <!-- About installing this application -->
-        <xs:element name="installFolder" minOccurs="0">
-          <xs:simpleType>
-            <xs:restriction base="xs:string">
-              <!-- installFolder cannot begin with a / (forward-slash) or a ' ' (space), have any of these characters: *":<>?\|, and end with a . (dot) or ' ' (space) -->
-              <xs:pattern value='[^\*"/:&gt;&lt;\?\\\|\. ]|[^\*"/:&gt;&lt;\?\\\| ][^\*":&gt;&lt;\?\\\|]*[^\*":&gt;&lt;\?\\\|\. ]'/>
-            </xs:restriction>
-          </xs:simpleType>
-        </xs:element>
-        <xs:element name="programMenuFolder" minOccurs="0">
-          <xs:simpleType>
-            <xs:restriction base="xs:string">
-              <!-- programMenuFolder cannot begin with a / (forward-slash) or a ' ' (space), have any of these characters: *":<>?\|, and end with a . (dot) or ' ' (space) -->
-              <xs:pattern value='[^\*"/:&gt;&lt;\?\\\|\. ]|[^\*"/:&gt;&lt;\?\\\| ][^\*":&gt;&lt;\?\\\|]*[^\*":&gt;&lt;\?\\\|\. ]'/>
-            </xs:restriction>
-          </xs:simpleType>
-        </xs:element>        
-
-        <!-- Features this application can opt in to -->
-        <xs:element name="customUpdateUI" type="xs:boolean" minOccurs="0"/>
-        <xs:element name="allowBrowserInvocation" type="xs:boolean" minOccurs="0"/>
-        <xs:element name="fileTypes" minOccurs="0">
-          <xs:complexType>
-            <xs:sequence>                    
-              <xs:element name="fileType" minOccurs="0" maxOccurs="unbounded">
-                <xs:complexType>
-                  <xs:all>
-                  <xs:element name="name" type="xs:string"/>
-                  <xs:element name="extension" type="xs:string"/>
-                  <xs:element name="description" type="xs:string" minOccurs="0"/>
-                  <xs:element name="contentType" type="xs:string" minOccurs="0"/>
-                  <xs:element name="icon" type="IconType" minOccurs="0"/>
-                </xs:all>
-                </xs:complexType>
-              </xs:element>
-            </xs:sequence>
-          </xs:complexType>
-        </xs:element>
-      </xs:all>
-
-      <!-- About the runtime version required -->
-      <xs:attribute name="minimumPatchLevel" type="xs:unsignedInt"/>
-    </xs:complexType>
-  </xs:element>
-
-  <!-- Type definitions -->
-  <xs:complexType name="IconType">
-      <xs:all>
-          <xs:element name="image16x16"   type="xs:anyURI" minOccurs="0"/>
-          <xs:element name="image32x32"   type="xs:anyURI" minOccurs="0"/>
-          <xs:element name="image48x48"   type="xs:anyURI" minOccurs="0"/>
-          <xs:element name="image128x128" type="xs:anyURI" minOccurs="0"/>
-      </xs:all>
-  </xs:complexType>
-  <xs:simpleType name="UnsignedIntListType">
-    <xs:list itemType="xs:unsignedInt"/>
-  </xs:simpleType>
-  <xs:simpleType name="BoundsSizeType">
-    <xs:restriction base="UnsignedIntListType">
-      <xs:length value="2"/> 
-    </xs:restriction>
-  </xs:simpleType>
-</xs:schema>

Deleted: trunk/dna-graph/src/test/resources/jackrabbitInMemoryTestRepositoryConfig.xml
===================================================================
--- trunk/dna-graph/src/test/resources/jackrabbitInMemoryTestRepositoryConfig.xml	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/test/resources/jackrabbitInMemoryTestRepositoryConfig.xml	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,116 +0,0 @@
-<?xml version="1.0"?>
-<!--
-   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.
--->
-<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.2//EN"
-                            "http://jackrabbit.apache.org/dtd/repository-1.2.dtd">
-<!-- Example Repository Configuration File -->
-<Repository>
-    <!--
-        virtual file system where the repository stores global state
-        (e.g. registered namespaces, custom node types, etc.)
-    -->
-    <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem">
-        <param name="path" value="${rep.home}/repository"/>
-    </FileSystem>
-
-    <!--
-        security configuration
-    -->
-    <Security appName="Jackrabbit">
-        <!--
-            access manager:
-            class: FQN of class implementing the AccessManager interface
-        -->
-        <AccessManager class="org.apache.jackrabbit.core.security.SimpleAccessManager">
-            <!-- <param name="config" value="${rep.home}/access.xml"/> -->
-        </AccessManager>
-
-        <LoginModule class="org.apache.jackrabbit.core.security.SimpleLoginModule">
-           <!-- anonymous user name ('anonymous' is the default value) -->
-           <param name="anonymousId" value="anonymous"/>
-           <!--
-              default user name to be used instead of the anonymous user
-              when no login credentials are provided (unset by default)
-           -->
-           <!-- <param name="defaultUserId" value="superuser"/> -->
-        </LoginModule>
-    </Security>
-
-    <!--
-        location of workspaces root directory and name of default workspace
-    -->
-    <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default"/>
-    <!--
-        workspace configuration template:
-        used to create the initial workspace if there's no workspace yet
-    -->
-    <Workspace name="Jackrabbit Core">
-        <!--
-            virtual file system of the workspace:
-            class: FQN of class implementing the FileSystem interface
-        -->
-
-        <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem">
-            <param name="path" value="${wsp.home}"/>
-        </FileSystem>
-        <!--
-            persistence manager of the workspace:
-            class: FQN of class implementing the PersistenceManager interface
-        -->
-        <PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager">
-          <param name="persistent" value="false"/>
-        </PersistenceManager>
-        <!--
-            Search index and the file system it uses.
-            class: FQN of class implementing the QueryHandler interface
-        -->
-        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
-            <param name="path" value="${wsp.home}/index"/>
-        </SearchIndex>
-    </Workspace>
-
-    <!--
-        Configures the versioning
-    -->
-    <Versioning rootPath="${rep.home}/version">
-        <!--
-            Configures the filesystem to use for versioning for the respective
-            persistence manager
-        -->
-        <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem">
-            <param name="path" value="${rep.home}/version" />
-        </FileSystem>
-
-        <!--
-            Configures the persistence manager to be used for persisting version state.
-            Please note that the current versioning implementation is based on
-            a 'normal' persistence manager, but this could change in future
-            implementations.
-        -->
-        <PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager">
-          <param name="persistent" value="false"/>
-        </PersistenceManager>
-    </Versioning>
-
-    <!--
-        Search index for content that is shared repository wide
-        (/jcr:system tree, contains mainly versions)
-    -->
-    <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
-        <param name="path" value="${rep.home}/repository/index"/>
-    </SearchIndex>
-</Repository>

Deleted: trunk/dna-graph/src/test/resources/master.xml
===================================================================
--- trunk/dna-graph/src/test/resources/master.xml	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/test/resources/master.xml	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,1890 +0,0 @@
-<!--
-  ~ JBoss, Home of Professional Open Source.
-  ~
-  ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
-  ~ indicated by the @author tags or express copyright attribution
-  ~ statements applied by the authors.  All third-party contributions are
-  ~ distributed under license by Red Hat Middleware LLC.
-  ~
-  ~ This copyrighted material is made available to anyone wishing to use, modify,
-  ~ copy, or redistribute it subject to the terms and conditions of the GNU
-  ~ Lesser General Public License, as published by the Free Software Foundation.
-  ~
-  ~ This program is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-  ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-  ~ for more details.
-  ~
-  ~ You should have received a copy of the GNU Lesser General Public License
-  ~ along with this distribution; if not, write to:
-  ~ Free Software Foundation, Inc.
-  ~ 51 Franklin Street, Fifth Floor
-  ~ Boston, MA  02110-1301  USA
-  -->
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
-<!ENTITY % RH-ENTITIES SYSTEM "Common_Config/rh-entities.ent">
-<!ENTITY versionNumber "0.1">
-<!ENTITY copyrightYear "2008">
-<!ENTITY copyrightHolder "Red Hat Middleware, LLC.">]>
-<book>
-  <bookinfo>
-    <title>JBoss DNA</title>
-    <subtitle>Getting Started Guide</subtitle>
-    <releaseinfo>&versionNumber;
-    </releaseinfo>
-    <productnumber>&versionNumber;
-    </productnumber>
-    <issuenum>1</issuenum>
-    <mediaobject>
-      <imageobject role="fo">
-        <imagedata fileref="images/dna-logo.png" align="center" />
-      </imageobject>
-      <imageobject role="pdf">
-        <imagedata fileref="images/dna-logo.png" scale="75" align="center" />
-      </imageobject>
-      <imageobject role="html">
-        <imagedata fileref="images/dna-logo.png" depth="3cm" />
-      </imageobject>
-      <imageobject role="xhtml">
-        <imagedata fileref="images/dna-logo.png" depth="3cm" />
-      </imageobject>
-      <imageobject role="xhtml_single">
-        <imagedata fileref="images/dna-logo.png" depth="3cm" />
-      </imageobject>
-    </mediaobject>
-    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml" />
-    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Legal_Notice.xml" />
-  </bookinfo>
-  <preface id="preface" revision="1">
-    <title>What this book covers</title>
-    <para>The goal of this book is to help you learn about JBoss DNA and how you can use it in your own applications to get the
-      most out of your JCR repositories.</para>
-    <para>The first part of the book starts out with an introduction to content repositories and an overview of the JCR API,
-      both of which are important aspects of JBoss DNA. This is followed by an overview of the JBoss DNA project, its
-      architecture, and a basic roadmap for what's coming next.</para>
-    <para>The next part of the book covers how to download and build the examples, how to use JBoss DNA with existing
-      repositories, and how to build and use custom sequencers.</para>
-    <para>
-      If you have any questions or comments, please feel free to contact JBoss DNA's
-      <ulink url="mailto:dna-users at jboss.org">user mailing list</ulink>
-      or use the
-      <ulink url="http://www.jboss.com/index.html?module=bb&amp;op=viewforum&amp;f=272">user forums</ulink>
-      . If you'd like to get involved on the project, join the
-      <ulink url="http://www.jboss.org/dna/lists.html">mailing lists</ulink>
-      ,
-      <ulink url="http://www.jboss.org/dna/subversion.html">download the code</ulink>
-      and get it building, and visit our
-      <ulink url="http://jira.jboss.org/jira/browse/DNA">JIRA issue management system</ulink>
-      . If there's something in particular you're interested in, talk with the community - there may be others interested in the
-      same thing.
-    </para>
-  </preface>
-  <chapter id="introduction">
-    <title>Introduction</title>
-    <para>There are a lot of choices for how applications can store information persistently so that it can be accessed at a
-      later time and by other processes. The challenge developers face is how to use an approach that most closely matches the
-      needs of their application. This choice becomes more important as developers choose to focus their efforts on
-      application-specific logic, delegating much of the responsibilities for persistence to libraries and frameworks.</para>
-    <para>
-      Perhaps one of the easiest techniques is to simply store information in
-      <emphasis>files</emphasis>
-      . The Java language makes working with files relatively easy, but Java really doesn't provide many bells and whistles. So
-      using files is an easy choice when the information is either not complicated (for example property files), or when users may
-      need to read or change the information outside of the application (for example log files or configuration files). But using
-      files to persist information becomes more difficult as the information becomes more complex, as the volume of it increases,
-      or if it needs to be accessed by multiple processes. For these situations, other techniques often offer better choices.
-    </para>
-    <para>
-      Another technique built into the Java language is
-      <emphasis>Java serialization</emphasis>
-      , which is capable of persisting the state of an object graph so that it can be read back in at a later time. However, Java
-      serialization can quickly become tricky if the classes are changed, and so it's beneficial usually when the information is
-      persisted for a very short period of time. For example, serialization is sometimes used to send an object graph from one
-      process to another.
-    </para>
-    <para>
-      One of the more popular persistence technologies is the
-      <emphasis>relational database</emphasis>
-      . Relational database management systems have been around for decades and are very capable. The Java Database Connectivity
-      (JDBC) API provides a standard interface for connecting to and interacting with relational databases. However, it is a
-      low-level API that requires a lot of code to use correctly, and it still doesn't abstract away the DBMS-specific SQL
-      grammar. Also, working with relational data in an object-oriented language can feel somewhat unnatural, so many developers
-      map this data to classes that fit much more cleanly into their application. The problem is that manually creating this
-      mapping layer requires a lot of repetitive and non-trivial JDBC code.
-    </para>
-    <para>
-      <emphasis>Object-relational mapping</emphasis>
-      libraries automate the creation of this mapping layer and result in far less code that is much more maintainable with
-      performance that is often as good as (if not better than) handwritten JDBC code. The new
-      <ulink url="http://java.sun.com/developer/technicalArticles/J2EE/jpa/">Java Persistence API (JPA)</ulink>
-      provide a standard mechanism for defining the mappings (through annotations) and working with these entity objects. Several
-      commercial and open-source libraries implement JPA, and some even offer additional capabilities and features that go beyond
-      JPA. For example,
-      <ulink url="http://www.hibernate.org">Hibernate</ulink>
-      is one of the most feature-rich JPA implementations and offers object caching, statement caching, extra association
-      mappings, and other features that help to improve performance and usefulness.
-    </para>
-    <para>
-      While relational databases and JPA are solutions that work for many applications, they become more limited in cases when the
-      information structure is highly flexible, is not known
-      <emphasis>a priori</emphasis>
-      , or is subject to frequent change and customization. In these situations,
-      <emphasis>content repositories</emphasis>
-      may offer a better choice for persistence. Content repositories are almost a hybrid between relational databases and file
-      systems, and typically provide other capabilities as well, including versioning, indexing, search, access control,
-      transactions, and observation. Because of this, content repositories are used by content management systems (CMS), document
-      management systems (DMS), and other applications that manage electronic files (e.g., documents, images, multi-media, web
-      content, etc.) and metadata associated with them (e.g., author, date, status, security information, etc.). The
-      <ulink url="http://www.jcp.org/en/jsr/detail?id=170">Content Repository for Java technology API</ulink>
-      provides a standard Java API for working with content repositories. Abbreviated "JCR", this API was developed as part of the
-      Java Community Process under
-      <ulink url="http://www.jcp.org/en/jsr/detail?id=170">JSR-170</ulink>
-      and is being revised under
-      <ulink url="http://www.jcp.org/en/jsr/detail?id=283">JSR-283</ulink>
-      .
-    </para>
-    <para>
-      The
-      <emphasis>JBoss DNA project</emphasis>
-      is building the tools and services that surround content repositories. Nearly all of these capabilities are to be hidden
-      below the JCR API and involve automated processing of the information in the repository. Thus, JBoss DNA can add value to
-      existing repository implementations. For example, JCR repositories offer the ability to upload files into the repository and
-      have the file content indexed for search purposes. JBoss DNA also defines a library for "sequencing" content - to extract
-      meaningful information from that content and store it in the repository, where it can then be searched, accessed, and
-      analyzed using the JCR API.
-    </para>
-    <para> JBoss DNA is building other features as well. One goal of JBoss DNA is to create federated repositories that
-      dynamically merge the information from multiple databases, services, applications, and other JCR repositories. Another is to
-      create customized views based upon the type of data and the role of the user that is accessing the data. And yet another is
-      to create a REST-ful API to allow the JCR content to be accessed easily by other applications written in other languages.
-    </para>
-    <para>
-      The
-      <link linkend="jboss_dna">next chapter</link>
-      in this book goes into more detail about JBoss DNA and its architecture, the different components, what's available now, and
-      what's coming in future releases.
-      <link linkend="downloading_and_running">Chapter 3</link>
-      then provides instructions for downloading and running the sequencer examples for the current release.
-      <link linkend="using_dna">Chapter 4</link>
-      walks through how to use JBoss DNA in your applications, while
-      <link linkend="custom_sequencers">Chapter 5</link>
-      goes over how to create custom sequencers. Finally,
-      <link linkend="future_directions">Chapter 6</link>
-      wraps things up with a discussion about the future of JBoss DNA.
-    </para>
-  </chapter>
-  <chapter id="jboss_dna">
-    <title>Understanding JBoss DNA</title>
-    <sect1 id="jboss_dna_overview">
-      <title>Overview</title>
-      <para>JBoss DNA is a repository and set of tools that make it easy to capture, version, analyze, and understand the
-        fundamental building blocks of information. As models, service and process definitions, schemas, source code, and other
-        artifacts are added to the repository, JBoss DNA "sequences" the makeup of these components and extracts their structure
-        and interdependencies. The JBoss DNA web application allows end users to access, visualize, and edit this information in
-        the terminology and structure they are familiar with. Such domain-specific solutions can be easily created with little or
-        no programming.</para>
-      <para> JBoss DNA supports the Java Content Repository (JCR) standard and is able to provide a single integrated view of
-        multiple repositories, external databases, services, and applications, ensuring that JBoss DNA has access to the latest
-        and most reliable master data. For instance, DNA could provide in a single view valuable insight into the business
-        processes and process-level services impacted by a change to in an intermediary web server operation defined via WSDL.
-        Similarly, a user could quickly view and navigate the dependencies between the data source models and transformation
-        information stored within a content repository, the code base stored within a version control system, and the database
-        schemas used by an application.</para>
-    </sect1>
-    <sect1 id="architecture">
-      <title>Architecture</title>
-      <para>The architecture for JBoss DNA consists of several major components that will be built on top of standard APIs,
-        including JCR, JDBC, JNDI and HTTP. The goal is to allow these components to be assembled as needed and add value on top
-        of other DNA components or third-party systems that support these standard APIs.</para>
-      <mediaobject>
-        <imageobject role="fo">
-          <imagedata align="center" fileref="images/dna-architecture.png" />
-        </imageobject>
-        <imageobject role="html">
-          <imagedata align="center" fileref="images/dna-architecture.png" />
-        </imageobject>
-      </mediaobject>
-      <para>
-        As shown in the diagram above, the major components are (starting at the top):
-        <itemizedlist>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Eclipse Plugins</emphasis>
-              enable Eclipse users to access the contents of a JBoss DNA repository.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA JDBC Driver</emphasis>
-              provides a driver implementation, allowing JDBC-aware applications to connect to and use a JBoss DNA repository.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Remote JCR</emphasis>
-              is a client-side component for accessing remote JCR repositories.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Web Application</emphasis>
-              is used by end users and domain experts to visualize, search, edit, change and tag the repository content. The web
-              application uses views to define how different types of information are to be presented and edited in
-              domain-specific ways. The goal is that this web application is easily customized and branded for inclusion into
-              other solutions and application systems. The DNA Web Application operates upon any JCR-compliant repository,
-              although it does rely upon the DNA analysis and templating services.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Publishing Server</emphasis>
-              allows content to be downloaded, uploaded, and edited using the Atom Publishing Protocol. With the DNA Publishing
-              Server, the content of the repository can easily be created, read, edited, and deleted using the standard HTTP
-              operations of POST, GET, PUT, and DELETE (respectively). More and more tools are being created that support working
-              with Atom Publishing servers. The DNA Publishing Server operates upon any JCR-compliant repository.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA WebDAV Server</emphasis>
-              allows clients such as Microsoft Windows and Apple OS X to connect to, read, and edit the content in the repository
-              using the WebDAV standard. Since WebDAV is an extension of HTTP, web browsers are able to read (but not modify) the
-              content served by a WebDAV compliant server. The DNA WebDAV Server operates upon any JCR-compliant repository.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Sequencers</emphasis>
-              are pluggable components that make it possible for content to be uploaded to the repository and automatically
-              processed to extract meaningful structure and place that structure in the repository. Once this information is in
-              the repository, it can be viewed, edited, analyzed, searched, and related to other content. DNA defines a Java
-              interface that sequencers must implement. DNA sequencers operate upon any JCR-compliant repository.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Analyses</emphasis>
-              are pluggable components that analyze content and the relationships between content to generate reports or to answer
-              queries. DNA will include some standard analyzers, like dependency analysis and similarity analysis, that are
-              commonly needed by many different solutions. DNA analyzers operate upon any JCR-compliant repository.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Views</emphasis>
-              are definitions of how types of information are to be presented in a user interface to allow for creation, reading,
-              editing, and deletion of information. DNA view definitions consist of data stored in a JCR repository, and as such
-              views can be easily added, changed or removed entirely by using the DNA Web Application, requiring no programming.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Federation</emphasis>
-              is an implementation of the JCR API that builds the content within the repository by accessing and integrating
-              information from multiple sources. DNA Federation allows the integration of external systems, like other JCR
-              repositories, databases, applications, and services.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Connectors</emphasis>
-              are used to communicate with these external sources of information. In the federation engine, each source is able to
-              contribute node structure and node properties to any part of the federated graph, although typically many connectors
-              will contribute most of their information to isolated subgraphs. The result is that integration from a wide range of
-              systems can be integrated and accessed through the DNA Web Application, DNA Publishing Server, and DNA WebDAV
-              Server. Connectors also may optionally participate in distributed transactions by exposing an XAResource.
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">DNA Maven</emphasis>
-              is a classloader library compatible with Maven 2 project dependencies. This allows the creation of Java ClassLoader
-              instances using Maven 2 style paths, and all dependencies are transitively managed and included.
-            </para>
-          </listitem>
-        </itemizedlist>
-      </para>
-      <para>
-        Continue reading the rest of this chapter for more detail about the
-        <link linkend="sequencers">sequencing framework</link>
-        available in this release, or the
-        <link linkend="federation">federation engine</link>
-        and
-        <link linkend="federation_connectors">connectors</link>
-        that will be the focus of the next release. Or, skip to the
-        <link linkend="downloading_and_running">examples</link>
-        to see how to start using JBoss DNA &versionNumber;
-        today. 
-      </para>
-    </sect1>
-    <sect1 id="sequencers">
-      <title>Sequencing content</title>
-      <para> The current JBoss DNA release contains a sequencing framework that is designed to sequence data (typically files)
-        stored in a JCR repository to automatically extract meaningful and useful information. This additional information is then
-        saved back into the repository, where it can be accessed and used.</para>
-      <para> In other words, you can just upload various kinds of files into a JCR repository, and DNA automatically processes
-        those files to extract meaningful structured information. For example, load DDL files into the repository, and let
-        sequencers extract the structure and metadata for the database schema. Load Hibernate configuration files into the
-        repository, and let sequencers extract the schema and mapping information. Load Java source into the repository, and let
-        sequencers extract the class structure, JavaDoc, and annotations. Load a PNG, JPEG, or other image into the repository,
-        and let sequencers extract the metadata from the image and save it in the repository. The same with XSDs, WSDL, WS
-        policies, UML, MetaMatrix models, etc.</para>
-      <para>
-        JBoss DNA sequencers sit on top of existing JCR repositories (including federated repositories) - they basically extract
-        more useful information from what's already stored in the repository. And they use the existing JCR versioning system. Each
-        sequencer typically processes a single kind of file format or a single kind of content. </para>
-      <para>The following sequencers are included in JBoss DNA:
-        <itemizedlist>
-          <listitem>
-            <para>
-              <emphasis role="strong">Image sequencer</emphasis>
-              - A sequencer that processes the binary content of an image file, extracts the metadata for the image, and then
-              writes that image metadata to the repository. It gets the file format, image resolution, number of bits per pixel
-              (and optionally number of images), comments and physical resolution from JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM,
-              PGM, PPM, and PSD files. (This sequencer may be improved in the future to also extract EXIF metadata from JPEG
-              files; see
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
-              .)
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">MP3 sequencer</emphasis>
-              - A sequencer that processes the contents of an MP3 audio file, extracts the metadata for the file, and then
-              writes that image metadata to the repository. It gets the title, author, album, year, and comment.  
-              (This sequencer may be improved in the future to also extract other ID3 metadata from other audio file formats; see
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-66">DNA-26</ulink>
-              .)
-            </para>
-          </listitem>
-        </itemizedlist>
-      </para>
-      <para>
-        As the community develops additional sequencers, they will also be included in JBoss DNA. Some of those that have been
-        identified as being useful include:
-        <itemizedlist>
-          <listitem>
-            <para>
-              <emphasis role="strong">XML Schema Document (XSD) Sequencer</emphasis>
-              - Process XSD files and extract the various elements, attributes, complex types, simple types, groups, and other
-              information. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-32">DNA-32</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">Web Service Definition Language (WSDL) Sequencer</emphasis>
-              - Process WSDL files and extract the services, bindings, ports, operations, parameters, and other information. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-33">DNA-33</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">Hibernate File Sequencer</emphasis>
-              - Process Hibernate configuration (cfg.xml) and mapping (hbm.xml) files to extract the configuration and mapping
-              information. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-61">DNA-61</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">XML Metadata Interchange (XMI) Sequencer</emphasis>
-              - Process XMI documents that contain UML models or models using another metamodel, extracting the model structure
-              into the repository. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-31">DNA-31</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">ZIP Archive Sequencer</emphasis>
-              - Process ZIP archive files to extract (explode) the contents into the repository. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-63">DNA-63</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">Java Archive (JAR) Sequencer</emphasis>
-              - Process JAR files to extract (explode) the contents into the classes and file resources. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-64">DNA-64</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">Java Class File Sequencer</emphasis>
-              - Process Java class files (bytecode) to extract the class structure (including annotations) into the repository.
-              (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-62">DNA-62</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">Java Source File Sequencer</emphasis>
-              - Process Java source files to extract the class structure (including annotations) into the repository. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-51">DNA-51</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">PDF Sequencer</emphasis>
-              - Process PDF files to extract the document metadata, including table of contents. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-50">DNA-50</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">Maven 2 POM Sequencer</emphasis>
-              - Process Maven 2 Project Object Model (POM) files to extract the project information, dependencies, plugins, and
-              other content. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-24">DNA-24</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">Data Definition Language (DDL) Sequencer</emphasis>
-              - Process various dialects of DDL, including that from Oracle, SQL Server, MySQL, PostgreSQL, and others. May need
-              to be split up into a different sequencer for each dialect. (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
-              )
-            </para>
-          </listitem>
-          <listitem>
-            <para>
-              <emphasis role="strong">MP3 and MP4 Sequencer</emphasis>
-              - Process MP3 and MP4 audio files to extract the name of the song, artist, album, track number, and other metadata.
-              (See
-              <ulink url="http://jira.jboss.org/jira/browse/DNA-30">DNA-30</ulink>
-              )
-            </para>
-          </listitem>
-        </itemizedlist>
-      </para>
-      <para>
-        The
-        <link linkend="using_dna">examples</link>
-        in this book go into more detail about how sequencers are managed and used, and
-        <link linkend="custom_sequencers">Chapter 5</link>
-        goes into detail about how to write custom sequencers.
-      </para>
-    </sect1>
-    <sect1 id="federation">
-      <title>Federating content</title>
-      <para>There is a lot of information stored in many of different places: databases, repositories, SCM systems,
-        registries, file systems, services, etc. The purpose of the federation engine is to allow applications to use the JCR API
-        to access that information as if it were all stored in a single JCR repository, but to really leave the information where
-        it is.</para>
-      <para>Why not just move the information into a JCR repository? Most likely there are existing applications that rely upon
-        that information being where it is. If we were to move it, then all those applications would break. Or they'd have to be
-        changed to use JCR. If the information is being used, the most practical thing is to leave it where it is.</para>
-      <para>
-        Then why not just copy the information into a JCR repository? Actually, there are times when it's perfectly reasonable to
-        make a copy of the data. Perhaps the system managing the existing information cannot handle the additional load of more
-        clients. Or, perhaps the information doesn't change, or it does change and we want snapshots that don't change. But more
-        likely, the data
-        <emphasis>does</emphasis>
-        change. So if applications are to use the most current information and we make copies of the data, we have to keep the
-        copies synchronized with the master. That's generally a lot of work.
-      </para>
-      <para>The JBoss DNA federation engine lets us leave the information where it is, yet lets client applications use the JCR
-        API to access all the information without caring where the information really exists. If the underlying information
-        changes, client applications using JCR observation will be notified of the changes. If a JBoss DNA federated repository is
-        configured to allow updates, client applications can change the information in the repository and JBoss DNA will propagate
-        those changes down to the original source.</para>
-      <sect2 id="federation_connectors">
-        <title>Connecting to information sources</title>
-        <para>
-          The JBoss DNA federation engine will use connectors to interact with different information sources to get at the content
-          in those systems. Some ideas for connectors include:
-          <itemizedlist>
-            <listitem>
-              <para>
-                <emphasis role="strong">JCR Repository Connector</emphasis>
-                - Connect to and interact with other JCR repositories.
-              </para>
-            </listitem>
-            <listitem>
-              <para>
-                <emphasis role="strong">File System Connector</emphasis>
-                - Expose the files and directories on a file system through JCR.
-              </para>
-            </listitem>
-            <listitem>
-              <para>
-                <emphasis role="strong">Maven 2 Repository Connector</emphasis>
-                - Access and expose the contents of a Maven 2 repository (either on the local file system or via HTTP) through
-                JCR.
-              </para>
-            </listitem>
-            <listitem>
-              <para>
-                <emphasis role="strong">JDBC Metadata Connector</emphasis>
-                - Connect to relational databases via JDBC and expose their schema as content in a repository.
-              </para>
-            </listitem>
-            <listitem>
-              <para>
-                <emphasis role="strong">UDDI Connector</emphasis>
-                - Interact with UDDI registries to integrate their content into a repository.
-              </para>
-            </listitem>
-            <listitem>
-              <para>
-                <emphasis role="strong">SVN Connector</emphasis>
-                - Interact with Subversion software configuration management (SCM) repositories to expose the managed resources
-                through JCR. Consider using the
-                <ulink url="http://svnkit.com/">SVNkit</ulink>
-                (dual license) library for an API into Subversion.
-              </para>
-            </listitem>
-            <listitem>
-              <para>
-                <emphasis role="strong">CVS Connector</emphasis>
-                - Interact with CVS software configuration management (SCM) repositories to expose the managed resources through
-                JCR.
-              </para>
-            </listitem>
-            <listitem>
-              <para>
-                <emphasis role="strong">JDBC Storage Connector</emphasis>
-                - Store and access information in a relational database. Also useful for persisting information in the federated
-                repository not stored elsewhere.
-              </para>
-            </listitem>
-            <listitem>
-              <para>
-                <emphasis role="strong">Distributed Database Connector</emphasis>
-                - Store and access information in a
-                <ulink url="http://www.hypertable.org/">Hypertable</ulink>
-                or
-                <ulink url="http://hadoop.apache.org/hbase/">HBase</ulink>
-                distributed databases. Also useful for persisting information in the federated repository not stored elsewhere.
-              </para>
-            </listitem>
-          </itemizedlist>
-        </para>
-        <para>
-          If the connectors allow the information they contribute to be updated, they must provide an
-          <code>XAResource</code>
-          implementation that can be used with a Java Transaction Service. Connectors that provide read-only access need not
-          provide an implementation.
-        </para>
-        <para>
-          Also, connectors talk to
-          <emphasis>sources</emphasis>
-          of information, and it's quite likely that the same connector is used to talk to different sources. Each source contains
-          the configuration details (e.g., connection information, location, properties, options, etc.) for working with that
-          particular source, as well as a reference to the connector that should be used to establish connections to the source.
-          And of course, sources can be added or removed without having to stop and restart the federated repository.
-        </para>
-      </sect2>
-      <sect2 id="federation_graph">
-        <title>Building the unified graph</title>
-        <para> The federation engine works by effectively building up a single graph by querying each source and merging or
-          unifying the responses. This information is cached, which improves performance, reduces the number of (potentially
-          expensive) remote calls, reduces the load on the sources, and helps mitigate problems with source availability. As
-          clients interact with the repository, this cache is consulted first. When the requested portion of the graph (or
-          "subgraph") is contained completely in the cache, it is retuned immediately. However, if any part of the requested
-          subgraph is not in the cache, each source is consulted for their contributions to that subgraph, and any results are
-          cached.</para>
-        <para> This basic flow makes it possible for the federated repository to build up a local cache of the integrated graph
-          (or at least the portions that are used by clients). In fact, the federated repository caches information in a manner
-          that is similar to that of the Domain Name System (DNS). As sources are consulted for their contributions, the source
-          also specifies whether it is the authoritative source for this information (some sources that are themselves federated
-          may not be the information's authority), whether the information may be modified, the time-to-live (TTL) value (the time
-          after which the cached information should be refreshed), and the expiration time (the time after which the cached
-          information is no longer valid). In effect, the source has complete control over how the information it contributes is
-          cached and used.</para>
-        <para>
-          The federated repository also needs to incorporate
-          <emphasis>negative caching</emphasis>
-          , which is storage of the knowledge that something does not exist. Sources can be configured to contribute information
-          only below certain paths (e.g.,
-          <code>/A/B/C</code>
-          ), and the federation engine can take advantage of this by never consulting that source for contributions to information
-          on other paths. However, below that path, any negative responses must also be cached (with appropriate TTL and expiry
-          parameters) to prevent the exclusion of that source (in case the source has information to contribute at a later time)
-          or the frequent checking with the source.
-        </para>
-      </sect2>
-      <sect2 id="federation_queries">
-        <title>Searching and querying</title>
-        <para> The JBoss DNA federated repository will also support queries against the integrated and unified graph. In some
-          situations the query can be determined to apply to a single source, but in most situations the query must be planned
-          (and possibly rewritten) such that it can be pushed down to all the appropriate sources. Also, the cached results must
-          be consulted prior to returning the query results, as the results from one source might have contributions from another
-          source.</para>
-        <note>
-          <para> It is hoped that the MetaMatrix query engine can be used for this purpose after it is open-sourced. This engine
-            implements sophisticated query planning and optimization techniques for working efficiently with multiple sources.
-          </para>
-        </note>
-        <para>Searching the whole federated repository is also important. This allows users to simply supply a handful of
-          search terms, and to get results that are ranked based upon how close each result is to the search terms. (Searching is
-          very different from querying, which involves specifying the exact semantics of what is to be searched and how the
-          information is to be compared.) JBoss DNA will incorporate a search engine (e.g., likely to be Lucene) and will populate
-          the engine's indexes using the federated content and the cached information. Notifications of changing information will
-          be reflected in the indexes, but some sources may want to explicitly allow or disallow periodic crawling of their
-          content.</para>
-      </sect2>
-      <sect2 id="federation_updates">
-        <title>Updating content</title>
-        <para>
-          The JBoss DNA federated repositories also make it possible for client applications to make changes to the unified graph
-          within the context of distributed transactions. According to the JCR API, client applications use the Java Transaction
-          API (JTA) to control the boundaries of their transactions. Meanwhile, the federated repository uses a
-          <ulink url="http://www.jboss.org/jbosstm/">distributed transaction service</ulink>
-          to coordinate the XA resources provided by the connectors.
-        </para>
-        <para> It is quite possible that clients add properties to nodes in the unified graph, and that this information cannot be
-          handled by the same underlying source that contributed to the node. In this case, the federated repository can be
-          configured with a fallback source that will be used used to store this "extra" information.</para>
-        <para>
-          It is a goal that non-XA sources (i.e., sources that use connectors without XA resources) can participate in distributed
-          transactions through the use of
-          <emphasis>compensating transactions</emphasis>
-          . Because the JBoss DNA federation engine implements the JCR observation system, it is capable of recording all of the
-          changes made to the distributed graph (and those changes sent to each updatable source). Therefore, if a non-XA source
-          is involved in a distributed transaction that must be rolled back, any changes made to non-XA sources can be undone. (Of
-          course, this does not make the underlying source transactional: non-transactional sources still may expose the interim
-          changes to other clients.)
-        </para>
-      </sect2>
-      <sect2 id="federation_events">
-        <title>Observing changes</title>
-        <para> The JCR API supports observing a repository to receive notifications of additions, changes and deletions of nodes
-          and properties. The JBoss DNA federated repository will support this API through two primary means.</para>
-        <para> When the changes are made through the federated repository, the JBoss DNA federation engine is well aware of the
-          set of changes that have been (or are being) made to the unified graph. These events are directly propagated to
-          listeners.</para>
-        <para> Sources have the ability to publish events, making it possible for the JBoss DNA federation engine and clients that
-          have registered listeners to be notified of changes in the information managed by that source. These events are first
-          processed by the federation engine and possibly altered based upon contributions from other sources. (The federation
-          engine also uses these events to update or purge information in the cache, which may add to the event set.) The
-          resulting (and possibly altered) event set is then sent to all client listeners.</para>
-      </sect2>
-    </sect1>
-  </chapter>
-  <!--  ====================================================================================================
-                                                   Chapter 
-        ====================================================================================================   -->
-  <chapter id="downloading_and_running">
-    <title>Running the example application</title>
-    <para>
-      This chapter provides instructions for downloading and running a sample application that demonstrates how JBoss DNA works
-      with a JCR repository to automatically sequence changing content to extract useful information. So read on to get the simple
-      application running, and then in the
-      <link linkend="using_dna">next chapter</link>
-      we'll dive into the source code for the example and show how to use JBoss DNA in your own applications.
-    </para>
-    <para>JBoss DNA uses Maven 2 for its build system, as is this example. Using Maven 2 has several advantages, including
-      the ability to manage dependencies. If a library is needed, Maven automatically finds and downloads that library, plus
-      everything that library needs. This means that it's very easy to build the examples - or even create a maven project that
-      depends on the JBoss DNA JARs.</para>
-    <note>
-      <para>
-        To use Maven with JBoss DNA, you'll need to have
-        <ulink url="http://java.sun.com/javase/downloads/index_jdk5.jsp">JDK 5 or 6</ulink>
-        and Maven 2.0.7 (or higher).
-      </para>
-      <para>
-        Maven can be downloaded from
-        <ulink url="http://maven.apache.org/">http://maven.apache.org/</ulink>
-        , and is installed by unzipping the
-        <code>maven-2.0.7-bin.zip</code>
-        file to a convenient location on your local disk. Simply add
-        <code>$MAVEN_HOME/bin</code>
-        to your path and add the following profile to your
-        <code>~/.m2/settings.xml</code>
-        file:
-        <programlisting role="XML" language="xml">&lt;settings&gt;
-  &lt;profiles&gt;
-    &lt;profile&gt;
-      &lt;id&gt;jboss.repository&lt;/id&gt;
-      &lt;activation&gt;
-        &lt;property&gt;          
-          &lt;name&gt;!jboss.repository.off&lt;/name&gt;
-        &lt;/property&gt;
-      &lt;/activation&gt;
-      &lt;repositories&gt;
-        &lt;repository&gt;
-          &lt;id&gt;snapshots.jboss.org&lt;/id&gt;
-          &lt;url&gt;http://snapshots.jboss.org/maven2&lt;/url&gt;
-          &lt;snapshots&gt;
-            &lt;enabled&gt;true&lt;/enabled&gt;
-          &lt;/snapshots&gt;
-        &lt;/repository&gt;
-        &lt;repository&gt;
-          &lt;id&gt;repository.jboss.org&lt;/id&gt;
-          &lt;url&gt;http://repository.jboss.org/maven2&lt;/url&gt;
-          &lt;snapshots&gt;
-            &lt;enabled&gt;false&lt;/enabled&gt;
-          &lt;/snapshots&gt;
-        &lt;/repository&gt;
-      &lt;/repositories&gt;
-      &lt;pluginRepositories&gt;
-        &lt;pluginRepository&gt;
-          &lt;id&gt;repository.jboss.org&lt;/id&gt;
-          &lt;url&gt;http://repository.jboss.org/maven2&lt;/url&gt;
-          &lt;snapshots&gt;
-            &lt;enabled&gt;false&lt;/enabled&gt;
-          &lt;/snapshots&gt;
-        &lt;/pluginRepository&gt;
-        &lt;pluginRepository&gt;
-          &lt;id&gt;snapshots.jboss.org&lt;/id&gt;
-          &lt;url&gt;http://snapshots.jboss.org/maven2&lt;/url&gt;
-          &lt;snapshots&gt;
-            &lt;enabled&gt;true&lt;/enabled&gt;
-          &lt;/snapshots&gt;
-        &lt;/pluginRepository&gt;
-      &lt;/pluginRepositories&gt;
-    &lt;/profile&gt;
-  &lt;/profiles&gt;
-&lt;/settings&gt;</programlisting>
-        This profile informs Maven of the two JBoss repositories (snapshots and releases) that contain 
-        all of the JARs for JBoss DNA and all dependent libraries.</para>
-      </note>
-    <sect1 id="downloading">
-      <title>Downloading and compiling</title>
-      <para>The next step is to <ulink url="http://www.jboss.org/file-access/default/members/dna/downloads/0.1/jboss-dna-0.1-gettingstarted-examples.zip">download</ulink>
-      the example for this Getting Started guide, and extract the contents to a convenient location on your local disk.
-      You'll find the example contains the following files, which are organized according to the standard Maven directory structure:
-  <programlisting>
-examples/pom.xml
-         sequencers/pom.xml
-                   /src/main/assembly
-                            /config
-                            /java
-                            /resources
-                       /test/java
-                            /resources
-  </programlisting>
-      </para>
-      <para>There are essentially two Maven projects: a <code>sequencers</code> project and a parent project.  All of the source
-      for the example is located in the <code>sequencers</code> subdirectory.  And you may have noticed that none
-      of the JBoss DNA libraries are there.  This is where Maven comes in.  The two <code>pom.xml</code> files tell
-      Maven everything it needs to know about what libraries are required and how to build the example.</para>
-      <para>In a terminal, go to the <code>examples</code> directory and run <emphasis role="strong"><code>mvn install</code></emphasis>.  
-      This command downloads all of the JARs necessary to compile and build the example, including the JBoss DNA libraries,
-      the libraries they depend on, and any missing Maven components.  (These are downloaded from the JBoss repositories
-      only once and saved on your machine.  This means that the next time you run Maven, all the libraries will
-      already be available locally, and the build will run much faster.)  The command then continues by compiling the example's source
-      code (and unit tests) and running the unit tests.  The build is successful if you see the following:
-           <programlisting language="bash">$ mvn install
-...
-[INFO] ------------------------------------------------------------------------
-[INFO] Reactor Summary:
-[INFO] ------------------------------------------------------------------------
-[INFO] Getting Started examples .............................. SUCCESS [2.106s]
-[INFO] Sequencer Examples .................................... SUCCESS [9.768s]
-[INFO] ------------------------------------------------------------------------
-[INFO] ------------------------------------------------------------------------
-[INFO] BUILD SUCCESSFUL
-[INFO] ------------------------------------------------------------------------
-[INFO] Total time: 12 seconds
-[INFO] Finished at: Wed May 07 12:00:06 CDT 2008
-[INFO] Final Memory: 14M/28M
-[INFO] ------------------------------------------------------------------------
-$ </programlisting>
-      If there are errors, check whether you have the correct version of Maven installed and that you've correctly updated
-           your Maven settings as described above.</para>
-    <para>If you've successfully built the examples, there will be a <code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
-    directory that contains the following:
-    <itemizedlist>
-  	<listitem>
-  	  <para><emphasis role="strong"><code>run.sh</code></emphasis> is the *nix shell script that will run the example.</para>
-      </listitem>
-    <listitem>
-      <para>
-        <emphasis role="strong">
-          <code>log4j.properties</code>
-        </emphasis>
-        is the Log4J configuration file.
-      </para>
-    </listitem>
-    <listitem>
-      <para>
-        <emphasis role="strong">
-          <code>jackrabbitConfig.xml</code>
-        </emphasis>
-        is the Jackrabbit configuration file, which is set up to use a transient in-memory repository.
-      </para>
-    </listitem>
-    <listitem>
-      <para>
-        <emphasis role="strong">
-          <code>jackrabbitNodeTypes.cnd</code>
-        </emphasis>
-        defines the additional JCR node types used by this example.
-      </para>
-    </listitem>
-    <listitem>
-      <para>
-        <emphasis role="strong">
-          <code>sample1.mp3</code>
-        </emphasis>
-        is a sample MP3 audio file you'll use later to upload into the repository.
-      </para>
-    </listitem>
-    <listitem>
-      <para>
-        <emphasis role="strong">
-          <code>caution.gif</code>
-        </emphasis>, <emphasis role="strong">
-          <code>caution.png</code>
-        </emphasis>, and <emphasis role="strong">
-          <code>caution.jpg</code>
-        </emphasis>
-        are images that you'll use later and upload into the repository.
-      </para>
-    </listitem>
-    <listitem>
-      <para>
-        <emphasis role="strong">
-          <code>lib</code>
-        </emphasis>
-        subdirectory contains the JARs for all of the JBoss DNA artifacts as well as those for other libraries required
-    by JBoss DNA and the example.
-      </para>
-    </listitem>
-    </itemizedlist>
-    <note>
-      <para>JBoss DNA 0.1 and the examples are currently tested with <ulink url="http://jackrabbit.apache.org/">Apache Jackrabbit</ulink> version 1.3.3.  
-      This version is stable and used by a number of other projects and applications.  However, you should be able to use a newer
-      version of Jackrabbit, as long as that version uses the same JCR API.  For example, version 1.4.2 was released on March 26, 2008 and
-      should be compatible.
-      </para>
-      <para>Just remember, if the version of Jackrabbit you want to use for these examples is not in the Maven repository,
-      you'll have to either add it or add it locally.  For more information, see the <ulink url="http://maven.apache.org/">Maven documentation</ulink>.
-      </para>
-    </note>
-    </para>
-  </sect1>
-  <sect1 id="running">
-    <title>Running the example</title>
-    <para>This example consists of a client application that sets up an in-memory JCR repository and that allows a user to
-      upload files into that repository. The client also sets up the DNA services with two sequencers so that if any of the
-      uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically extract the image's metadata (e.g., image
-      format, physical size, pixel density, etc.) and store that in the repository.  Alternatively, if the uploaded file 
-      is an MP3 audio file, DNA will extract some of the ID3 metadata (e.g., the author, title, album, year and comment)
-      and store that in the repository.</para>
-    <para>
-      To run the client application, go to the
-      <code>examples/sequencers/target/dna-example-sequencers-basic.dir/
-      </code>
-      directory and type
-      <code>./run.sh</code>
-      . You should see the command-line client and its menus in your terminal:
-      <figure id="xample-sequencer-cli-client">
-        <title>Example Client</title>
-        <graphic align="center" scale="100" fileref="images/example-sequencer-cli-client.png" />
-      </figure>
-      From this menu, you can upload a file into the repository, search for media in the repository, print sequencing statistics,
-      or quit the application.
-    </para>
-    <para>
-      The first step is to upload one of the example images. If you type 'u' and press return, you'll be prompted to supply the
-      path to the file you want to upload. Since the application is running from within the
-      <code>examples/sequencers/target/dna-example-sequencers-basic.dir/
-      </code>
-      directory, you can specify any of the files in that directory without specifying the path:
-      <figure id="example-sequencer-upload">
-        <title>Uploading an image using the Example Client</title>
-        <graphic align="center" scale="100" fileref="images/example-sequencer-upload.png" />
-      </figure>
-      You can specify any fully-qualified or relative path. The application will notify you if it cannot find the file you
-      specified. The example client configures JBoss DNA to sequence and MP3 audio files and image files with one of
-      the following extensions (technically, nodes that have names ending in the following):
-      <code>jpg</code>
-      ,
-      <code>jpeg</code>
-      ,
-      <code>gif</code>
-      ,
-      <code>bmp</code>
-      ,
-      <code>pcx</code>
-      ,
-      <code>png</code>
-      ,
-      <code>iff</code>
-      ,
-      <code>ras</code>
-      ,
-      <code>pbm</code>
-      ,
-      <code>pgm</code>
-      ,
-      <code>ppm</code>
-      , and
-      <code>psd</code>
-      . Files with other extensions in the repository path will be ignored. For your convenience, the example provides several
-      files that will be sequenced (
-      <code>caution.png</code>
-      ,
-      <code>caution.jpg</code>
-      ,
-      <code>caution.gif</code>
-      , and
-      <code>sample1.mp3</code>
-      ) and one image that will not be sequenced (
-      <code>caution.pict</code>
-      ). Feel free to try other files.
-    </para>
-    <para>
-      After you have specified the file you want to upload, the example application asks you where in the repository you'd like to
-      place the file. (If you want to use the suggested location, just press
-      <code>return</code>
-      .) The client application uses the JCR API to upload the file to that location in the repository, creating any nodes (of
-      type
-      <code>nt:folder</code>
-      ) for any directories that don't exist, and creating a node (of type
-      <code>nt:file</code>
-      ) for the file. And, per the JCR specification, the application creates a
-      <code>jcr:content</code>
-      node (of type
-      <code>nt:resource</code>
-      ) under the file node. The file contents are placed on this
-      <code>jcr:content</code>
-      node in the
-      <code>jcr:data</code>
-      property. For example, if you specify
-      <code>/a/b/caution.png</code>
-      , the following structure will be created in the repository:<programlisting>
-    /a   (nt:folder)
-      /b   (nt:folder)
-        /caution.png   (nt:file)
-                    /jcr:content    (nt:resource)
-                                @jcr:data = {contents of the file}
-                                @jcr:mimeType = {mime type of the file}
-                                @jcr:lastModified = {now}
-    </programlisting>
-    Other kinds of files are treated in a similar way.
-    </para>
-  <para>
-    When the client uploads the file using the JCR API, DNA gets notified of the changes, consults the sequencers to see whether
-    any of them are interested in the new or updated content, and if so runs those sequencers. The image sequencer processes image
-    files for metadata, and any metadata found is stored under the
-    <code>/images</code>
-    branch of the repository. The MP3 sequencer processes MP3 audio files for metadata, and any metadata found is stored under the
-    <code>/mp3s</code>
-    branch of the repository.  All of this happens asynchronously, so any DNA activity doesn't impede or slow down the client
-    activities.
-  </para>
-  <para>
-    So, after the file is uploaded, you can search the repository for the image metadata using the "s" menu option:
-    <figure id="example-sequencer-search">
-      <title>Searching for media using the Example Client</title>
-      <graphic align="center" scale="100" fileref="images/example-sequencer-search.png" />
-    </figure>
-    Here are the search results after the <code>sample1.mp3</code> audio file has been uploaded (to the <code>/a/b/sample1.mp3</code> location):
-    <figure id="example-sequencer-search-with-mp3">
-      <title>Searching for media using the Example Client</title>
-      <graphic align="center" scale="100" fileref="images/example-sequencer-search-with-mp3.png" />
-    </figure>
-    You can also display the sequencing statistics using the "d" menu option:
-    <figure id="example-sequencer-statistics">
-      <title>Sequencing statistics using the Example Client</title>
-      <graphic align="center" scale="100" fileref="images/example-sequencer-statistics.png" />
-    </figure>
-    These stats show how many nodes were sequenced, and how many nodes were skipped because they didn't apply to the sequencer's
-    criteria.
-  </para>
-  <note>
-    <para>
-      There will probably be more nodes skipped than sequenced, since there are more
-      <code>nt:folder</code>
-      and
-      <code>nt:resource</code>
-      nodes than there are
-      <code>nt:file</code>
-      nodes with acceptable names.
-    </para>
-  </note>
-  <para>You can repeat this process with other files. Any file that isn't an image or MP3 files (as recognized by the sequencing configurations
-    that we'll describe later) will not be sequenced.</para>
-  </sect1>
-  <sect1 id="downloading_and_running_review">
-    <title>Summarizing what we just did</title>
-    <para>In this chapter you downloaded and installed the example application and used it to upload files into a
-    JCR repository.  JBoss DNA automatically sequenced the image and/or MP3 files you uploaded, extracted the metadata from the
-    files, and stored that metadata inside the repository.  The application allowed you to see this metadata
-    and the sequencing statistics.</para>
-    <para>This application was very simplistic.  In fact, running through the example probably only took you a minute or two.
-    So while this application won't win any awards, it does show the basics of what JBoss DNA can do.</para>
-    <para>In the <link linkend="using_dna">next chapter</link> we'll venture into the code to get an understanding
-    of how JBoss DNA actually works and how you can use it in your own applications.</para>
-  </sect1>
-  </chapter>
-  
-  <!--  ====================================================================================================
-                                                   Chapter 
-        ====================================================================================================   -->
-<chapter id="using_dna">
-  <title>Using JBoss DNA</title>
-  <para>As we've mentioned before, JBoss DNA is able to work with existing JCR repositories.  Your client applications
-  make changes to the information in those repositories, and JBoss DNA automatically uses its sequencers to extract
-  additional information from the uploaded files.</para>
-  <note>
-    <para>Configuring JBoss DNA sequencers is a bit more manual than is ideal. As you'll see, JBoss DNA uses dependency
-      injection to allow a great deal of flexibility in how it can be configured and customized. However, the next release will
-      provide a much easier mechanism for configuring not only the sequencer service but also the upcoming federation engine and
-      JCR implementation.</para>
-  </note>
-  <sect1 id="sequencing_service">
-    <title>Configuring the Sequencing Service</title>
-    <para>
-      The JBoss DNA <emphasis>sequencing service</emphasis> is the component that manages the <emphasis>sequencers</emphasis>
-      , reacting to changes in JCR repositories and then running the appropriate sequencers.
-      This involves processing the changes on a node, determining which (if any) sequencers should be run on that node,
-      and for each sequencer constructing the execution environment, calling the sequencer, and saving the information
-      generated by the sequencer.</para>
-    <para>To set up the sequencing service, an instance is created, and dependent components are injected into
-      the object.  This includes among other things:
-      <itemizedlist>
-        <listitem>
-          <para>An <emphasis>execution context</emphasis> that defines the context in which the service runs, including
-        a factory for JCR sessions given names of the repository and workspace.  This factory must be configured,
-        and is how JBoss DNA knows about your JCR repositories and how to connect to them.  More on this a bit later.</para>
-        </listitem>
-        <listitem>
-          <para>An optional <emphasis>factory for class loaders</emphasis> used to load sequencers.  If no factory is supplied,
-        the service uses the current thread's context class loader (or if that is null, the class loader that loaded the
-        sequencing service class).</para>
-        </listitem>
-        <listitem>
-          <para>An <code>java.util.concurrent.ExecutorService</code> used to execute the sequencing activites.  If none
-        is supplied, a new single-threaded executor is created by calling <code>Executors.newSingleThreadExecutor()</code>.
-        (This can easily be changed by subclassing and overriding the <code>SequencerService.createDefaultExecutorService()</code> method.)</para>
-        </listitem>
-        <listitem>
-          <para>Filters for sequencers and events.  By default, all sequencers are considered for "node added", "property added"
-        and "property changed" events.</para>
-        </listitem>
-      </itemizedlist>
-      </para>
-      <para>As mentioned above, the <code>ExecutionContext</code> provides access to a <code>SessionFactory</code> that is used
-      by JBoss DNA to establish sessions to your JCR repositories.  Two implementations are available:
-      <itemizedlist>
-        <listitem>
-          <para>The <code>JndiSessionFactory</code> looks up JCR <code>Repository</code> instances in JNDI using
-          names that are supplied when creating sessions.  This implementation also has methods to set the
-          JCR <code>Credentials</code> for a given workspace name.</para>
-        </listitem>
-        <listitem>
-          <para>The <code>SimpleSessionFactory</code> has methods to register the JCR <code>Repository</code> instances
-          with names, as well as methods to set the JCR <code>Credentials</code> for a given workspace name.</para>
-        </listitem>
-      </itemizedlist>
-      You can use the <code>SimpleExecutionContext</code> implementation of <code>ExecutionContext</code> and supply
-      a <code>SessionFactory</code> instance, or you can provide your own implementation.
-      </para>
-      <para>Here's an example of how to instantiate and configure the SequencingService:
-      <programlisting>
-SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
-sessionFactory.registerRepository("Main Repository", this.repository);
-Credentials credentials = new SimpleCredentials("jsmith", "secret".toCharArray());
-sessionFactory.registerCredentials("Main Repository/Workspace1", credentials);
-ExecutionContext executionContext = new SimpleExecutionContext(sessionFactory);
-
-// Create the sequencing service, passing in the execution context ...
-SequencingService sequencingService = new SequencingService();
-sequencingService.setExecutionContext(executionContext);</programlisting>
-      </para>
-      <para>After the sequencing service is created and configured, it must be started.  The SequencingService
-      has an <emphasis>administration object</emphasis> (that is an instance of <code>ServiceAdministrator</code>)
-      with <code>start()</code>, <code>pause()</code>, and <code>shutdown()</code> methods.  The latter method will 
-      close the queue for sequencing, but will allow sequencing operations already running to complete normally.
-      To wait until all sequencing operations have completed, simply call the <code>awaitTermination</code> method
-      and pass it the maximum amount of time you want to wait.</para>
-      <para>
-      <programlisting>
-sequencingService.getAdministrator().start();</programlisting>
-      </para>
-      <para>The sequencing service must also be configured with the sequencers that it will use.  This is done using the
-      <code>addSequencer(SequencerConfig)</code> method and passing a <code>SequencerConfig</code> instance that
-      you create.  Here's an example:
-      <programlisting>
-String name = "Image Sequencer";
-String desc = "Sequences image files to extract the characteristics of the image";
-String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
-String[] classpath = null; // Use the current classpath
-String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png))[*]/jcr:content[@jcr:data] => /images/$1"};
-SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
-sequencingService.addSequencer(imageSequencerConfig);
-
-name = "Mp3 Sequencer";
-desc = "Sequences mp3 files to extract the id3 tags of the audio file";
-classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
-String[] mp3PathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data] => /mp3s/$1"};
-SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname, classpath, mp3PathExpressions);
-sequencingService.addSequencer(mp3SequencerConfig);</programlisting>
-      This is pretty self-explanatory, except for the <code>classpath</code> and <code>pathExpression</code> parameters.
-      The classpath parameter defines the classpath that is passed to the class loader factory mentioned above.
-      Our sequencer is on the classpath, so we can simply use <code>null</code> here.
-      </para>
-      <para>The path expression is more complicated.  Sequencer path expressions are used by the sequencing service to
-      determine whether a particular changed node should be sequenced.  The expressions consist of two parts: a selection
-      criteria and an output expression.  Here's a simple example:
-      <programlisting>
-/a/b/c at title =&gt; /d/e/f</programlisting>
-      Here, the <code>/a/b/c at title</code> is the selection criteria that applies when the <code>/a/b/c</code> node has a <code>title</code> property
-      that is added or changed.  When the selection criteria matches a change event, the sequencer will be run
-      and any generated output will be inserted into the repository described by the output expression.  In this example,
-      the generated output would be placed at the <code>/d/e/f</code> node.
-      </para>
-      <note>
-        <para>Sequencer path expressions can be fairly complex and may use wildcards, specificy same-name sibling indexes,
-        provide optional and choice elements, and may capture parts of the selection criteria for use in the output expression.
-        The path expression used in the image sequencer configuration example above shows a more complex example:
-        <programlisting>
-//(*.(jpg|jpeg|gif|bmp|pcx|png))[*]/jcr:content[@jcr:data] => /images/$1</programlisting>
-        This uses "//" to select any node at any level in the repository whose name ends with "." and one of the extensions (e.g., ".jpg", ".jpeg", etc.)
-        and that has a child node named "jcr:content" that has a "jcr:data" property.  It also selects the file name
-        as the first capture group (the first set of parentheses) for use in the output expression.
-        In this example, any sequencer output is placed on a node with that same file name under the "/images" node.
-        </para>
-        <para></para>
-        <para>Other things are possible, too.  For example, the name of the repository/workspace (as used by the <code>SessionFactory</code>)
-        may be specified at the beginning of the select criteria and/or the output expression.  This means it's possible to place
-        the sequencer output in a different repository than the node being sequenced.</para>
-        <para>For more detail about sequencer path expressions, see the <code>org.jboss.dna.repository.sequencer.SequencerPathExpression</code>
-        class and the corresponding <code>org.jboss.dna.repository.sequencer.SequencerPathExpressionTest</code> test case.</para>
-      </note>
-      <para>After the service is started, it is ready to start reacting to changes in the repository.  But it first
-      must be wired to the repositories using a listener.  This is accomplished using the <code>ObservationService</code>
-      described in the <link linkend="observation_service">next section</link>.</para>
-  </sect1>
-  <sect1 id="observation_service">
-    <title>Configuring the Observation Service</title>
-    <para>The JBoss DNA <code>ObservationService</code> is responsible for listening to one or more JCR repositories
-    and multiplexing the events to its listeners.  Unlike JCR events, this framework embeds in the events the
-    name of the repository and workspace that can be passed to a <code>SessionFactory</code> to obtain a session
-    to the repository in which the change occurred.  This simple design makes it very easy for JBoss DNA to
-    concurrently work with multiple JCR repositories.</para>
-    <para>Configuring an observation service is pretty easy, especially if you reuse the same <code>SessionFactory</code>
-    supplied to the sequencing service.  Here's an example:
-    <programlisting>
-this.observationService = new ObservationService(sessionFactory);
-this.observationService.getAdministrator().start();</programlisting>
-    </para> 
-    <note>
-    <para>Both <code>ObservationService</code> and <code>SequencingService</code> implement
-    <code>AdministeredService</code>, which has a <code>ServiceAdministrator</code> used to start, pause, and shutdown the
-    service.  In other words, the lifecycle of the services are managed in the same way.</para>
-    </note>
-    <para>
-    After the observation service is started, listeners can be added.  The <code>SequencingService</code> implements the required
-    interface, and so it may be registered directly:
-    <programlisting>
-observationService.addListener(sequencingService);</programlisting>
-    </para>
-    <para>Finally, the observation service must be wired to monitor one of your JCR repositories.  This is done with
-    one of the <code>monitor(...)</code> methods:
-    <programlisting>
-int eventTypes = Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED;
-observationService.monitor("Main Repository/Workspace1", eventTypes);</programlisting>
-    </para>
-    <para>At this point, the observation service is listening to a JCR repository and forwarding the appropriate events
-    to the sequencing service, which will asynchronously process the changes and sequence the information added to or changed in the repository.
-    </para>
-  </sect1>
-  <sect1 id="shutting_down">
-    <title>Shutting down JBoss DNA services</title>
-    <para>The JBoss DNA services are utilizing resources and threads that must be released before your application is ready to shut down.
-    The safe way to do this is to simply obtain the <code>ServiceAdministrator</code> for each service (via the <code>getServiceAdministrator()</code> method)
-    and call <code>shutdown()</code>.  As previously mentioned, the shutdown method will simply prevent new work from being processed
-    and will not wait for existing work to be completed.  If you want to wait until the service completes all its work, you must wait
-    until the service terminates.  Here's an example that shows how this is done:
-    <programlisting>
-// Shut down the service and wait until it's all shut down ...
-sequencingService.getAdministrator().shutdown();
-sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-
-// Shut down the observation service ...
-observationService.getAdministrator().shutdown();
-observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);</programlisting>
-    </para>
-    <para>At this point, we've covered how to configure and use the JBoss DNA services in your application.
-    The next chapter goes back to the <link linkend="downloading_and_running">sample application</link> to show how all these pieces fit together.</para>
-  </sect1>
-  <sect1 id="example_application_review">
-    <title>Reviewing the example application</title>
-    <para>Recall that the example application consists of a client application that sets up an in-memory JCR repository and
-      that allows a user to upload files into that repository. The client also sets up the DNA services with an image sequencer so
-      that if any of the uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically extract the image's
-      metadata (e.g., image format, physical size, pixel density, etc.) and store that in the repository.  Or, if the client uploads
-      MP3 audio files, the title, author, album, year, and comment are extracted from the audio file and stored in the repository.</para>
-    <para>
-      The example is comprised of 3 classes and 1 interface, located in the
-      <code>src/main/java</code>
-      directory:
-      <programlisting>
-  org/jboss/example/dna/sequencers/ConsoleInput.java
-                                  /MediaInfo.java
-                                  /SequencingClient.java
-                                  /UserInterface.java</programlisting>
-    </para>
-    <para>
-      <code>SequencingClient</code>
-      is the class that contains the main application.
-      <code>MediaInfo</code>
-      is a simple Java object that encapsulates metadata about a media file (as generated by the sequencer), and used by the client to
-      pass information to the
-      <code>UserInterface</code>
-      , which is an interface with methods that will be called at runtime to request data from the user.
-      <code>ConsoleInput</code>
-      is an implementation of this that creates a text user interface, allowing the user to operate the client from the command-line.
-      We can easily create a graphical implementation of
-      <code>UserInterface</code>
-      at a later date. We can also create a mock implementation for testing purposes that simulates a user entering data. This
-      allows us to check the behavior of the client automatically using conventional JUnit test cases, as demonstrated by the
-      code in the
-      <code>src/test/java</code>
-      directory:
-      <programlisting>
-  org/jboss/example/dna/sequencers/SequencingClientTest.java
-                                  /MockUserInterface.java</programlisting>
-    </para>
-    <para>
-      If we look at the
-      <code>SequencingClient</code>
-      code, there are a handful of methods that encapsulate the various activities.
-    </para>
-    <note>
-      <para>To keep the code shown in this book as readable as possible, some of the comments and error handling
-      have been removed.</para>
-    </note>
-    <para>
-      The
-      <code>startRepository()</code>
-      method starts up an in-memory Jackrabbit JCR repository. The bulk of this method is simply gathering and passing the
-      information required by Jackrabbit. Because Jackrabbit's
-      <code>TransientRepository</code>
-      implementation shuts down after the last session is closed, the application maintains a session to ensure that the
-      repository remains open throughout the application's lifetime. And finally, the node type needed by the image sequencer is
-      registered with Jackrabbit.
-    </para>
-    <programlisting>
-public void startRepository() throws Exception {
-    if (this.repository == null) {
-        try {
-
-            // Load the Jackrabbit configuration ...
-            File configFile = new File(this.jackrabbitConfigPath);
-            String pathToConfig = configFile.getAbsolutePath();
-
-            // Find the directory where the Jackrabbit repository data will be stored ...
-            File workingDirectory = new File(this.workingDirectory);
-            String workingDirectoryPath = workingDirectory.getAbsolutePath();
-
-            // Get the Jackrabbit custom node definition (CND) file ...
-            URL cndFile = Thread.currentThread().getContextClassLoader().getResource("jackrabbitNodeTypes.cnd");
-
-            // Create the Jackrabbit repository instance and establish a session to keep the repository alive ...
-            this.repository = new TransientRepository(pathToConfig, workingDirectoryPath);
-            if (this.username != null) {
-                Credentials credentials = new SimpleCredentials(this.username, this.password);
-                this.keepAliveSession = this.repository.login(credentials, this.workspaceName);
-            } else {
-                this.keepAliveSession = this.repository.login();
-            }
-
-            try {
-                // Register the node types (only valid the first time) ...
-                JackrabbitNodeTypeManager mgr = (JackrabbitNodeTypeManager)this.keepAliveSession.getWorkspace().getNodeTypeManager();
-                mgr.registerNodeTypes(cndFile.openStream(), JackrabbitNodeTypeManager.TEXT_X_JCR_CND);
-            } catch (RepositoryException e) {
-                if (!e.getMessage().contains("already exists")) throw e;
-            }
-
-        } catch (Exception e) {
-            this.repository = null;
-            this.keepAliveSession = null;
-            throw e;
-        }
-    }
-}</programlisting>
-    <para>As you can see, this method really has nothing to do with JBoss DNA, other than setting up a JCR repository that JBoss
-      DNA will use.</para>
-    <para>
-      The
-      <code>shutdownRepository()</code>
-      method shuts down the Jackrabbit transient repository by closing the "keep-alive session". Again, this method really does
-      nothing specifically with JBoss DNA, but is needed to manage the JCR repository that JBoss DNA uses.
-      <programlisting>
-public void shutdownRepository() throws Exception {
-    if (this.repository != null) {
-        try {
-            this.keepAliveSession.logout();
-        } finally {
-            this.repository = null;
-            this.keepAliveSession = null;
-        }
-    }
-}</programlisting>
-    </para>
-    <para>
-      The
-      <code>startDnaServices()</code>
-      method first starts the JCR repository (if it was not already started), and proceeds to create and configure the
-      <code>SequencingService</code>
-      as described
-      <link linkend="sequencing_service">earlier</link>
-      . This involes setting up the
-      <code>SessionFactory</code>
-      and
-      <code>ExecutionContext</code>
-      , creating the
-      <code>SequencingService</code>
-      instance, and configuring the image sequencer. The method then continues by setting up the
-      <code>ObservationService</code>
-      as described
-      <link linkend="observation_service">earlier</link>
-      and starting the service.
-      <programlisting>
-public void startDnaServices() throws Exception {
-    if (this.repository == null) this.startRepository();
-    if (this.sequencingService == null) {
-
-        SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
-        sessionFactory.registerRepository(this.repositoryName, this.repository);
-        if (this.username != null) {
-            Credentials credentials = new SimpleCredentials(this.username, this.password);
-            sessionFactory.registerCredentials(this.repositoryName + "/" + this.workspaceName, credentials);
-        }
-        this.executionContext = new SimpleExecutionContext(sessionFactory);
-
-        // Create the sequencing service, passing in the execution context ...
-        this.sequencingService = new SequencingService();
-        this.sequencingService.setExecutionContext(executionContext);
-
-        // Configure the sequencers.
-        String name = "Image Sequencer";
-        String desc = "Sequences image files to extract the characteristics of the image";
-        String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
-        String[] classpath = null; // Use the current classpath
-        String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data] => /images/$1"};
-        SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
-        this.sequencingService.addSequencer(imageSequencerConfig);
-
-        // Set up the MP3 sequencer ...
-        name = "Mp3 Sequencer";
-        desc = "Sequences mp3 files to extract the id3 tags of the audio file";
-        classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
-        String[] mp3PathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data] => /mp3s/$1"};
-        SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname, classpath, mp3PathExpressions);
-        this.sequencingService.addSequencer(mp3SequencerConfig);
-
-        // Use the DNA observation service to listen to the JCR repository (or multiple ones), and
-        // then register the sequencing service as a listener to this observation service...
-        this.observationService = new ObservationService(this.executionContext.getSessionFactory());
-        this.observationService.getAdministrator().start();
-        this.observationService.addListener(this.sequencingService);
-        this.observationService.monitor(this.repositoryName + "/" + this.workspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED);
-    }
-    // Start up the sequencing service ...
-    this.sequencingService.getAdministrator().start();
-}</programlisting>
-    </para>
-    <para>
-      The
-      <code>shutdownDnaServices()</code>
-      method is pretty straightforward: it just calls shutdown on each of the services and waits until they terminate.
-      <programlisting>
-public void shutdownDnaServices() throws Exception {
-    if (this.sequencingService == null) return;
-
-    // Shut down the service and wait until it's all shut down ...
-    this.sequencingService.getAdministrator().shutdown();
-    this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-
-    // Shut down the observation service ...
-    this.observationService.getAdministrator().shutdown();
-    this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-}</programlisting>
-    </para>
-    <para>None of the other methods really do anything with JBoss DNA <emphasis>per se</emphasis>. Instead, they merely work with the repository
-      using the JCR API.</para>
-    <para>
-      The <code>main</code> method of the <code>SequencingClient</code> class creates a <code>SequencingClient</code> instance,
-      and passes a new <code>ConsoleInput</code> instance:
-      <programlisting>
-public static void main( String[] args ) throws Exception {
-    SequencingClient client = new SequencingClient();
-    client.setRepositoryInformation("repo", "default", "jsmith", "secret".toCharArray());
-    client.setUserInterface(new ConsoleInput(client));
-}</programlisting>
-      </para>
-      <para>If we look at the
-      <code>ConsoleInput</code>
-      constructor, it starts the repository, the DNA services, and a thread for the user interface. At this point, the constructor
-      returns, but the main application continues under the user interface thread.  When the user requests to quit,
-      the user interface thread also shuts down the DNA services and JCR repository.
-      <programlisting>
-public ConsoleInput( SequencerClient client ) {
-  try {
-      client.startRepository();
-      client.startDnaServices();
-  
-      System.out.println(getMenu());
-      Thread eventThread = new Thread(new Runnable() {
-          private boolean quit = false;
-          public void run() {
-              try {
-                  while (!quit) {
-                      // Display the prompt and process the requested operation ...
-                  }
-              } finally {
-                  try {
-                      // Terminate ...
-                      client.shutdownDnaServices();
-                      client.shutdownRepository();
-                  } catch (Exception err) {
-                      System.out.println("Error shutting down sequencing service and repository: " + err.getLocalizedMessage());
-                      err.printStackTrace(System.err);
-                  }
-              }
-          }
-      });
-      eventThread.start();
-  } catch (Exception err) {
-      System.out.println("Error: " + err.getLocalizedMessage());
-      err.printStackTrace(System.err);
-  }
-}</programlisting>
-    </para>
-    <para>At this point, we've reviewed all of the interesting code in the example application.  However, feel free
-    to play with the application, trying different things.
-    </para>
-  </sect1>
-  <sect1 id="using_dna_review">
-    <title>Summarizing what we just did</title>
-    <para>In this chapter we covered the different JBoss DNA components and how they can be used in your application.
-      Specifically, we described how the <code>SequencingService</code> and <code>ObservationService</code> can 
-      be configured and used.  And we ended the chapter by reviewing the example application, which not only uses
-      JBoss DNA, but also the repository via the JCR API.
-    </para>
-  </sect1>
-</chapter>
-  
-<!--  ====================================================================================================
-                                               Chapter 
-      ====================================================================================================   -->
-<chapter id="custom_sequencers">
-  <title>Creating custom sequencers</title>
-  <para>The current release of JBoss DNA comes with two sequencers: one that extracts metadata from a variety of image file formats,
-  and another that extracts some of the ID3 metadata from MP3 audio files.  However, it's very easy to create your own
-  sequencers and to then configure JBoss DNA to use them in your own application.
-  </para>
-  <para>
-  Creating a custom sequencer involves the following steps:
-  <itemizedlist>
-    <listitem>
-      <para>Create a Maven 2 project for your sequencer;</para>
-    </listitem>
-    <listitem>
-      <para>Implement the <code>org.jboss.dna.graph.sequencers.StreamSequencer</code> interface with your own implementation, and create unit tests to verify
-      the functionality and expected behavior;</para>
-    </listitem>
-    <listitem>
-      <para>Add the sequencer configuration to the JBoss DNA <code>SequencingService</code> in your application
-      as described in the <link linkend="using_dna">previous chapter</link>; and</para>
-    </listitem>
-    <listitem>
-      <para>Deploy the JAR file with your implementation (as well as any dependencies), and make them available to JBoss DNA
-      in your application.</para>
-    </listitem>
-  </itemizedlist>
-  It's that simple.
-  </para>
-  <sect1 id="custom_sequencer_project">
-    <title>Creating the Maven 2 project</title>
-    <para>The first step is to create the Maven 2 project that you can use to compile your code and build the JARs.
-    Maven 2 automates a lot of the work, and since you're already <link linkend="downloading_and_running">set up to use Maven</link>,
-    using Maven for your project will save you a lot of time and effort.  Of course, you don't have to use Maven 2, but then you'll
-    have to get the required libraries and manage the compiling and building process yourself.</para>
-    <note>
-      <para>JBoss DNA may provide in the future a Maven archetype for creating sequencer projects.  If you'd find this useful
-        and would like to help create it, please <link linkend="preface">join the community</link>.</para>
-    </note>
-  <note>
-    <para>The <code>dna-sequencer-images</code> project is a small, self-contained sequencer implementation that
-    has only the minimal dependencies.  Starting with this project's source and modifying it to suit your needs may be the easiest way to get started.
-    See the subversion repository: <ulink url="http://anonsvn.jboss.org/repos/dna/trunk/sequencers/dna-sequencer-images/">http://anonsvn.jboss.org/repos/dna/trunk/sequencers/dna-sequencer-images/</ulink>
-    </para>
-  </note>
-    <para>You can create your Maven project any way you'd like.  For examples, see the <ulink url="http://maven.apache.org/guides/getting-started/index.html#How_do_I_make_my_first_Maven_project">Maven 2 documentation</ulink>.  
-    Once you've done that, just add the dependencies in your project's <code>pom.xml</code> dependencies section:
-  <programlisting>
-&lt;dependency&gt;
-  &lt;groupId&gt;org.jboss.dna&lt;/groupId&gt;
-  &lt;artifactId&gt;dna-common&lt;/artifactId&gt;
-  &lt;version&gt;0.1&lt;/version&gt;
-&lt;/dependency&gt;
-&lt;dependency&gt;
-  &lt;groupId&gt;org.jboss.dna&lt;/groupId&gt;
-  &lt;artifactId&gt;dna-graph&lt;/artifactId&gt;
-  &lt;version&gt;0.1&lt;/version&gt;
-&lt;/dependency&gt;
-&lt;dependency&gt;
-  &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
-  &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
-&lt;/dependency&gt;
-</programlisting>
-  These are minimum dependencies required for compiling a sequencer.  Of course, you'll have to add
-  other dependencies that your sequencer needs.</para>
-  <para>As for testing, you probably will want to add more dependencies, such as those listed here:
-<programlisting>
-&lt;dependency&gt;
-  &lt;groupId&gt;junit&lt;/groupId&gt;
-  &lt;artifactId&gt;junit&lt;/artifactId&gt;
-  &lt;version&gt;4.4&lt;/version&gt;
-  &lt;scope&gt;test&lt;/scope&gt;
-&lt;/dependency&gt;
-&lt;dependency&gt;
-  &lt;groupId&gt;org.hamcrest&lt;/groupId&gt;
-  &lt;artifactId&gt;hamcrest-library&lt;/artifactId&gt;
-  &lt;version&gt;1.1&lt;/version&gt;
-  &lt;scope&gt;test&lt;/scope&gt;
-&lt;/dependency&gt;
-&lt;!-- Logging with Log4J --&gt;
-&lt;dependency&gt;
-  &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
-  &lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
-  &lt;version&gt;1.4.3&lt;/version&gt;
-  &lt;scope&gt;test&lt;/scope&gt;
-&lt;/dependency&gt;
-&lt;dependency&gt;
-  &lt;groupId&gt;log4j&lt;/groupId&gt;
-  &lt;artifactId&gt;log4j&lt;/artifactId&gt;
-  &lt;version&gt;1.2.14&lt;/version&gt;
-  &lt;scope&gt;test&lt;/scope&gt;
-&lt;/dependency&gt;
-</programlisting>
-  Testing JBoss DNA sequencers does not require a JCR repository or the JBoss DNA services.  (For more detail,
-  see the <link linkend="testing_custom_sequencers">testing section</link>.)  However, if you want to do
-  integration testing with a JCR repository and the JBoss DNA services, you'll need additional dependencies for these libraries.
-<programlisting>
-&lt;dependency&gt;
-  &lt;groupId&gt;org.jboss.dna&lt;/groupId&gt;
-  &lt;artifactId&gt;dna-repository&lt;/artifactId&gt;
-  &lt;version&gt;0.1&lt;/version&gt;
-  &lt;scope&gt;test&lt;/scope&gt;
-&lt;/dependency&gt;
-&lt;!-- Java Content Repository API --&gt;
-&lt;dependency&gt;
-  &lt;groupId&gt;javax.jcr&lt;/groupId&gt;
-  &lt;artifactId&gt;jcr&lt;/artifactId&gt;
-  &lt;version&gt;1.0.1&lt;/version&gt;
-  &lt;scope&gt;test&lt;/scope&gt;
-&lt;/dependency&gt;
-&lt;!-- Apache Jackrabbit (JCR Implementation) --&gt;
-&lt;dependency&gt;
-  &lt;groupId&gt;org.apache.jackrabbit&lt;/groupId&gt;
-  &lt;artifactId&gt;jackrabbit-api&lt;/artifactId&gt;
-  &lt;version&gt;1.3.3&lt;/version&gt;
-  &lt;scope&gt;test&lt;/scope&gt;
-  &lt;!-- Exclude these since they are included in JDK 1.5 --&gt;
-  &lt;exclusions&gt;
-    &lt;exclusion&gt;
-      &lt;groupId&gt;xml-apis&lt;/groupId&gt;
-      &lt;artifactId&gt;xml-apis&lt;/artifactId&gt;
-    &lt;/exclusion&gt;
-    &lt;exclusion&gt;
-      &lt;groupId&gt;xerces&lt;/groupId&gt;
-      &lt;artifactId&gt;xercesImpl&lt;/artifactId&gt;
-    &lt;/exclusion&gt;
-  &lt;/exclusions&gt;
-&lt;/dependency&gt;
-&lt;dependency&gt;
-  &lt;groupId&gt;org.apache.jackrabbit&lt;/groupId&gt;
-  &lt;artifactId&gt;jackrabbit-core&lt;/artifactId&gt;
-  &lt;version&gt;1.3.3&lt;/version&gt;
-  &lt;scope&gt;test&lt;/scope&gt;
-  &lt;!-- Exclude these since they are included in JDK 1.5 --&gt;
-  &lt;exclusions&gt;
-    &lt;exclusion&gt;
-      &lt;groupId&gt;xml-apis&lt;/groupId&gt;
-      &lt;artifactId&gt;xml-apis&lt;/artifactId&gt;
-    &lt;/exclusion&gt;
-    &lt;exclusion&gt;
-      &lt;groupId&gt;xerces&lt;/groupId&gt;
-      &lt;artifactId&gt;xercesImpl&lt;/artifactId&gt;
-    &lt;/exclusion&gt;
-  &lt;/exclusions&gt;
-&lt;/dependency&gt;
-</programlisting>
-  </para>
-  <para>At this point, your project should be set up correctly, and you're ready to move on to 
-  <link linkend="custom_sequencer_implementation">writing the Java implementation</link> for your sequencer.
-  </para>
-  </sect1>
-  <sect1 id="custom_sequencer_implementation">
-    <title>Implementing the StreamSequencer interface</title>
-    <para>After creating the project and setting up the dependencies, the next step is to create a Java class that implements
-    the <code>org.jboss.dna.graph.sequencers.StreamSequencer</code> interface.  This interface is very straightforward
-    and involves a single method:
-    <programlisting>
-public interface StreamSequencer {
-
-    /**
-     * Sequence the data found in the supplied stream, placing the output 
-     * information into the supplied map.
-     *
-     * @param stream the stream with the data to be sequenced; never null
-     * @param output the output from the sequencing operation; never null
-     * @param progressMonitor the progress monitor that should be kept 
-     *   updated with the sequencer's progress and that should be
-     *   frequently consulted as to whether this operation has been cancelled.
-     */
-    void sequence( InputStream stream, SequencerOutput output, 
-                   ProgressMonitor progressMonitor );</programlisting>
-    </para>
-    <para>The job of a stream sequencer is to process the data in the supplied stream, and place into the <code>SequencerOutput</code> 
-    any information that is to go into the JCR repository.  JBoss DNA figures out when your sequencer should be called
-    (of course, using the sequencing configuration you'll add in a bit), and then makes sure the generated information
-    is saved in the correct place in the repository.  
-    </para>
-    <para>The <code>SequencerOutput</code> class is fairly easy to use.  There are basically two methods you need to call.
-    One method sets the property values, while the other sets references to other nodes in the repository.  Use these
-    methods to describe the properties of the nodes you want to create, using relative paths for the nodes and
-    valid JCR property names for properties and references.  JBoss DNA will ensure that nodes are created or updated
-    whenever they're needed.
-    <programlisting>
-public interface SequencerOutput {
-
-  /**
-   * Set the supplied property on the supplied node.  The allowable
-   * values are any of the following:
-   *   - primitives (which will be autoboxed)
-   *   - String instances
-   *   - String arrays
-   *   - byte arrays
-   *   - InputStream instances
-   *   - Calendar instances
-   *
-   * @param nodePath the path to the node containing the property; 
-   * may not be null
-   * @param property the name of the property to be set
-   * @param values the value(s) for the property; may be empty if 
-   * any existing property is to be removed
-   */
-  void setProperty( String nodePath, String property,
-                    Object... values );
-
-  /**
-   * Set the supplied reference on the supplied node.
-   *
-   * @param nodePath the path to the node containing the property; 
-   * may not be null
-   * @param property the name of the property to be set
-   * @param paths the paths to the referenced property, which may be
-   * absolute paths or relative to the sequencer output node;
-   * may be empty if any existing property is to be removed
-   */
-  void setReference( String nodePath, String property,
-                     String... paths );
-}</programlisting>
-    </para>
-      <para>JBoss DNA will create nodes of type <code>nt:unstructured</code> unless you specify the value for the
-      <code>jcr:primaryType</code> property.  You can also specify the values for the <code>jcr:mixinTypes</code> property
-      if you want to add mixins to any node.
-      </para>
-    <para>For a complete example of a sequencer, let's look at the <code>org.jboss.dna.sequencers.image.ImageMetadataSequencer</code> implementation:
-    <programlisting>
-public class ImageMetadataSequencer implements StreamSequencer {
-
-    public static final String METADATA_NODE = "image:metadata";
-    public static final String IMAGE_PRIMARY_TYPE = "jcr:primaryType";
-    public static final String IMAGE_MIXINS = "jcr:mixinTypes";
-    public static final String IMAGE_MIME_TYPE = "jcr:mimeType";
-    public static final String IMAGE_ENCODING = "jcr:encoding";
-    public static final String IMAGE_FORMAT_NAME = "image:formatName";
-    public static final String IMAGE_WIDTH = "image:width";
-    public static final String IMAGE_HEIGHT = "image:height";
-    public static final String IMAGE_BITS_PER_PIXEL = "image:bitsPerPixel";
-    public static final String IMAGE_PROGRESSIVE = "image:progressive";
-    public static final String IMAGE_NUMBER_OF_IMAGES = "image:numberOfImages";
-    public static final String IMAGE_PHYSICAL_WIDTH_DPI = "image:physicalWidthDpi";
-    public static final String IMAGE_PHYSICAL_HEIGHT_DPI = "image:physicalHeightDpi";
-    public static final String IMAGE_PHYSICAL_WIDTH_INCHES = "image:physicalWidthInches";
-    public static final String IMAGE_PHYSICAL_HEIGHT_INCHES = "image:physicalHeightInches";
-
-    /**
-     * {@inheritDoc}
-     */
-    public void sequence( InputStream stream, SequencerOutput output, 
-                          ProgressMonitor progressMonitor ) {
-        progressMonitor.beginTask(10, ImageSequencerI18n.sequencerTaskName);
-
-        ImageMetadata metadata = new ImageMetadata();
-        metadata.setInput(stream);
-        metadata.setDetermineImageNumber(true);
-        metadata.setCollectComments(true);
-
-        // Process the image stream and extract the metadata ...
-        if (!metadata.check()) {
-            metadata = null;
-        }
-        progressMonitor.worked(5);
-        if (progressMonitor.isCancelled()) return;
-
-        // Generate the output graph if we found useful metadata ...
-        if (metadata != null) {
-            // Place the image metadata into the output map ...
-            output.setProperty(METADATA_NODE, IMAGE_PRIMARY_TYPE, "image:metadata");
-            // output.psetProperty(METADATA_NODE, IMAGE_MIXINS, "");
-            output.setProperty(METADATA_NODE, IMAGE_MIME_TYPE, metadata.getMimeType());
-            // output.setProperty(METADATA_NODE, IMAGE_ENCODING, "");
-            output.setProperty(METADATA_NODE, IMAGE_FORMAT_NAME, metadata.getFormatName());
-            output.setProperty(METADATA_NODE, IMAGE_WIDTH, metadata.getWidth());
-            output.setProperty(METADATA_NODE, IMAGE_HEIGHT, metadata.getHeight());
-            output.setProperty(METADATA_NODE, IMAGE_BITS_PER_PIXEL, metadata.getBitsPerPixel());
-            output.setProperty(METADATA_NODE, IMAGE_PROGRESSIVE, metadata.isProgressive());
-            output.setProperty(METADATA_NODE, IMAGE_NUMBER_OF_IMAGES, metadata.getNumberOfImages());
-            output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_WIDTH_DPI, metadata.getPhysicalWidthDpi());
-            output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_HEIGHT_DPI, metadata.getPhysicalHeightDpi());
-            output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_WIDTH_INCHES, metadata.getPhysicalWidthInch());
-            output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_HEIGHT_INCHES, metadata.getPhysicalHeightInch());
-        }
-
-        progressMonitor.done();
-    }
-}</programlisting>
-    </para>
-    <para>
-    Notice how the image metadata is extracted and the output graph is generated.  A single node is created with the name <code>image:metadata</code>
-    and with the <code>image:metadata</code> node type.  No mixins are defined for the node, but several properties are set on the node
-    using the values obtained from the image metadata.  After this method returns, the constructed graph will be saved to the repository
-    in all of the places defined by its configuration.  (This is why only relative paths are used in the sequencer.)
-    </para>
-    <para>Also note how the progress monitor is used.  Reporting progress through the supplied <code>ProgressMonitor</code> is very easy, and it ensures that JBoss DNA
-     can accurately monitor and report the status of sequencing activities to the users.  At the beginning of the operation, call
-     <code>beginTask(...)</code> with a meaningful message describing
-     the operation and a total for the amount of work that will be done by this sequencer. Then perform the sequencing work,
-     periodically reporting work by specifying the incremental amount of work with the <code>worked(double)</code> method, or
-     by creating a subtask with the <code>createSubtask(double)</code> method and reporting work against that subtask
-     monitor.
-     </para>
-     <para>Your method should periodically use the ProgressMonitor's <code>isCancelled()</code> method to check whether the operation has been
-     cancelled.. If this method returns true, the implementation should abort all work as
-     soon as possible and close any resources that were acquired or opened.
-     </para>
-     <para>
-     Finally, when your sequencing operation is completed, it should call <code>done()</code> on the progress monitor.
-     </para>
-  </sect1>
-  <sect1 id="testing_custom_sequencers">
-    <title>Testing custom sequencers</title>
-    <para>The sequencing framework was designed to make testing sequencers much easier.  In particular, the
-    <code>StreamSequencer</code> interface does not make use of the JCR API.  So instead of requiring a fully-configured
-    JCR repository and JBoss DNA system, unit tests for a sequencer can focus on testing that the content is
-    processed correctly and the desired output graph is generated.</para>
-    <note>
-      <para>For a complete example of a sequencer unit test, see the <code>ImageMetadataSequencerTest</code> unit test
-      in the <code>org.jboss.dna.sequencer.images</code> package of the <code>dna-sequencers-image</code> project.
-      </para>
-    </note>
-    <para>The following code fragment shows one way of testing a sequencer, using JUnit 4.4 assertions and 
-      some of the classes made available by JBoss DNA.  Of course,
-      this example code does not do any error handling and does not make all the assertions a real test would.
-    <programlisting>
-Sequencer sequencer = new ImageMetadataSequencer();
-MockSequencerOutput output = new MockSequencerOutput();
-ProgressMonitor progress = new SimpleProgressMonitor("Test activity");
-InputStream stream = null;
-try {
-    stream = this.getClass().getClassLoader().getResource("caution.gif").openStream();
-    sequencer.sequence(stream,output,progress);   // writes to 'output'
-    assertThat(output.getPropertyValues("image:metadata", "jcr:primaryType"), 
-               is(new Object[] {"image:metadata"}));
-    assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"), 
-               is(new Object[] {"image/gif"}));
-    // ... make more assertions here
-    assertThat(output.hasReferences(), is(false));
-} finally {
-    stream.close();
-}</programlisting>
-  </para>
-  <para>It's also useful to test that a sequencer produces no output for something it should not understand:
-    <programlisting>
-Sequencer sequencer = new ImageMetadataSequencer();
-MockSequencerOutput output = new MockSequencerOutput();
-ProgressMonitor progress = new SimpleProgressMonitor("Test activity");
-InputStream stream = null;
-try {
-    stream = this.getClass().getClassLoader().getResource("caution.pict").openStream();
-    sequencer.sequence(stream,output,progress);   // writes to 'output'
-    assertThat(output.hasProperties(), is(false));
-    assertThat(output.hasReferences(), is(false));
-} finally {
-    stream.close();
-}</programlisting>
-    </para>
-    <para>These are just two simple tests that show ways of testing a sequencer.  Some tests may get quite involved,
-    especially if a lot of output data is produced.  
-    </para>
-    <para>It may also be useful to create some integration tests
-    that <link linkend="using_dna">configure JBoss DNA</link> to use a custom sequencer, and to then upload
-    content using the JCR API, verifying that the custom sequencer did run.  However, remember that JBoss DNA
-    runs sequencers asynchronously in the background, and you must sychronize your tests to ensure that the
-    sequencers have a chance to run before checking the results.  (One way of doing this (although, granted, not always reliable) is to wait for a second
-    after uploading your content, shutdown the <code>SequencingService</code> and await its termination,
-    and then check that the sequencer output has been saved to the JCR repository.  For an example of this technique,
-    see the <code>SequencingClientTest</code> unit test in the example application.)
-    </para>  
-  </sect1>
-  <sect1 id="deploying_custom_sequencers">
-    <title>Deploying custom sequencers</title>
-    <para>The first step of deploying a sequencer consists of adding/changing the sequencer configuration (e.g., <code>SequencerConfig</code>)
-    in the <code>SequencingService</code>.  This was covered in the <link linkend="sequencing_service">previous chapter</link>.
-    </para>
-    <para>
-    The second step is to make the sequencer implementation available to JBoss DNA.  At this time, the JAR containing 
-    your new sequencer, as well as any JARs that your sequencer depends on, should be placed on your application classpath.</para>
-    <note>
-      <para>A future goal of JBoss DNA is to allow sequencers, connectors, and other extensions to be easily deployed into
-        a runtime repository.  This process will not only be much simpler, but it will also provide JBoss DNA 
-        with the information necessary to update configurations and create the appropriate class loaders for each extension.
-        Having separate class loaders for each extension helps prevent the pollution of the common classpath, 
-        facilitates an isolated runtime environment to eliminate any dependency conflicts, and may potentially
-        enable hot redeployment of newer extension versions.
-      </para>
-    </note>
-  </sect1>
-</chapter>
-  
-<!--  ====================================================================================================
-                                               Chapter 
-      ====================================================================================================   -->
-<chapter id="future_directions">
-  <title>Looking to the future</title>
-  <para>What's next for JBoss DNA?  Well, the sequencing system is just the beginning.  With this release, the sequencing system
-  is stable enough so that more <link linkend="sequencers">sequencers</link> can be developed and used within your own applications.
-  If you're interested in getting involved with the JBoss DNA project, consider picking up one of the sequencers on our
-  <ulink url="http://jira.jboss.org/jira/browse/DNA?report=com.atlassian.jira.plugin.system.project:roadmap-panel">roadmap</ulink>.
-  Or, check out <ulink url="http://jira.jboss.org/jira/secure/IssueNavigator.jspa?reset=true&amp;mode=hide&amp;pid=12310520&amp;sorter/order=DESC&amp;sorter/field=priority&amp;resolution=-1&amp;component=12311436">JIRA</ulink>
-  for the list of sequencers we've thought of.  If you think of one that's not there, please add it to JIRA!
-  </para>
-  <para>
-  The next release will focus on creating the <link linkend="federation">federation engine</link> and connectors
-  for several popular and ubiquitous systems.  The 0.2 release will likely only federate information in a read-only manner,
-  but updates will soon follow.  Also, during the early part of the next release, the JBoss DNA project will switch to use JDK 6.  
-  Java 5 is being end-of-lifed, so we want to move to a supported JDK. However, a number of JBoss projects and products continue to
-  require Java 5, so our next release will most likely use JDK 6 with Java 5 compatibility.</para>
-  <para>
-  Other components on our roadmap include a web user interface, a REST-ful server, and a view system that allows domain-specific
-  views of information in the repository.  These components are farther out on our roadmap, and at this time have not been
-  targeted to a particular release.  If any of these are of interest to you, please <link linkend="preface">get involved</link> in the community.
-  </para>
-</chapter>
-</book>
\ No newline at end of file

Deleted: trunk/dna-graph/src/test/resources/plugin.xml
===================================================================
--- trunk/dna-graph/src/test/resources/plugin.xml	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/dna-graph/src/test/resources/plugin.xml	2008-10-29 18:23:01 UTC (rev 598)
@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.0"?>
-<!--  (c) 2007 Varsity Gateway LLC.  All rights reserved. -->
-<plugin
-   id="com.metamatrix.metamodels.transformation"
-   name="%pluginName"
-   version="5.5.1"
-   provider-name="%providerName"
-   class="com.metamatrix.metamodels.transformation.TransformationPlugin">
-
-   <runtime>
-      <library name="metamodelsTransformation.jar">
-         <export name="*"/>
-      </library>
-   </runtime>
-   <requires>
-      <import plugin="org.eclipse.emf.mapping" export="true"/>
-      <import plugin="org.eclipse.emf.ecore" export="true"/>
-      <import plugin="org.eclipse.emf.edit" export="true"/>
-      <import plugin="org.eclipse.emf.ecore.edit" export="true"/>
-      <import plugin="org.eclipse.core.runtime" export="true"/>
-      <import plugin="com.metamatrix.core" export="true"/>
-      <import plugin="com.metamatrix.metamodels.core" export="true"/>
-   </requires>
-
-
-<!--
-   	Each extension below represents a single metamodel.  Each metmodel is
-   	registered using under the specified <uri> value which must be the same
-   	eNS_URI value defined in the EPackage class for that metamodel.
-   -->
-   <extension
-         id="transformation"
-         name="%metamodelName"
-         point="com.metamatrix.modeler.core.metamodel">
-      <uri>
-         http://www.metamatrix.com/metamodels/Transformation
-      </uri>
-      <alternateUri>
-         mtkplugin:///com.metamatrix.metamodels.Transformation
-      </alternateUri>
-      <packageClass
-            name="com.metamatrix.metamodels.transformation.TransformationPackage">
-      </packageClass>
-      <adapterClass
-            name="com.metamatrix.metamodels.transformation.provider.TransformationItemProviderAdapterFactory">
-      </adapterClass>
-      <properties
-            createAsPhysical="false"
-            requiresProxies="false"
-            participatoryOnly="true"
-            createAsVirtual="false"
-            supportsDiagrams="false"
-            supportsExtension="true">
-      </properties>
-   </extension>
-   <extension
-         point="org.eclipse.emf.ecore.generated_package">
-      <package
-            uri="http://www.metamatrix.com/metamodels/Transformation"
-            class="com.metamatrix.metamodels.transformation.TransformationPackage">
-      </package>
-   </extension>
-     
-   <extension
-         id="mapping"
-         name="%mappingMetamodelName"
-         point="com.metamatrix.modeler.core.metamodel">
-      <uri>
-         http://www.eclipse.org/emf/2002/Mapping
-      </uri>
-      <alternateUri>
-         mtkplugin:///www.eclipse.org/emf/2002/Mapping
-      </alternateUri>
-      <packageClass
-            name="org.eclipse.emf.mapping.MappingPackage">
-      </packageClass>
-      <adapterClass
-            name="org.eclipse.emf.mapping.provider.MappingItemProviderAdapterFactory">
-      </adapterClass>
-      <properties
-            createAsPhysical="false"
-            requiresProxies="false"
-            participatoryOnly="true"
-            createAsVirtual="false"
-            supportsDiagrams="false"
-            supportsExtension="false">
-      </properties>
-   </extension>
-
-</plugin>


Property changes on: trunk/extensions/dna-sequencer-xml
___________________________________________________________________
Name: svn:ignore
   + target


Added: trunk/extensions/dna-sequencer-xml/.classpath
===================================================================
--- trunk/extensions/dna-sequencer-xml/.classpath	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/.classpath	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/main/java"/>
+	<classpathentry kind="src" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

Added: trunk/extensions/dna-sequencer-xml/.project
===================================================================
--- trunk/extensions/dna-sequencer-xml/.project	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/.project	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>dna-sequencer-xml</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>

Added: trunk/extensions/dna-sequencer-xml/pom.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/pom.xml	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/pom.xml	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,92 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.jboss.dna</groupId>
+    <artifactId>dna</artifactId>
+    <version>0.3-SNAPSHOT</version>
+    <relativePath>../..</relativePath>
+  </parent>
+  <!-- The groupId and version values are inherited from parent -->
+  <artifactId>dna-sequencer-xml</artifactId>
+  <packaging>jar</packaging>
+  <name>JBoss DNA XML Sequencer</name>
+  <description>JBoss DNA Sequencer that processes XML files</description>
+  <url>http://labs.jboss.org/dna</url>
+  
+  <!--
+  Define the dependencies.  Note that all version and scopes default to those 
+  defined in the dependencyManagement section of the parent pom.
+  -->
+  <dependencies>
+    <!-- 
+    Common
+    -->
+    <dependency>
+      <groupId>org.jboss.dna</groupId>
+      <artifactId>dna-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.dna</groupId>
+      <artifactId>dna-graph</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.dna</groupId>
+      <artifactId>dna-common</artifactId>
+      <version>${pom.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.dna</groupId>
+      <artifactId>dna-graph</artifactId>
+      <version>${pom.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <!-- 
+    Testing (note the scope)
+    -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-library</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+    </dependency>
+    <!-- 
+    Logging (require SLF4J API for compiling, but use Log4J and its SLF4J binding for testing) 
+    -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+    </dependency>
+    <!-- 
+    Java Concurrency in Practice annotations
+    -->
+	<dependency>
+	  <groupId>net.jcip</groupId>
+	  <artifactId>jcip-annotations</artifactId>
+	</dependency>
+  </dependencies>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-report-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>
\ No newline at end of file

Added: trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaDtdLexicon.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaDtdLexicon.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaDtdLexicon.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.basic.BasicName;
+
+/**
+ * @author Randall Hauch
+ */
+public class DnaDtdLexicon {
+
+    public static class Namespace {
+        public static final String URI = "http://www.jboss.org/dna/dtd/1.0";
+        public static final String PREFIX = "dnadtd";
+    }
+
+    public static final Name NAME = new BasicName(Namespace.URI, "name");
+    public static final Name PUBLIC_ID = new BasicName(Namespace.URI, "publicId");
+    public static final Name SYSTEM_ID = new BasicName(Namespace.URI, "systemId");
+    public static final Name VALUE = new BasicName(Namespace.URI, "value");
+    public static final Name ENTITY = new BasicName(Namespace.URI, "entity");
+}

Added: trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaXmlLexicon.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaXmlLexicon.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaXmlLexicon.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.basic.BasicName;
+
+/**
+ * @author Randall Hauch
+ */
+public class DnaXmlLexicon {
+
+    public static class Namespace {
+        public static final String URI = "http://www.jboss.org/dna/xml/1.0";
+        public static final String PREFIX = "dnaxml";
+    }
+
+    public static final Name CDATA = new BasicName(Namespace.URI, "cData");
+    public static final Name CDATA_CONTENT = new BasicName(Namespace.URI, "cDataContent");
+    public static final Name COMMENT = new BasicName(Namespace.URI, "comment");
+    public static final Name COMMENT_CONTENT = new BasicName(Namespace.URI, "commentContent");
+    public static final Name DOCUMENT = new BasicName(Namespace.URI, "document");
+    public static final Name ELEMENT_CONTENT = new BasicName(Namespace.URI, "elementContent");
+    public static final Name PROCESSING_INSTRUCTION = new BasicName(Namespace.URI, "processingInstruction");
+    public static final Name PROCESSING_INSTRUCTION_CONTENT = new BasicName(Namespace.URI, "processingInstructionContent");
+    public static final Name TARGET = new BasicName(Namespace.URI, "target");
+}

Added: trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,702 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.jboss.dna.common.monitor.ProgressMonitor;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.NameFactory;
+import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.jboss.dna.graph.sequencers.SequencerOutput;
+import org.jboss.dna.graph.sequencers.StreamSequencer;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.DefaultHandler2;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * @author John Verhaeg
+ */
+public class XmlSequencer implements StreamSequencer {
+
+    private static final String DEFAULT_PRIMARY_TYPE = "nt:unstructured";
+    private static final String DECL_HANDLER_FEATURE = "http://xml.org/sax/properties/declaration-handler";
+    private static final String ENTITY_RESOLVER_2_FEATURE = "http://xml.org/sax/features/use-entity-resolver2";
+    private static final String LEXICAL_HANDLER_FEATURE = "http://xml.org/sax/properties/lexical-handler";
+    private static final String RESOLVE_DTD_URIS_FEATURE = "http://xml.org/sax/features/resolve-dtd-uris";
+    private static final String LOAD_EXTERNAL_DTDS_FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.sequencers.StreamSequencer#sequence(InputStream, SequencerOutput, SequencerContext,
+     *      ProgressMonitor)
+     */
+    public void sequence( InputStream stream,
+                          SequencerOutput output,
+                          SequencerContext context,
+                          ProgressMonitor monitor ) {
+        monitor.beginTask(100.0, XmlSequencerI18n.sequencingXmlDocument);
+        XMLReader reader;
+        try {
+            reader = XMLReaderFactory.createXMLReader();
+            Handler handler = new Handler(output, context, monitor);
+            reader.setContentHandler(handler);
+            reader.setErrorHandler(handler);
+            // Ensure handler acting as entity resolver 2
+            reader.setProperty(DECL_HANDLER_FEATURE, handler);
+            // Ensure handler acting as lexical handler
+            reader.setProperty(LEXICAL_HANDLER_FEATURE, handler);
+            // Ensure handler acting as entity resolver 2
+            setFeature(reader, ENTITY_RESOLVER_2_FEATURE, true);
+            // Prevent loading of external DTDs
+            setFeature(reader, LOAD_EXTERNAL_DTDS_FEATURE, false);
+            // Prevent the resolving of DTD entities into fully-qualified URIS
+            setFeature(reader, RESOLVE_DTD_URIS_FEATURE, false);
+            // Parse XML document
+            reader.parse(new InputSource(stream));
+        } catch (Exception error) {
+            context.getLogger(getClass()).error(error, XmlSequencerI18n.fatalErrorSequencingXmlDocument, error);
+            monitor.getProblems().addError(error, XmlSequencerI18n.fatalErrorSequencingXmlDocument, error);
+        } finally {
+            monitor.done();
+        }
+    }
+
+    /**
+     * Sets the reader's named feature to the supplied value, only if the feature is not already set to that value. This method
+     * does nothing if the feature is not known to the reader.
+     * 
+     * @param reader the reader; may not be null
+     * @param featureName the name of the feature; may not be null
+     * @param value the value for the feature
+     */
+    private void setFeature( XMLReader reader,
+                             String featureName,
+                             boolean value ) {
+        try {
+            if (reader.getFeature(featureName) != value) {
+                reader.setFeature(featureName, value);
+            }
+        } catch (SAXNotRecognizedException meansFeatureNotRecognized) {
+        } catch (SAXNotSupportedException meansFeatureNotSupported) {
+        }
+    }
+
+    private final class Handler extends DefaultHandler2 {
+
+        private final SequencerOutput output;
+        private final SequencerContext context;
+        private final ProgressMonitor monitor;
+
+        private double progress;
+
+        private Path path; // The DNA path of the node representing the current XML element
+
+        // Cached instances of the name factory and commonly referenced names
+        private final NameFactory nameFactory;
+        private Name defaultPrimaryType;
+
+        // Recursive map used to track the number of occurrences of names for elements under a particular path
+        private Map<Name, List<IndexedName>> nameToIndexedNamesMap = new HashMap<Name, List<IndexedName>>();
+
+        // The stack of recursive maps being processed, with the head entry being the map for the current path
+        private final LinkedList<Map<Name, List<IndexedName>>> nameToIndexedNamesMapStack = new LinkedList<Map<Name, List<IndexedName>>>();
+
+        // The stack of XML namespace in scope, with the head entry being namespace of the closest ancestor element declaring a
+        // namespace.
+        private final LinkedList<String> nsStack = new LinkedList<String>();
+
+        // Builder used to concatenate concurrent lines of CDATA into a single value.
+        private StringBuilder cDataBuilder;
+
+        // Builder used to concatenate concurrent lines of element content and entity evaluations into a single value.
+        private StringBuilder contentBuilder;
+
+        // The entity being processed
+        private String entity;
+
+        Handler( SequencerOutput output,
+                 SequencerContext context,
+                 ProgressMonitor monitor ) {
+            assert output != null;
+            assert monitor != null;
+            assert context != null;
+            this.output = output;
+            this.context = context;
+            this.monitor = monitor;
+            // Initialize path to a an empty path relative to the SequencerOutput's target path.
+            path = context.getValueFactories().getPathFactory().createRelativePath();
+            // Cache name factory since it is frequently used
+            nameFactory = context.getValueFactories().getNameFactory();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#attributeDecl(java.lang.String, java.lang.String, java.lang.String,
+         *      java.lang.String, java.lang.String)
+         */
+        @Override
+        public void attributeDecl( String name,
+                                   String name2,
+                                   String type,
+                                   String mode,
+                                   String value ) throws SAXException {
+            stopIfCancelled();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
+         */
+        @Override
+        public void characters( char[] ch,
+                                int start,
+                                int length ) throws SAXException {
+            stopIfCancelled();
+            String content = String.valueOf(ch, start, length);
+            // Check if data should be appended to previously parsed CDATA
+            if (cDataBuilder == null) {
+                // If content is for an entity, replace with entity reference
+                if (entity != null) {
+                    content = '&' + entity + ';';
+                }
+                // Check if first line of content
+                if (contentBuilder == null) {
+                    contentBuilder = new StringBuilder(content);
+                } else {
+                    // Append additional lines or entity evaluations to previous content, separated by a space
+                    if (entity == null) {
+                        contentBuilder.append(' ');
+                    }
+                    contentBuilder.append(content);
+                    // Text within builder will be output when another element or CDATA is encountered
+                }
+            } else {
+                cDataBuilder.append(ch, start, length);
+                // Text within builder will be output at the end of CDATA
+            }
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#comment(char[], int, int)
+         */
+        @Override
+        public void comment( char[] ch,
+                             int start,
+                             int length ) throws SAXException {
+            stopIfCancelled();
+            // Output separate nodes for each comment since multiple are allowed
+            startElement(DnaXmlLexicon.COMMENT);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.COMMENT);
+            output.setProperty(path, DnaXmlLexicon.COMMENT_CONTENT, String.valueOf(ch, start, length));
+            endElement();
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#elementDecl(java.lang.String, java.lang.String)
+         */
+        @Override
+        public void elementDecl( String name,
+                                 String model ) throws SAXException {
+            stopIfCancelled();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#endCDATA()
+         */
+        @Override
+        public void endCDATA() throws SAXException {
+            stopIfCancelled();
+            // Output CDATA built in characters() method
+            output.setProperty(path, DnaXmlLexicon.CDATA_CONTENT, cDataBuilder.toString());
+            endElement();
+            // Null-out builder to free memory
+            cDataBuilder = null;
+            updateProgress();
+        }
+
+        private void endContent() {
+            if (contentBuilder != null) {
+                // Normalize content
+                String content = StringUtil.normalize(contentBuilder.toString());
+                // Null-out builder to setup for subsequent content.
+                // Must be done before call to startElement below to prevent infinite loop.
+                contentBuilder = null;
+                // Skip if nothing in content but whitespace
+                if (content.length() > 0) {
+                    // Create separate node for each content entry since entries can be interspersed amongst child elements
+                    startElement(DnaXmlLexicon.ELEMENT_CONTENT);
+                    output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.ELEMENT_CONTENT);
+                    output.setProperty(path, DnaXmlLexicon.ELEMENT_CONTENT, content);
+                    endElement();
+                }
+            }
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#endDocument()
+         */
+        @Override
+        public void endDocument() throws SAXException {
+            stopIfCancelled();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#endDTD()
+         */
+        @Override
+        public void endDTD() throws SAXException {
+            stopIfCancelled();
+        }
+
+        private void endElement() {
+            // Recover parent's path, namespace, and indexedName map, clearing the ended element's map to free memory
+            path = path.getParent();
+            nameToIndexedNamesMap.clear();
+            nameToIndexedNamesMap = nameToIndexedNamesMapStack.removeFirst();
+            nsStack.removeFirst();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+         */
+        @Override
+        public void endElement( String uri,
+                                String localName,
+                                String name ) throws SAXException {
+            stopIfCancelled();
+            // Check if content still needs to be output
+            endContent();
+            endElement();
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#endEntity(java.lang.String)
+         */
+        @Override
+        public void endEntity( String name ) throws SAXException {
+            stopIfCancelled();
+            entity = null;
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
+         */
+        @Override
+        public void error( SAXParseException error ) {
+            context.getLogger(XmlSequencer.class).error(error, XmlSequencerI18n.errorSequencingXmlDocument, error);
+            monitor.getProblems().addError(error, XmlSequencerI18n.errorSequencingXmlDocument, error);
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#externalEntityDecl(java.lang.String, java.lang.String, java.lang.String)
+         */
+        @Override
+        public void externalEntityDecl( String name,
+                                        String publicId,
+                                        String systemId ) throws SAXException {
+            stopIfCancelled();
+            // Add "synthetic" entity container to path to help prevent name collisions with XML elements
+            Name entityName = DnaDtdLexicon.ENTITY;
+            startElement(entityName);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, entityName);
+            output.setProperty(path, nameFactory.create(DnaDtdLexicon.NAME), name);
+            output.setProperty(path, nameFactory.create(DnaDtdLexicon.PUBLIC_ID), publicId);
+            output.setProperty(path, nameFactory.create(DnaDtdLexicon.SYSTEM_ID), systemId);
+            endElement();
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException)
+         */
+        @Override
+        public void fatalError( SAXParseException error ) {
+            context.getLogger(XmlSequencer.class).error(error, XmlSequencerI18n.fatalErrorSequencingXmlDocument, error);
+            monitor.getProblems().addError(error, XmlSequencerI18n.fatalErrorSequencingXmlDocument, error);
+        }
+
+        private Name getDefaultPrimaryType() {
+            if (defaultPrimaryType == null) {
+                defaultPrimaryType = nameFactory.create(DEFAULT_PRIMARY_TYPE);
+            }
+            return defaultPrimaryType;
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#ignorableWhitespace(char[], int, int)
+         */
+        @Override
+        public void ignorableWhitespace( char[] ch,
+                                         int start,
+                                         int length ) throws SAXException {
+            stopIfCancelled();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#internalEntityDecl(java.lang.String, java.lang.String)
+         */
+        @Override
+        public void internalEntityDecl( String name,
+                                        String value ) throws SAXException {
+            stopIfCancelled();
+            // Add "synthetic" entity container to path to help prevent name collisions with XML elements
+            Name entityName = DnaDtdLexicon.ENTITY;
+            startElement(entityName);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, entityName);
+            output.setProperty(path, DnaDtdLexicon.NAME, name);
+            output.setProperty(path, DnaDtdLexicon.VALUE, value);
+            endElement();
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#notationDecl(java.lang.String, java.lang.String, java.lang.String)
+         */
+        @Override
+        public void notationDecl( String name,
+                                  String publicId,
+                                  String systemId ) throws SAXException {
+            stopIfCancelled();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#processingInstruction(java.lang.String, java.lang.String)
+         */
+        @Override
+        public void processingInstruction( String target,
+                                           String data ) throws SAXException {
+            stopIfCancelled();
+            // Output separate nodes for each instruction since multiple are allowed
+            Name name = DnaXmlLexicon.PROCESSING_INSTRUCTION;
+            startElement(name);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, name);
+            output.setProperty(path, DnaXmlLexicon.TARGET, target);
+            output.setProperty(path, DnaXmlLexicon.PROCESSING_INSTRUCTION_CONTENT, data);
+            endElement();
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#skippedEntity(java.lang.String)
+         */
+        @Override
+        public void skippedEntity( String name ) throws SAXException {
+            stopIfCancelled();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#startCDATA()
+         */
+        @Override
+        public void startCDATA() throws SAXException {
+            stopIfCancelled();
+            // Output separate nodes for each CDATA since multiple are allowed
+            startElement(DnaXmlLexicon.CDATA);
+            // Prepare builder for concatenating consecutive lines of CDATA
+            cDataBuilder = new StringBuilder();
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#startDocument()
+         */
+        @Override
+        public void startDocument() throws SAXException {
+            stopIfCancelled();
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.DOCUMENT);
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#startDTD(java.lang.String, java.lang.String, java.lang.String)
+         */
+        @Override
+        public void startDTD( String name,
+                              String publicId,
+                              String systemId ) throws SAXException {
+            stopIfCancelled();
+            output.setProperty(path, DnaDtdLexicon.NAME, name);
+            output.setProperty(path, DnaDtdLexicon.PUBLIC_ID, publicId);
+            output.setProperty(path, DnaDtdLexicon.SYSTEM_ID, systemId);
+            updateProgress();
+        }
+
+        private void startElement( Name name ) {
+            // Check if content still needs to be output
+            endContent();
+            // Add name to list of indexed names for this element to ensure we use the correct index (which is the size of the
+            // list)
+            List<IndexedName> indexedNames = nameToIndexedNamesMap.get(name);
+            if (indexedNames == null) {
+                indexedNames = new ArrayList<IndexedName>();
+                nameToIndexedNamesMap.put(name, indexedNames);
+            }
+            IndexedName indexedName = new IndexedName();
+            indexedNames.add(indexedName);
+            // Add element name and the appropriate index to the path.
+            // Per the JCR spec, the index must be relative to same-name sibling nodes
+            path = context.getValueFactories().getPathFactory().create(path, name, indexedNames.size());
+            path = path.getNormalizedPath();
+            // Add the indexed name map to the stack and set the current map to the new element's map
+            nameToIndexedNamesMapStack.addFirst(nameToIndexedNamesMap);
+            nameToIndexedNamesMap = indexedName.nameToIndexedNamesMap;
+            // Set the current namespace to whatever is declared by this element, or if not declared, to its nearest ancestor that
+            // does declare a namespace.
+            String ns = name.getNamespaceUri();
+            if (ns.length() == 0) {
+                nsStack.addFirst(nsStack.isEmpty() ? "" : nsStack.getFirst());
+            } else {
+                nsStack.addFirst(ns);
+            }
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String,
+         *      org.xml.sax.Attributes)
+         */
+        @Override
+        public void startElement( String uri,
+                                  String localName,
+                                  String name,
+                                  Attributes attributes ) throws SAXException {
+            stopIfCancelled();
+            // Look for the "jcr:name" attribute, and use that if it's there
+            Name type = getDefaultPrimaryType();
+            Name nameObj = nameFactory.create(name);
+            for (int ndx = 0, len = attributes.getLength(); ndx < len; ++ndx) {
+                String ns = attributes.getURI(ndx);
+                String attrLocalName = attributes.getLocalName(ndx);
+                Object value = attributes.getValue(ndx);
+                String jcrNsUri = context.getNamespaceRegistry().getNamespaceForPrefix("jcr");
+                if (jcrNsUri != null && jcrNsUri.equals(ns) && attrLocalName.equals("name")) {
+                    nameObj = nameFactory.create(value);
+                    break;
+                }
+            }
+            startElement(nameObj);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, type);
+            // Output this element's attributes using the attribute's namespace, if supplied, or the current namespace in scope.
+            String inheritedNs = nsStack.getFirst();
+            for (int ndx = 0, len = attributes.getLength(); ndx < len; ++ndx) {
+                String ns = attributes.getURI(ndx);
+                String attrLocalName = attributes.getLocalName(ndx);
+                Object value = attributes.getValue(ndx);
+                String jcrNsUri = context.getNamespaceRegistry().getNamespaceForPrefix("jcr");
+                if (jcrNsUri != null && jcrNsUri.equals(ns) && attrLocalName.equals("primaryType")) {
+                    value = nameFactory.create(value);
+                }
+                if (jcrNsUri != null && jcrNsUri.equals(ns) && attrLocalName.equals("name")) {
+                    continue;
+                }
+                output.setProperty(path, nameFactory.create(ns.length() == 0 ? inheritedNs : ns, attrLocalName), value);
+            }
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.ext.DefaultHandler2#startEntity(java.lang.String)
+         */
+        @Override
+        public void startEntity( String name ) throws SAXException {
+            stopIfCancelled();
+            entity = name;
+            updateProgress();
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#startPrefixMapping(java.lang.String, java.lang.String)
+         */
+        @Override
+        public void startPrefixMapping( String prefix,
+                                        String uri ) throws SAXException {
+            stopIfCancelled();
+            // Register any unregistered namespaces
+            NamespaceRegistry registry = context.getNamespaceRegistry();
+            if (!registry.isRegisteredNamespaceUri(uri)) {
+                registry.register(prefix, uri);
+            }
+            updateProgress();
+        }
+
+        private void stopIfCancelled() throws SAXException {
+            if (monitor.isCancelled()) {
+                throw new SAXException(XmlSequencerI18n.canceledSequencingXmlDocument.text());
+            }
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String,
+         *      java.lang.String)
+         */
+        @Override
+        public void unparsedEntityDecl( String name,
+                                        String publicId,
+                                        String systemId,
+                                        String notationName ) throws SAXException {
+            stopIfCancelled();
+        }
+
+        private void updateProgress() {
+            if (progress == 100.0) {
+                progress = 1;
+            } else {
+                progress++;
+            }
+            monitor.worked(progress);
+        }
+
+        /**
+         * <p>
+         * {@inheritDoc}
+         * </p>
+         * 
+         * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException)
+         */
+        @Override
+        public void warning( SAXParseException warning ) {
+            context.getLogger(XmlSequencer.class).warn(warning, XmlSequencerI18n.warningSequencingXmlDocument);
+            monitor.getProblems().addWarning(warning, XmlSequencerI18n.warningSequencingXmlDocument, warning);
+        }
+    }
+
+    private class IndexedName {
+
+        Map<Name, List<IndexedName>> nameToIndexedNamesMap = new HashMap<Name, List<IndexedName>>();
+
+        IndexedName() {
+        }
+    }
+}

Added: trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerI18n.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerI18n.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerI18n.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+import java.util.Locale;
+import java.util.Set;
+import org.jboss.dna.common.CommonI18n;
+import org.jboss.dna.common.i18n.I18n;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public final class XmlSequencerI18n {
+
+    public static I18n errorSequencingXmlDocument;
+    public static I18n fatalErrorSequencingXmlDocument;
+    public static I18n sequencingXmlDocument;
+    public static I18n canceledSequencingXmlDocument;
+    public static I18n warningSequencingXmlDocument;
+
+    static {
+        try {
+            I18n.initialize(XmlSequencerI18n.class);
+        } catch (final Exception err) {
+            System.err.println(err);
+        }
+    }
+
+    public static Set<Locale> getLocalizationProblemLocales() {
+        return I18n.getLocalizationProblemLocales(CommonI18n.class);
+    }
+
+    public static Set<String> getLocalizationProblems() {
+        return I18n.getLocalizationProblems(CommonI18n.class);
+    }
+
+    public static Set<String> getLocalizationProblems( Locale locale ) {
+        return I18n.getLocalizationProblems(CommonI18n.class, locale);
+    }
+}

Added: trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/XmlSequencerI18n.properties
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/XmlSequencerI18n.properties	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/XmlSequencerI18n.properties	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,27 @@
+#
+# JBoss, Home of Professional Open Source.
+# Copyright 2008, Red Hat Middleware LLC, and individual contributors
+# as indicated by the @author tags. See the copyright.txt file in the
+# distribution for a full listing of individual contributors.
+#
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this software; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+#
+errorSequencingXmlDocument = An error was received while sequencing XML: {0}
+fatalErrorSequencingXmlDocument = A fatal error was received while sequencing XML: {0}
+sequencingXmlDocument = Sequencing XML
+canceledSequencingXmlDocument = Canceled sequencing XML
+warningSequencingXmlDocument = A warning was received while sequencing XML: {0}
+

Added: trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/xml.cnd
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/xml.cnd	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/main/resources/org/jboss/dna/sequencer/xml/xml.cnd	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+ 
+//------------------------------------------------------------------------------
+// N A M E S P A C E S
+//------------------------------------------------------------------------------
+<jcr='http://www.jcp.org/jcr/1.0'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+<mix='http://www.jcp.org/jcr/mix/1.0'>
+<dnaxml='http://www.jboss.org/dna/xml/1.0'>
+<dnadtd='http://www.jboss.org/dna/dtd/1.0'>
+
+// ----------------------------------------------------------
+// JCR Pre-defined Mixin Types that are not loaded by default
+// ----------------------------------------------------------
+
+[mix:mimeType] mixin 
+  - jcr:mimeType (string)  
+  - jcr:encoding (string)
+
+
+//------------------------------------------------------------------------------
+// N O D E T Y P E S
+//------------------------------------------------------------------------------
+
+[dnaxml:document] > nt:unstructured, mix:mimeTyped
+  - dnaxml:cDataContent (string)
+
+[dnaxml:comment] > nt:unstructured, mix:mimeTyped
+  - dnaxml:commentContent (string)
+ 
+[dnaxml:element] > nt:unstructured, mix:mimeTyped
+  - dnaxml:elementContent (string)
+ 
+[dnaxml:cData] > nt:unstructured, mix:mimeTyped
+  - dnaxml:cDataContent (string)
+ 
+[dnaxml:processingInstruction] > nt:unstructured, mix:mimeTyped
+  - dnaxml:processingInstruction (string)
+  - dnaxml:target (string)
+
+ 
+[dnadtd:entity] > nt:unstructured, mix:mimeTyped
+  - dnaxml:name (string)
+  - dnaxml:value (string)
+  - dnaxml:publicId (string)
+  - dnaxml:systemId (string)
+ 
+ 
\ No newline at end of file

Added: trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,222 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import org.jboss.dna.common.monitor.ProgressMonitor;
+import org.jboss.dna.common.monitor.SimpleProgressMonitor;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.sequencers.MockSequencerContext;
+import org.jboss.dna.graph.sequencers.MockSequencerOutput;
+import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.jboss.dna.sequencer.xml.XmlSequencer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author John Verhaeg
+ */
+public class XmlSequencerTest {
+
+    private static final String CDATA = "dnaxml:cData";
+    private static final String CDATA_CONTENT = "dnaxml:cDataContent";
+    private static final String COMMENT = "dnaxml:comment";
+    private static final String COMMENT_CONTENT = "dnaxml:commentContent";
+    private static final String DOCUMENT = "dnaxml:document";
+    private static final String DTD_NAME = "dnadtd:name";
+    private static final String DTD_PUBLIC_ID = "dnadtd:publicId";
+    private static final String DTD_SYSTEM_ID = "dnadtd:systemId";
+    private static final String DTD_VALUE = "dnadtd:value";
+    private static final String ELEMENT_CONTENT = "dnaxml:elementContent";
+    private static final String ENTITY = "dnadtd:entity";
+    private static final String PI = "dnaxml:processingInstruction";
+    private static final String PI_CONTENT = "dnaxml:processingInstructionContent";
+    private static final String TARGET = "dnaxml:target";
+
+    private XmlSequencer sequencer;
+    private InputStream stream;
+    private MockSequencerOutput output;
+    private ProgressMonitor monitor;
+    private URL xml1;
+    private URL xml2;
+    private URL xml3;
+    private URL xml4;
+    private URL xsd;
+    private SequencerContext context;
+
+    @Before
+    public void beforeEach() {
+        sequencer = new XmlSequencer();
+        context = new MockSequencerContext();
+        output = new MockSequencerOutput(context);
+        monitor = new SimpleProgressMonitor("Test activity");
+        xml1 = this.getClass().getClassLoader().getResource("jackrabbitInMemoryTestRepositoryConfig.xml");
+        assertThat(xml1, is(notNullValue()));
+        xml2 = this.getClass().getClassLoader().getResource("master.xml");
+        assertThat(xml2, is(notNullValue()));
+        xml3 = this.getClass().getClassLoader().getResource("CurrencyFormatterExample.mxml");
+        assertThat(xml3, is(notNullValue()));
+        xml4 = this.getClass().getClassLoader().getResource("plugin.xml");
+        assertThat(xml4, is(notNullValue()));
+        xsd = this.getClass().getClassLoader().getResource("Descriptor.1.0.xsd");
+        assertThat(xsd, is(notNullValue()));
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        if (stream != null) {
+            try {
+                stream.close();
+            } finally {
+                stream = null;
+            }
+        }
+    }
+
+    @Test
+    public void shouldSequenceXml() throws IOException {
+        verifyDocument(xml1);
+        verifyName(COMMENT + "[1]", "jcr:primaryType", COMMENT);
+        String text = verify(COMMENT + "[1]", COMMENT_CONTENT, String.class);
+        assertThat(text.startsWith("\n   Licensed to the Apache Software Foundation (ASF)"), is(true));
+        assertThat(text.endsWith("   limitations under the License.\n"), is(true));
+        verifyString("/", DTD_NAME, "Repository");
+        verifyString("/", DTD_PUBLIC_ID, "-//The Apache Software Foundation//DTD Jackrabbit 1.2//EN");
+        verifyString("/", DTD_SYSTEM_ID, "http://jackrabbit.apache.org/dtd/repository-1.2.dtd");
+        verifyName(COMMENT + "[2]", "jcr:primaryType", COMMENT);
+        verifyString(COMMENT + "[2]", COMMENT_CONTENT, " Example Repository Configuration File ");
+        verifyName("Repository[1]", "jcr:primaryType", "nt:unstructured");
+        verifyName("Repository[1]/" + COMMENT + "[1]", "jcr:primaryType", COMMENT);
+    }
+
+    @Test
+    public void shouldHandleNamespaces() throws IOException {
+        verifyDocument(xml2);
+        verifyName("book[1]/bookinfo[1]/xi:include[1]", "jcr:primaryType", "nt:unstructured");
+        verifyString("book[1]/bookinfo[1]/xi:include[1]", "xi:href", "Author_Group.xml");
+        verifyName("book[1]/bookinfo[1]/xi:include[2]", "jcr:primaryType", "nt:unstructured");
+        verifyString("book[1]/bookinfo[1]/xi:include[2]", "xi:href", "Legal_Notice.xml");
+    }
+
+    @Test
+    public void shouldSequenceEntityDeclarations() throws IOException {
+        verifyDocument(xml2);
+        verifyName(ENTITY + "[1]", "jcr:primaryType", ENTITY);
+        verifyString(ENTITY + "[1]", DTD_NAME, "%RH-ENTITIES");
+        verifyString(ENTITY + "[1]", DTD_SYSTEM_ID, "Common_Config/rh-entities.ent");
+        verifyName(ENTITY + "[2]", "jcr:primaryType", ENTITY);
+        verifyString(ENTITY + "[2]", DTD_NAME, "versionNumber");
+        verifyString(ENTITY + "[2]", DTD_VALUE, "0.1");
+        verifyName(ENTITY + "[3]", "jcr:primaryType", ENTITY);
+        verifyString(ENTITY + "[3]", DTD_NAME, "copyrightYear");
+        verifyString(ENTITY + "[3]", DTD_VALUE, "2008");
+    }
+
+    @Test
+    public void shouldSequenceElementContent() throws IOException {
+        verifyDocument(xml2);
+        verifyString("book[1]/chapter[4]/sect1[1]/para[8]/" + ELEMENT_CONTENT + "[1]",
+                     ELEMENT_CONTENT,
+                     "The path expression is more complicated."
+                     + " Sequencer path expressions are used by the sequencing service to determine whether a particular changed node should be sequenced."
+                     + " The expressions consist of two parts: a selection criteria and an output expression."
+                     + " Here's a simple example:");
+        verifyString("book[1]/chapter[4]/sect1[1]/para[8]/programlisting[1]/" + ELEMENT_CONTENT + "[1]",
+                     ELEMENT_CONTENT,
+                     "/a/b/c at title =&gt; /d/e/f");
+    }
+
+    @Test
+    public void shouldSequenceCData() throws IOException {
+        verifyDocument(xml3);
+        verifyString("mx:Application[1]/mx:Script[1]/" + CDATA + "[1]",
+                     CDATA_CONTENT,
+                     "\n\n" + "              import mx.events.ValidationResultEvent;\t\t\t\n"
+                     + "              private var vResult:ValidationResultEvent;\n" + "\t\t\t\n"
+                     + "              // Event handler to validate and format input.\n"
+                     + "              private function Format():void {\n" + "              \n"
+                     + "                    vResult = numVal.validate();\n\n"
+                     + "                    if (vResult.type==ValidationResultEvent.VALID) {\n"
+                     + "                        var temp:Number=Number(priceUS.text); \n"
+                     + "                        formattedUSPrice.text= usdFormatter.format(temp);\n" + "                    }\n"
+                     + "                    \n" + "                    else {\n"
+                     + "                       formattedUSPrice.text=\"\";\n" + "                    }\n" + "              }\n"
+                     + "        ");
+    }
+
+    @Test
+    public void shouldSequenceProcessingInstructions() throws IOException {
+        verifyDocument(xml4);
+        verifyName(PI + "[1]", "jcr:primaryType", PI);
+        verifyString(PI + "[1]", TARGET, "eclipse");
+        verifyString(PI + "[1]", PI_CONTENT, "version=\"3.0\"");
+    }
+
+    @Test
+    public void shouldSequenceXsds() throws IOException {
+        verifyDocument(xsd);
+        verifyName("xs:schema[1]", "jcr:primaryType", "nt:unstructured");
+        verifyString("xs:schema[1]", "xs:targetNamespace", "http://ns.adobe.com/air/application/1.0");
+        verifyString("xs:schema[1]", "xs:elementFormDefault", "qualified");
+        verifyName("xs:schema[1]/xs:element[1]", "jcr:primaryType", "nt:unstructured");
+        verifyString("xs:schema[1]/xs:element[1]", "xs:name", "application");
+    }
+
+    private <T> T verify( String nodePath,
+                          String property,
+                          Class<T> expectedClass ) {
+        Object[] values = output.getPropertyValues(nodePath.length() == 0 ? "." : nodePath, property);
+        assertThat(values, notNullValue());
+        assertThat(values.length, is(1));
+        Object value = values[0];
+        assertThat(value, instanceOf(expectedClass));
+        return expectedClass.cast(value);
+    }
+
+    private void verifyDocument( URL url ) throws IOException {
+        stream = url.openStream();
+        assertThat(stream, is(notNullValue()));
+        sequencer.sequence(stream, output, context, monitor);
+        verifyName("", "jcr:primaryType", DOCUMENT);
+    }
+
+    private void verifyName( String nodePath,
+                             String property,
+                             String expectedName ) {
+        Name name = verify(nodePath, property, Name.class);
+        assertThat(name, is(context.getValueFactories().getNameFactory().create(expectedName)));
+    }
+
+    private void verifyString( String nodePath,
+                               String property,
+                               String expectedString ) {
+        String string = verify(nodePath, property, String.class);
+        assertThat(string, is(expectedString));
+    }
+}

Added: trunk/extensions/dna-sequencer-xml/src/test/resources/CurrencyFormatterExample.mxml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/CurrencyFormatterExample.mxml	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/CurrencyFormatterExample.mxml	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Simple example to demonstrate the CurrencyFormatter. -->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
+
+    <mx:Script>
+        <![CDATA[
+
+              import mx.events.ValidationResultEvent;			
+              private var vResult:ValidationResultEvent;
+			
+              // Event handler to validate and format input.
+              private function Format():void {
+              
+                    vResult = numVal.validate();
+
+                    if (vResult.type==ValidationResultEvent.VALID) {
+                        var temp:Number=Number(priceUS.text); 
+                        formattedUSPrice.text= usdFormatter.format(temp);
+                    }
+                    
+                    else {
+                       formattedUSPrice.text="";
+                    }
+              }
+        ]]>
+    </mx:Script>
+
+    <mx:CurrencyFormatter id="usdFormatter" precision="2" 
+        currencySymbol="$" decimalSeparatorFrom="."
+        decimalSeparatorTo="." useNegativeSign="true" 
+        useThousandsSeparator="true" alignSymbol="left"/>
+
+    <mx:NumberValidator id="numVal" source="{priceUS}" property="text" 
+        allowNegative="true" domain="real"/>
+
+    <mx:Panel title="CurrencyFormatter Example" width="75%" height="75%" 
+        paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
+
+        <mx:Form>
+            <mx:FormItem label="Enter U.S. dollar amount:">
+                <mx:TextInput id="priceUS" text="" width="50%"/>
+            </mx:FormItem>
+
+            <mx:FormItem label="Formatted amount: ">
+                <mx:TextInput id="formattedUSPrice" text="" width="50%" editable="false"/>
+            </mx:FormItem>
+
+            <mx:FormItem>
+                <mx:Button label="Validate and Format" click="Format();"/>
+            </mx:FormItem>
+        </mx:Form>
+
+    </mx:Panel>
+</mx:Application>

Added: trunk/extensions/dna-sequencer-xml/src/test/resources/Descriptor.1.0.xsd
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/Descriptor.1.0.xsd	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/Descriptor.1.0.xsd	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<xs:schema 
+    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
+    targetNamespace="http://ns.adobe.com/air/application/1.0" 
+    xmlns="http://ns.adobe.com/air/application/1.0" 
+    elementFormDefault="qualified"
+>
+  <xs:element name="application">
+    <xs:complexType>
+      <xs:all>
+        <!-- About this application -->
+        <xs:element name="id">
+          <xs:simpleType>
+            <xs:restriction base="xs:string">
+              <xs:pattern value="[A-Za-z0-9\-\.]{1,212}"/>
+            </xs:restriction>
+          </xs:simpleType>
+        </xs:element>
+        <xs:element name="name"           type="xs:string" minOccurs="0"/>
+        <xs:element name="version"        type="xs:string"/>
+        <xs:element name="filename">
+          <xs:simpleType>
+            <xs:restriction base="xs:string">
+              <!-- name cannot begin with a ' ' (space), have any of these characters: *"/:<>?\|, and end with a . (dot) or ' ' (space) -->
+              <xs:pattern value='[^\*"/:&gt;&lt;\?\\\|\. ]|[^\*"/:&gt;&lt;\?\\\| ][^\*"/:&gt;&lt;\?\\\|]*[^\*"/:&gt;&lt;\?\\\|\. ]'/>
+            </xs:restriction>
+          </xs:simpleType>
+        </xs:element>
+        <xs:element name="description"    type="xs:string" minOccurs="0"/>
+        <xs:element name="copyright"      type="xs:string" minOccurs="0"/>
+        <xs:element name="icon" type="IconType" minOccurs="0"/>
+
+        <!-- How to start this application -->
+        <xs:element name="initialWindow">
+          <xs:complexType>
+            <xs:all>
+              <xs:element name="content" type="xs:anyURI" minOccurs="1" />
+              <xs:element name="title" type="xs:string" minOccurs="0" />
+
+              <xs:element name="systemChrome" minOccurs="0" >
+                <xs:simpleType>
+                  <xs:restriction base="xs:string">
+                    <xs:enumeration value="none"/>
+                    <xs:enumeration value="standard"/>
+                  </xs:restriction>
+                </xs:simpleType>
+              </xs:element>
+              <xs:element name="transparent" type="xs:boolean" minOccurs="0" />
+              <xs:element name="visible" type="xs:boolean" minOccurs="0" />
+
+              <xs:element name="minimizable" type="xs:boolean" minOccurs="0" />
+              <xs:element name="maximizable" type="xs:boolean" minOccurs="0" />
+              <xs:element name="resizable" type="xs:boolean" minOccurs="0" />
+
+              <xs:element name="x" type="xs:int" minOccurs="0" />
+              <xs:element name="y" type="xs:int" minOccurs="0" />
+              <xs:element name="width" type="xs:unsignedInt" minOccurs="0" />
+              <xs:element name="height" type="xs:unsignedInt" minOccurs="0" />
+              <xs:element name="minSize" type="BoundsSizeType" minOccurs="0" />
+              <xs:element name="maxSize" type="BoundsSizeType" minOccurs="0" />
+            </xs:all>
+          </xs:complexType>
+        </xs:element>
+        
+        <!-- About installing this application -->
+        <xs:element name="installFolder" minOccurs="0">
+          <xs:simpleType>
+            <xs:restriction base="xs:string">
+              <!-- installFolder cannot begin with a / (forward-slash) or a ' ' (space), have any of these characters: *":<>?\|, and end with a . (dot) or ' ' (space) -->
+              <xs:pattern value='[^\*"/:&gt;&lt;\?\\\|\. ]|[^\*"/:&gt;&lt;\?\\\| ][^\*":&gt;&lt;\?\\\|]*[^\*":&gt;&lt;\?\\\|\. ]'/>
+            </xs:restriction>
+          </xs:simpleType>
+        </xs:element>
+        <xs:element name="programMenuFolder" minOccurs="0">
+          <xs:simpleType>
+            <xs:restriction base="xs:string">
+              <!-- programMenuFolder cannot begin with a / (forward-slash) or a ' ' (space), have any of these characters: *":<>?\|, and end with a . (dot) or ' ' (space) -->
+              <xs:pattern value='[^\*"/:&gt;&lt;\?\\\|\. ]|[^\*"/:&gt;&lt;\?\\\| ][^\*":&gt;&lt;\?\\\|]*[^\*":&gt;&lt;\?\\\|\. ]'/>
+            </xs:restriction>
+          </xs:simpleType>
+        </xs:element>        
+
+        <!-- Features this application can opt in to -->
+        <xs:element name="customUpdateUI" type="xs:boolean" minOccurs="0"/>
+        <xs:element name="allowBrowserInvocation" type="xs:boolean" minOccurs="0"/>
+        <xs:element name="fileTypes" minOccurs="0">
+          <xs:complexType>
+            <xs:sequence>                    
+              <xs:element name="fileType" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:all>
+                  <xs:element name="name" type="xs:string"/>
+                  <xs:element name="extension" type="xs:string"/>
+                  <xs:element name="description" type="xs:string" minOccurs="0"/>
+                  <xs:element name="contentType" type="xs:string" minOccurs="0"/>
+                  <xs:element name="icon" type="IconType" minOccurs="0"/>
+                </xs:all>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </xs:all>
+
+      <!-- About the runtime version required -->
+      <xs:attribute name="minimumPatchLevel" type="xs:unsignedInt"/>
+    </xs:complexType>
+  </xs:element>
+
+  <!-- Type definitions -->
+  <xs:complexType name="IconType">
+      <xs:all>
+          <xs:element name="image16x16"   type="xs:anyURI" minOccurs="0"/>
+          <xs:element name="image32x32"   type="xs:anyURI" minOccurs="0"/>
+          <xs:element name="image48x48"   type="xs:anyURI" minOccurs="0"/>
+          <xs:element name="image128x128" type="xs:anyURI" minOccurs="0"/>
+      </xs:all>
+  </xs:complexType>
+  <xs:simpleType name="UnsignedIntListType">
+    <xs:list itemType="xs:unsignedInt"/>
+  </xs:simpleType>
+  <xs:simpleType name="BoundsSizeType">
+    <xs:restriction base="UnsignedIntListType">
+      <xs:length value="2"/> 
+    </xs:restriction>
+  </xs:simpleType>
+</xs:schema>

Added: trunk/extensions/dna-sequencer-xml/src/test/resources/jackrabbitInMemoryTestRepositoryConfig.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/jackrabbitInMemoryTestRepositoryConfig.xml	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/jackrabbitInMemoryTestRepositoryConfig.xml	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<!--
+   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.
+-->
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.2//EN"
+                            "http://jackrabbit.apache.org/dtd/repository-1.2.dtd">
+<!-- Example Repository Configuration File -->
+<Repository>
+    <!--
+        virtual file system where the repository stores global state
+        (e.g. registered namespaces, custom node types, etc.)
+    -->
+    <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem">
+        <param name="path" value="${rep.home}/repository"/>
+    </FileSystem>
+
+    <!--
+        security configuration
+    -->
+    <Security appName="Jackrabbit">
+        <!--
+            access manager:
+            class: FQN of class implementing the AccessManager interface
+        -->
+        <AccessManager class="org.apache.jackrabbit.core.security.SimpleAccessManager">
+            <!-- <param name="config" value="${rep.home}/access.xml"/> -->
+        </AccessManager>
+
+        <LoginModule class="org.apache.jackrabbit.core.security.SimpleLoginModule">
+           <!-- anonymous user name ('anonymous' is the default value) -->
+           <param name="anonymousId" value="anonymous"/>
+           <!--
+              default user name to be used instead of the anonymous user
+              when no login credentials are provided (unset by default)
+           -->
+           <!-- <param name="defaultUserId" value="superuser"/> -->
+        </LoginModule>
+    </Security>
+
+    <!--
+        location of workspaces root directory and name of default workspace
+    -->
+    <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default"/>
+    <!--
+        workspace configuration template:
+        used to create the initial workspace if there's no workspace yet
+    -->
+    <Workspace name="Jackrabbit Core">
+        <!--
+            virtual file system of the workspace:
+            class: FQN of class implementing the FileSystem interface
+        -->
+
+        <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem">
+            <param name="path" value="${wsp.home}"/>
+        </FileSystem>
+        <!--
+            persistence manager of the workspace:
+            class: FQN of class implementing the PersistenceManager interface
+        -->
+        <PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager">
+          <param name="persistent" value="false"/>
+        </PersistenceManager>
+        <!--
+            Search index and the file system it uses.
+            class: FQN of class implementing the QueryHandler interface
+        -->
+        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+            <param name="path" value="${wsp.home}/index"/>
+        </SearchIndex>
+    </Workspace>
+
+    <!--
+        Configures the versioning
+    -->
+    <Versioning rootPath="${rep.home}/version">
+        <!--
+            Configures the filesystem to use for versioning for the respective
+            persistence manager
+        -->
+        <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem">
+            <param name="path" value="${rep.home}/version" />
+        </FileSystem>
+
+        <!--
+            Configures the persistence manager to be used for persisting version state.
+            Please note that the current versioning implementation is based on
+            a 'normal' persistence manager, but this could change in future
+            implementations.
+        -->
+        <PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager">
+          <param name="persistent" value="false"/>
+        </PersistenceManager>
+    </Versioning>
+
+    <!--
+        Search index for content that is shared repository wide
+        (/jcr:system tree, contains mainly versions)
+    -->
+    <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+        <param name="path" value="${rep.home}/repository/index"/>
+    </SearchIndex>
+</Repository>

Added: trunk/extensions/dna-sequencer-xml/src/test/resources/log4j.properties
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/log4j.properties	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/log4j.properties	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,12 @@
+# Direct log messages to stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %m%n
+
+# Root logger option
+log4j.rootLogger=INFO, stdout
+
+# Set up the default logging to be INFO level, then override specific units
+log4j.logger.org.jboss.dna=INFO
+

Added: trunk/extensions/dna-sequencer-xml/src/test/resources/master.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/master.xml	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/master.xml	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,1890 @@
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~
+  ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+  ~ indicated by the @author tags or express copyright attribution
+  ~ statements applied by the authors.  All third-party contributions are
+  ~ distributed under license by Red Hat Middleware LLC.
+  ~
+  ~ This copyrighted material is made available to anyone wishing to use, modify,
+  ~ copy, or redistribute it subject to the terms and conditions of the GNU
+  ~ Lesser General Public License, as published by the Free Software Foundation.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+  ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+  ~ for more details.
+  ~
+  ~ You should have received a copy of the GNU Lesser General Public License
+  ~ along with this distribution; if not, write to:
+  ~ Free Software Foundation, Inc.
+  ~ 51 Franklin Street, Fifth Floor
+  ~ Boston, MA  02110-1301  USA
+  -->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!ENTITY % RH-ENTITIES SYSTEM "Common_Config/rh-entities.ent">
+<!ENTITY versionNumber "0.1">
+<!ENTITY copyrightYear "2008">
+<!ENTITY copyrightHolder "Red Hat Middleware, LLC.">]>
+<book>
+  <bookinfo>
+    <title>JBoss DNA</title>
+    <subtitle>Getting Started Guide</subtitle>
+    <releaseinfo>&versionNumber;
+    </releaseinfo>
+    <productnumber>&versionNumber;
+    </productnumber>
+    <issuenum>1</issuenum>
+    <mediaobject>
+      <imageobject role="fo">
+        <imagedata fileref="images/dna-logo.png" align="center" />
+      </imageobject>
+      <imageobject role="pdf">
+        <imagedata fileref="images/dna-logo.png" scale="75" align="center" />
+      </imageobject>
+      <imageobject role="html">
+        <imagedata fileref="images/dna-logo.png" depth="3cm" />
+      </imageobject>
+      <imageobject role="xhtml">
+        <imagedata fileref="images/dna-logo.png" depth="3cm" />
+      </imageobject>
+      <imageobject role="xhtml_single">
+        <imagedata fileref="images/dna-logo.png" depth="3cm" />
+      </imageobject>
+    </mediaobject>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml" />
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Legal_Notice.xml" />
+  </bookinfo>
+  <preface id="preface" revision="1">
+    <title>What this book covers</title>
+    <para>The goal of this book is to help you learn about JBoss DNA and how you can use it in your own applications to get the
+      most out of your JCR repositories.</para>
+    <para>The first part of the book starts out with an introduction to content repositories and an overview of the JCR API,
+      both of which are important aspects of JBoss DNA. This is followed by an overview of the JBoss DNA project, its
+      architecture, and a basic roadmap for what's coming next.</para>
+    <para>The next part of the book covers how to download and build the examples, how to use JBoss DNA with existing
+      repositories, and how to build and use custom sequencers.</para>
+    <para>
+      If you have any questions or comments, please feel free to contact JBoss DNA's
+      <ulink url="mailto:dna-users at jboss.org">user mailing list</ulink>
+      or use the
+      <ulink url="http://www.jboss.com/index.html?module=bb&amp;op=viewforum&amp;f=272">user forums</ulink>
+      . If you'd like to get involved on the project, join the
+      <ulink url="http://www.jboss.org/dna/lists.html">mailing lists</ulink>
+      ,
+      <ulink url="http://www.jboss.org/dna/subversion.html">download the code</ulink>
+      and get it building, and visit our
+      <ulink url="http://jira.jboss.org/jira/browse/DNA">JIRA issue management system</ulink>
+      . If there's something in particular you're interested in, talk with the community - there may be others interested in the
+      same thing.
+    </para>
+  </preface>
+  <chapter id="introduction">
+    <title>Introduction</title>
+    <para>There are a lot of choices for how applications can store information persistently so that it can be accessed at a
+      later time and by other processes. The challenge developers face is how to use an approach that most closely matches the
+      needs of their application. This choice becomes more important as developers choose to focus their efforts on
+      application-specific logic, delegating much of the responsibilities for persistence to libraries and frameworks.</para>
+    <para>
+      Perhaps one of the easiest techniques is to simply store information in
+      <emphasis>files</emphasis>
+      . The Java language makes working with files relatively easy, but Java really doesn't provide many bells and whistles. So
+      using files is an easy choice when the information is either not complicated (for example property files), or when users may
+      need to read or change the information outside of the application (for example log files or configuration files). But using
+      files to persist information becomes more difficult as the information becomes more complex, as the volume of it increases,
+      or if it needs to be accessed by multiple processes. For these situations, other techniques often offer better choices.
+    </para>
+    <para>
+      Another technique built into the Java language is
+      <emphasis>Java serialization</emphasis>
+      , which is capable of persisting the state of an object graph so that it can be read back in at a later time. However, Java
+      serialization can quickly become tricky if the classes are changed, and so it's beneficial usually when the information is
+      persisted for a very short period of time. For example, serialization is sometimes used to send an object graph from one
+      process to another.
+    </para>
+    <para>
+      One of the more popular persistence technologies is the
+      <emphasis>relational database</emphasis>
+      . Relational database management systems have been around for decades and are very capable. The Java Database Connectivity
+      (JDBC) API provides a standard interface for connecting to and interacting with relational databases. However, it is a
+      low-level API that requires a lot of code to use correctly, and it still doesn't abstract away the DBMS-specific SQL
+      grammar. Also, working with relational data in an object-oriented language can feel somewhat unnatural, so many developers
+      map this data to classes that fit much more cleanly into their application. The problem is that manually creating this
+      mapping layer requires a lot of repetitive and non-trivial JDBC code.
+    </para>
+    <para>
+      <emphasis>Object-relational mapping</emphasis>
+      libraries automate the creation of this mapping layer and result in far less code that is much more maintainable with
+      performance that is often as good as (if not better than) handwritten JDBC code. The new
+      <ulink url="http://java.sun.com/developer/technicalArticles/J2EE/jpa/">Java Persistence API (JPA)</ulink>
+      provide a standard mechanism for defining the mappings (through annotations) and working with these entity objects. Several
+      commercial and open-source libraries implement JPA, and some even offer additional capabilities and features that go beyond
+      JPA. For example,
+      <ulink url="http://www.hibernate.org">Hibernate</ulink>
+      is one of the most feature-rich JPA implementations and offers object caching, statement caching, extra association
+      mappings, and other features that help to improve performance and usefulness.
+    </para>
+    <para>
+      While relational databases and JPA are solutions that work for many applications, they become more limited in cases when the
+      information structure is highly flexible, is not known
+      <emphasis>a priori</emphasis>
+      , or is subject to frequent change and customization. In these situations,
+      <emphasis>content repositories</emphasis>
+      may offer a better choice for persistence. Content repositories are almost a hybrid between relational databases and file
+      systems, and typically provide other capabilities as well, including versioning, indexing, search, access control,
+      transactions, and observation. Because of this, content repositories are used by content management systems (CMS), document
+      management systems (DMS), and other applications that manage electronic files (e.g., documents, images, multi-media, web
+      content, etc.) and metadata associated with them (e.g., author, date, status, security information, etc.). The
+      <ulink url="http://www.jcp.org/en/jsr/detail?id=170">Content Repository for Java technology API</ulink>
+      provides a standard Java API for working with content repositories. Abbreviated "JCR", this API was developed as part of the
+      Java Community Process under
+      <ulink url="http://www.jcp.org/en/jsr/detail?id=170">JSR-170</ulink>
+      and is being revised under
+      <ulink url="http://www.jcp.org/en/jsr/detail?id=283">JSR-283</ulink>
+      .
+    </para>
+    <para>
+      The
+      <emphasis>JBoss DNA project</emphasis>
+      is building the tools and services that surround content repositories. Nearly all of these capabilities are to be hidden
+      below the JCR API and involve automated processing of the information in the repository. Thus, JBoss DNA can add value to
+      existing repository implementations. For example, JCR repositories offer the ability to upload files into the repository and
+      have the file content indexed for search purposes. JBoss DNA also defines a library for "sequencing" content - to extract
+      meaningful information from that content and store it in the repository, where it can then be searched, accessed, and
+      analyzed using the JCR API.
+    </para>
+    <para> JBoss DNA is building other features as well. One goal of JBoss DNA is to create federated repositories that
+      dynamically merge the information from multiple databases, services, applications, and other JCR repositories. Another is to
+      create customized views based upon the type of data and the role of the user that is accessing the data. And yet another is
+      to create a REST-ful API to allow the JCR content to be accessed easily by other applications written in other languages.
+    </para>
+    <para>
+      The
+      <link linkend="jboss_dna">next chapter</link>
+      in this book goes into more detail about JBoss DNA and its architecture, the different components, what's available now, and
+      what's coming in future releases.
+      <link linkend="downloading_and_running">Chapter 3</link>
+      then provides instructions for downloading and running the sequencer examples for the current release.
+      <link linkend="using_dna">Chapter 4</link>
+      walks through how to use JBoss DNA in your applications, while
+      <link linkend="custom_sequencers">Chapter 5</link>
+      goes over how to create custom sequencers. Finally,
+      <link linkend="future_directions">Chapter 6</link>
+      wraps things up with a discussion about the future of JBoss DNA.
+    </para>
+  </chapter>
+  <chapter id="jboss_dna">
+    <title>Understanding JBoss DNA</title>
+    <sect1 id="jboss_dna_overview">
+      <title>Overview</title>
+      <para>JBoss DNA is a repository and set of tools that make it easy to capture, version, analyze, and understand the
+        fundamental building blocks of information. As models, service and process definitions, schemas, source code, and other
+        artifacts are added to the repository, JBoss DNA "sequences" the makeup of these components and extracts their structure
+        and interdependencies. The JBoss DNA web application allows end users to access, visualize, and edit this information in
+        the terminology and structure they are familiar with. Such domain-specific solutions can be easily created with little or
+        no programming.</para>
+      <para> JBoss DNA supports the Java Content Repository (JCR) standard and is able to provide a single integrated view of
+        multiple repositories, external databases, services, and applications, ensuring that JBoss DNA has access to the latest
+        and most reliable master data. For instance, DNA could provide in a single view valuable insight into the business
+        processes and process-level services impacted by a change to in an intermediary web server operation defined via WSDL.
+        Similarly, a user could quickly view and navigate the dependencies between the data source models and transformation
+        information stored within a content repository, the code base stored within a version control system, and the database
+        schemas used by an application.</para>
+    </sect1>
+    <sect1 id="architecture">
+      <title>Architecture</title>
+      <para>The architecture for JBoss DNA consists of several major components that will be built on top of standard APIs,
+        including JCR, JDBC, JNDI and HTTP. The goal is to allow these components to be assembled as needed and add value on top
+        of other DNA components or third-party systems that support these standard APIs.</para>
+      <mediaobject>
+        <imageobject role="fo">
+          <imagedata align="center" fileref="images/dna-architecture.png" />
+        </imageobject>
+        <imageobject role="html">
+          <imagedata align="center" fileref="images/dna-architecture.png" />
+        </imageobject>
+      </mediaobject>
+      <para>
+        As shown in the diagram above, the major components are (starting at the top):
+        <itemizedlist>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Eclipse Plugins</emphasis>
+              enable Eclipse users to access the contents of a JBoss DNA repository.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA JDBC Driver</emphasis>
+              provides a driver implementation, allowing JDBC-aware applications to connect to and use a JBoss DNA repository.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Remote JCR</emphasis>
+              is a client-side component for accessing remote JCR repositories.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Web Application</emphasis>
+              is used by end users and domain experts to visualize, search, edit, change and tag the repository content. The web
+              application uses views to define how different types of information are to be presented and edited in
+              domain-specific ways. The goal is that this web application is easily customized and branded for inclusion into
+              other solutions and application systems. The DNA Web Application operates upon any JCR-compliant repository,
+              although it does rely upon the DNA analysis and templating services.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Publishing Server</emphasis>
+              allows content to be downloaded, uploaded, and edited using the Atom Publishing Protocol. With the DNA Publishing
+              Server, the content of the repository can easily be created, read, edited, and deleted using the standard HTTP
+              operations of POST, GET, PUT, and DELETE (respectively). More and more tools are being created that support working
+              with Atom Publishing servers. The DNA Publishing Server operates upon any JCR-compliant repository.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA WebDAV Server</emphasis>
+              allows clients such as Microsoft Windows and Apple OS X to connect to, read, and edit the content in the repository
+              using the WebDAV standard. Since WebDAV is an extension of HTTP, web browsers are able to read (but not modify) the
+              content served by a WebDAV compliant server. The DNA WebDAV Server operates upon any JCR-compliant repository.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Sequencers</emphasis>
+              are pluggable components that make it possible for content to be uploaded to the repository and automatically
+              processed to extract meaningful structure and place that structure in the repository. Once this information is in
+              the repository, it can be viewed, edited, analyzed, searched, and related to other content. DNA defines a Java
+              interface that sequencers must implement. DNA sequencers operate upon any JCR-compliant repository.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Analyses</emphasis>
+              are pluggable components that analyze content and the relationships between content to generate reports or to answer
+              queries. DNA will include some standard analyzers, like dependency analysis and similarity analysis, that are
+              commonly needed by many different solutions. DNA analyzers operate upon any JCR-compliant repository.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Views</emphasis>
+              are definitions of how types of information are to be presented in a user interface to allow for creation, reading,
+              editing, and deletion of information. DNA view definitions consist of data stored in a JCR repository, and as such
+              views can be easily added, changed or removed entirely by using the DNA Web Application, requiring no programming.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Federation</emphasis>
+              is an implementation of the JCR API that builds the content within the repository by accessing and integrating
+              information from multiple sources. DNA Federation allows the integration of external systems, like other JCR
+              repositories, databases, applications, and services.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Connectors</emphasis>
+              are used to communicate with these external sources of information. In the federation engine, each source is able to
+              contribute node structure and node properties to any part of the federated graph, although typically many connectors
+              will contribute most of their information to isolated subgraphs. The result is that integration from a wide range of
+              systems can be integrated and accessed through the DNA Web Application, DNA Publishing Server, and DNA WebDAV
+              Server. Connectors also may optionally participate in distributed transactions by exposing an XAResource.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">DNA Maven</emphasis>
+              is a classloader library compatible with Maven 2 project dependencies. This allows the creation of Java ClassLoader
+              instances using Maven 2 style paths, and all dependencies are transitively managed and included.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+      <para>
+        Continue reading the rest of this chapter for more detail about the
+        <link linkend="sequencers">sequencing framework</link>
+        available in this release, or the
+        <link linkend="federation">federation engine</link>
+        and
+        <link linkend="federation_connectors">connectors</link>
+        that will be the focus of the next release. Or, skip to the
+        <link linkend="downloading_and_running">examples</link>
+        to see how to start using JBoss DNA &versionNumber;
+        today. 
+      </para>
+    </sect1>
+    <sect1 id="sequencers">
+      <title>Sequencing content</title>
+      <para> The current JBoss DNA release contains a sequencing framework that is designed to sequence data (typically files)
+        stored in a JCR repository to automatically extract meaningful and useful information. This additional information is then
+        saved back into the repository, where it can be accessed and used.</para>
+      <para> In other words, you can just upload various kinds of files into a JCR repository, and DNA automatically processes
+        those files to extract meaningful structured information. For example, load DDL files into the repository, and let
+        sequencers extract the structure and metadata for the database schema. Load Hibernate configuration files into the
+        repository, and let sequencers extract the schema and mapping information. Load Java source into the repository, and let
+        sequencers extract the class structure, JavaDoc, and annotations. Load a PNG, JPEG, or other image into the repository,
+        and let sequencers extract the metadata from the image and save it in the repository. The same with XSDs, WSDL, WS
+        policies, UML, MetaMatrix models, etc.</para>
+      <para>
+        JBoss DNA sequencers sit on top of existing JCR repositories (including federated repositories) - they basically extract
+        more useful information from what's already stored in the repository. And they use the existing JCR versioning system. Each
+        sequencer typically processes a single kind of file format or a single kind of content. </para>
+      <para>The following sequencers are included in JBoss DNA:
+        <itemizedlist>
+          <listitem>
+            <para>
+              <emphasis role="strong">Image sequencer</emphasis>
+              - A sequencer that processes the binary content of an image file, extracts the metadata for the image, and then
+              writes that image metadata to the repository. It gets the file format, image resolution, number of bits per pixel
+              (and optionally number of images), comments and physical resolution from JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM,
+              PGM, PPM, and PSD files. (This sequencer may be improved in the future to also extract EXIF metadata from JPEG
+              files; see
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
+              .)
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">MP3 sequencer</emphasis>
+              - A sequencer that processes the contents of an MP3 audio file, extracts the metadata for the file, and then
+              writes that image metadata to the repository. It gets the title, author, album, year, and comment.  
+              (This sequencer may be improved in the future to also extract other ID3 metadata from other audio file formats; see
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-66">DNA-26</ulink>
+              .)
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+      <para>
+        As the community develops additional sequencers, they will also be included in JBoss DNA. Some of those that have been
+        identified as being useful include:
+        <itemizedlist>
+          <listitem>
+            <para>
+              <emphasis role="strong">XML Schema Document (XSD) Sequencer</emphasis>
+              - Process XSD files and extract the various elements, attributes, complex types, simple types, groups, and other
+              information. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-32">DNA-32</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">Web Service Definition Language (WSDL) Sequencer</emphasis>
+              - Process WSDL files and extract the services, bindings, ports, operations, parameters, and other information. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-33">DNA-33</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">Hibernate File Sequencer</emphasis>
+              - Process Hibernate configuration (cfg.xml) and mapping (hbm.xml) files to extract the configuration and mapping
+              information. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-61">DNA-61</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">XML Metadata Interchange (XMI) Sequencer</emphasis>
+              - Process XMI documents that contain UML models or models using another metamodel, extracting the model structure
+              into the repository. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-31">DNA-31</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">ZIP Archive Sequencer</emphasis>
+              - Process ZIP archive files to extract (explode) the contents into the repository. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-63">DNA-63</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">Java Archive (JAR) Sequencer</emphasis>
+              - Process JAR files to extract (explode) the contents into the classes and file resources. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-64">DNA-64</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">Java Class File Sequencer</emphasis>
+              - Process Java class files (bytecode) to extract the class structure (including annotations) into the repository.
+              (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-62">DNA-62</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">Java Source File Sequencer</emphasis>
+              - Process Java source files to extract the class structure (including annotations) into the repository. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-51">DNA-51</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">PDF Sequencer</emphasis>
+              - Process PDF files to extract the document metadata, including table of contents. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-50">DNA-50</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">Maven 2 POM Sequencer</emphasis>
+              - Process Maven 2 Project Object Model (POM) files to extract the project information, dependencies, plugins, and
+              other content. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-24">DNA-24</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">Data Definition Language (DDL) Sequencer</emphasis>
+              - Process various dialects of DDL, including that from Oracle, SQL Server, MySQL, PostgreSQL, and others. May need
+              to be split up into a different sequencer for each dialect. (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
+              )
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis role="strong">MP3 and MP4 Sequencer</emphasis>
+              - Process MP3 and MP4 audio files to extract the name of the song, artist, album, track number, and other metadata.
+              (See
+              <ulink url="http://jira.jboss.org/jira/browse/DNA-30">DNA-30</ulink>
+              )
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+      <para>
+        The
+        <link linkend="using_dna">examples</link>
+        in this book go into more detail about how sequencers are managed and used, and
+        <link linkend="custom_sequencers">Chapter 5</link>
+        goes into detail about how to write custom sequencers.
+      </para>
+    </sect1>
+    <sect1 id="federation">
+      <title>Federating content</title>
+      <para>There is a lot of information stored in many of different places: databases, repositories, SCM systems,
+        registries, file systems, services, etc. The purpose of the federation engine is to allow applications to use the JCR API
+        to access that information as if it were all stored in a single JCR repository, but to really leave the information where
+        it is.</para>
+      <para>Why not just move the information into a JCR repository? Most likely there are existing applications that rely upon
+        that information being where it is. If we were to move it, then all those applications would break. Or they'd have to be
+        changed to use JCR. If the information is being used, the most practical thing is to leave it where it is.</para>
+      <para>
+        Then why not just copy the information into a JCR repository? Actually, there are times when it's perfectly reasonable to
+        make a copy of the data. Perhaps the system managing the existing information cannot handle the additional load of more
+        clients. Or, perhaps the information doesn't change, or it does change and we want snapshots that don't change. But more
+        likely, the data
+        <emphasis>does</emphasis>
+        change. So if applications are to use the most current information and we make copies of the data, we have to keep the
+        copies synchronized with the master. That's generally a lot of work.
+      </para>
+      <para>The JBoss DNA federation engine lets us leave the information where it is, yet lets client applications use the JCR
+        API to access all the information without caring where the information really exists. If the underlying information
+        changes, client applications using JCR observation will be notified of the changes. If a JBoss DNA federated repository is
+        configured to allow updates, client applications can change the information in the repository and JBoss DNA will propagate
+        those changes down to the original source.</para>
+      <sect2 id="federation_connectors">
+        <title>Connecting to information sources</title>
+        <para>
+          The JBoss DNA federation engine will use connectors to interact with different information sources to get at the content
+          in those systems. Some ideas for connectors include:
+          <itemizedlist>
+            <listitem>
+              <para>
+                <emphasis role="strong">JCR Repository Connector</emphasis>
+                - Connect to and interact with other JCR repositories.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis role="strong">File System Connector</emphasis>
+                - Expose the files and directories on a file system through JCR.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis role="strong">Maven 2 Repository Connector</emphasis>
+                - Access and expose the contents of a Maven 2 repository (either on the local file system or via HTTP) through
+                JCR.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis role="strong">JDBC Metadata Connector</emphasis>
+                - Connect to relational databases via JDBC and expose their schema as content in a repository.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis role="strong">UDDI Connector</emphasis>
+                - Interact with UDDI registries to integrate their content into a repository.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis role="strong">SVN Connector</emphasis>
+                - Interact with Subversion software configuration management (SCM) repositories to expose the managed resources
+                through JCR. Consider using the
+                <ulink url="http://svnkit.com/">SVNkit</ulink>
+                (dual license) library for an API into Subversion.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis role="strong">CVS Connector</emphasis>
+                - Interact with CVS software configuration management (SCM) repositories to expose the managed resources through
+                JCR.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis role="strong">JDBC Storage Connector</emphasis>
+                - Store and access information in a relational database. Also useful for persisting information in the federated
+                repository not stored elsewhere.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis role="strong">Distributed Database Connector</emphasis>
+                - Store and access information in a
+                <ulink url="http://www.hypertable.org/">Hypertable</ulink>
+                or
+                <ulink url="http://hadoop.apache.org/hbase/">HBase</ulink>
+                distributed databases. Also useful for persisting information in the federated repository not stored elsewhere.
+              </para>
+            </listitem>
+          </itemizedlist>
+        </para>
+        <para>
+          If the connectors allow the information they contribute to be updated, they must provide an
+          <code>XAResource</code>
+          implementation that can be used with a Java Transaction Service. Connectors that provide read-only access need not
+          provide an implementation.
+        </para>
+        <para>
+          Also, connectors talk to
+          <emphasis>sources</emphasis>
+          of information, and it's quite likely that the same connector is used to talk to different sources. Each source contains
+          the configuration details (e.g., connection information, location, properties, options, etc.) for working with that
+          particular source, as well as a reference to the connector that should be used to establish connections to the source.
+          And of course, sources can be added or removed without having to stop and restart the federated repository.
+        </para>
+      </sect2>
+      <sect2 id="federation_graph">
+        <title>Building the unified graph</title>
+        <para> The federation engine works by effectively building up a single graph by querying each source and merging or
+          unifying the responses. This information is cached, which improves performance, reduces the number of (potentially
+          expensive) remote calls, reduces the load on the sources, and helps mitigate problems with source availability. As
+          clients interact with the repository, this cache is consulted first. When the requested portion of the graph (or
+          "subgraph") is contained completely in the cache, it is retuned immediately. However, if any part of the requested
+          subgraph is not in the cache, each source is consulted for their contributions to that subgraph, and any results are
+          cached.</para>
+        <para> This basic flow makes it possible for the federated repository to build up a local cache of the integrated graph
+          (or at least the portions that are used by clients). In fact, the federated repository caches information in a manner
+          that is similar to that of the Domain Name System (DNS). As sources are consulted for their contributions, the source
+          also specifies whether it is the authoritative source for this information (some sources that are themselves federated
+          may not be the information's authority), whether the information may be modified, the time-to-live (TTL) value (the time
+          after which the cached information should be refreshed), and the expiration time (the time after which the cached
+          information is no longer valid). In effect, the source has complete control over how the information it contributes is
+          cached and used.</para>
+        <para>
+          The federated repository also needs to incorporate
+          <emphasis>negative caching</emphasis>
+          , which is storage of the knowledge that something does not exist. Sources can be configured to contribute information
+          only below certain paths (e.g.,
+          <code>/A/B/C</code>
+          ), and the federation engine can take advantage of this by never consulting that source for contributions to information
+          on other paths. However, below that path, any negative responses must also be cached (with appropriate TTL and expiry
+          parameters) to prevent the exclusion of that source (in case the source has information to contribute at a later time)
+          or the frequent checking with the source.
+        </para>
+      </sect2>
+      <sect2 id="federation_queries">
+        <title>Searching and querying</title>
+        <para> The JBoss DNA federated repository will also support queries against the integrated and unified graph. In some
+          situations the query can be determined to apply to a single source, but in most situations the query must be planned
+          (and possibly rewritten) such that it can be pushed down to all the appropriate sources. Also, the cached results must
+          be consulted prior to returning the query results, as the results from one source might have contributions from another
+          source.</para>
+        <note>
+          <para> It is hoped that the MetaMatrix query engine can be used for this purpose after it is open-sourced. This engine
+            implements sophisticated query planning and optimization techniques for working efficiently with multiple sources.
+          </para>
+        </note>
+        <para>Searching the whole federated repository is also important. This allows users to simply supply a handful of
+          search terms, and to get results that are ranked based upon how close each result is to the search terms. (Searching is
+          very different from querying, which involves specifying the exact semantics of what is to be searched and how the
+          information is to be compared.) JBoss DNA will incorporate a search engine (e.g., likely to be Lucene) and will populate
+          the engine's indexes using the federated content and the cached information. Notifications of changing information will
+          be reflected in the indexes, but some sources may want to explicitly allow or disallow periodic crawling of their
+          content.</para>
+      </sect2>
+      <sect2 id="federation_updates">
+        <title>Updating content</title>
+        <para>
+          The JBoss DNA federated repositories also make it possible for client applications to make changes to the unified graph
+          within the context of distributed transactions. According to the JCR API, client applications use the Java Transaction
+          API (JTA) to control the boundaries of their transactions. Meanwhile, the federated repository uses a
+          <ulink url="http://www.jboss.org/jbosstm/">distributed transaction service</ulink>
+          to coordinate the XA resources provided by the connectors.
+        </para>
+        <para> It is quite possible that clients add properties to nodes in the unified graph, and that this information cannot be
+          handled by the same underlying source that contributed to the node. In this case, the federated repository can be
+          configured with a fallback source that will be used used to store this "extra" information.</para>
+        <para>
+          It is a goal that non-XA sources (i.e., sources that use connectors without XA resources) can participate in distributed
+          transactions through the use of
+          <emphasis>compensating transactions</emphasis>
+          . Because the JBoss DNA federation engine implements the JCR observation system, it is capable of recording all of the
+          changes made to the distributed graph (and those changes sent to each updatable source). Therefore, if a non-XA source
+          is involved in a distributed transaction that must be rolled back, any changes made to non-XA sources can be undone. (Of
+          course, this does not make the underlying source transactional: non-transactional sources still may expose the interim
+          changes to other clients.)
+        </para>
+      </sect2>
+      <sect2 id="federation_events">
+        <title>Observing changes</title>
+        <para> The JCR API supports observing a repository to receive notifications of additions, changes and deletions of nodes
+          and properties. The JBoss DNA federated repository will support this API through two primary means.</para>
+        <para> When the changes are made through the federated repository, the JBoss DNA federation engine is well aware of the
+          set of changes that have been (or are being) made to the unified graph. These events are directly propagated to
+          listeners.</para>
+        <para> Sources have the ability to publish events, making it possible for the JBoss DNA federation engine and clients that
+          have registered listeners to be notified of changes in the information managed by that source. These events are first
+          processed by the federation engine and possibly altered based upon contributions from other sources. (The federation
+          engine also uses these events to update or purge information in the cache, which may add to the event set.) The
+          resulting (and possibly altered) event set is then sent to all client listeners.</para>
+      </sect2>
+    </sect1>
+  </chapter>
+  <!--  ====================================================================================================
+                                                   Chapter 
+        ====================================================================================================   -->
+  <chapter id="downloading_and_running">
+    <title>Running the example application</title>
+    <para>
+      This chapter provides instructions for downloading and running a sample application that demonstrates how JBoss DNA works
+      with a JCR repository to automatically sequence changing content to extract useful information. So read on to get the simple
+      application running, and then in the
+      <link linkend="using_dna">next chapter</link>
+      we'll dive into the source code for the example and show how to use JBoss DNA in your own applications.
+    </para>
+    <para>JBoss DNA uses Maven 2 for its build system, as is this example. Using Maven 2 has several advantages, including
+      the ability to manage dependencies. If a library is needed, Maven automatically finds and downloads that library, plus
+      everything that library needs. This means that it's very easy to build the examples - or even create a maven project that
+      depends on the JBoss DNA JARs.</para>
+    <note>
+      <para>
+        To use Maven with JBoss DNA, you'll need to have
+        <ulink url="http://java.sun.com/javase/downloads/index_jdk5.jsp">JDK 5 or 6</ulink>
+        and Maven 2.0.7 (or higher).
+      </para>
+      <para>
+        Maven can be downloaded from
+        <ulink url="http://maven.apache.org/">http://maven.apache.org/</ulink>
+        , and is installed by unzipping the
+        <code>maven-2.0.7-bin.zip</code>
+        file to a convenient location on your local disk. Simply add
+        <code>$MAVEN_HOME/bin</code>
+        to your path and add the following profile to your
+        <code>~/.m2/settings.xml</code>
+        file:
+        <programlisting role="XML" language="xml">&lt;settings&gt;
+  &lt;profiles&gt;
+    &lt;profile&gt;
+      &lt;id&gt;jboss.repository&lt;/id&gt;
+      &lt;activation&gt;
+        &lt;property&gt;          
+          &lt;name&gt;!jboss.repository.off&lt;/name&gt;
+        &lt;/property&gt;
+      &lt;/activation&gt;
+      &lt;repositories&gt;
+        &lt;repository&gt;
+          &lt;id&gt;snapshots.jboss.org&lt;/id&gt;
+          &lt;url&gt;http://snapshots.jboss.org/maven2&lt;/url&gt;
+          &lt;snapshots&gt;
+            &lt;enabled&gt;true&lt;/enabled&gt;
+          &lt;/snapshots&gt;
+        &lt;/repository&gt;
+        &lt;repository&gt;
+          &lt;id&gt;repository.jboss.org&lt;/id&gt;
+          &lt;url&gt;http://repository.jboss.org/maven2&lt;/url&gt;
+          &lt;snapshots&gt;
+            &lt;enabled&gt;false&lt;/enabled&gt;
+          &lt;/snapshots&gt;
+        &lt;/repository&gt;
+      &lt;/repositories&gt;
+      &lt;pluginRepositories&gt;
+        &lt;pluginRepository&gt;
+          &lt;id&gt;repository.jboss.org&lt;/id&gt;
+          &lt;url&gt;http://repository.jboss.org/maven2&lt;/url&gt;
+          &lt;snapshots&gt;
+            &lt;enabled&gt;false&lt;/enabled&gt;
+          &lt;/snapshots&gt;
+        &lt;/pluginRepository&gt;
+        &lt;pluginRepository&gt;
+          &lt;id&gt;snapshots.jboss.org&lt;/id&gt;
+          &lt;url&gt;http://snapshots.jboss.org/maven2&lt;/url&gt;
+          &lt;snapshots&gt;
+            &lt;enabled&gt;true&lt;/enabled&gt;
+          &lt;/snapshots&gt;
+        &lt;/pluginRepository&gt;
+      &lt;/pluginRepositories&gt;
+    &lt;/profile&gt;
+  &lt;/profiles&gt;
+&lt;/settings&gt;</programlisting>
+        This profile informs Maven of the two JBoss repositories (snapshots and releases) that contain 
+        all of the JARs for JBoss DNA and all dependent libraries.</para>
+      </note>
+    <sect1 id="downloading">
+      <title>Downloading and compiling</title>
+      <para>The next step is to <ulink url="http://www.jboss.org/file-access/default/members/dna/downloads/0.1/jboss-dna-0.1-gettingstarted-examples.zip">download</ulink>
+      the example for this Getting Started guide, and extract the contents to a convenient location on your local disk.
+      You'll find the example contains the following files, which are organized according to the standard Maven directory structure:
+  <programlisting>
+examples/pom.xml
+         sequencers/pom.xml
+                   /src/main/assembly
+                            /config
+                            /java
+                            /resources
+                       /test/java
+                            /resources
+  </programlisting>
+      </para>
+      <para>There are essentially two Maven projects: a <code>sequencers</code> project and a parent project.  All of the source
+      for the example is located in the <code>sequencers</code> subdirectory.  And you may have noticed that none
+      of the JBoss DNA libraries are there.  This is where Maven comes in.  The two <code>pom.xml</code> files tell
+      Maven everything it needs to know about what libraries are required and how to build the example.</para>
+      <para>In a terminal, go to the <code>examples</code> directory and run <emphasis role="strong"><code>mvn install</code></emphasis>.  
+      This command downloads all of the JARs necessary to compile and build the example, including the JBoss DNA libraries,
+      the libraries they depend on, and any missing Maven components.  (These are downloaded from the JBoss repositories
+      only once and saved on your machine.  This means that the next time you run Maven, all the libraries will
+      already be available locally, and the build will run much faster.)  The command then continues by compiling the example's source
+      code (and unit tests) and running the unit tests.  The build is successful if you see the following:
+           <programlisting language="bash">$ mvn install
+...
+[INFO] ------------------------------------------------------------------------
+[INFO] Reactor Summary:
+[INFO] ------------------------------------------------------------------------
+[INFO] Getting Started examples .............................. SUCCESS [2.106s]
+[INFO] Sequencer Examples .................................... SUCCESS [9.768s]
+[INFO] ------------------------------------------------------------------------
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESSFUL
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 12 seconds
+[INFO] Finished at: Wed May 07 12:00:06 CDT 2008
+[INFO] Final Memory: 14M/28M
+[INFO] ------------------------------------------------------------------------
+$ </programlisting>
+      If there are errors, check whether you have the correct version of Maven installed and that you've correctly updated
+           your Maven settings as described above.</para>
+    <para>If you've successfully built the examples, there will be a <code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
+    directory that contains the following:
+    <itemizedlist>
+  	<listitem>
+  	  <para><emphasis role="strong"><code>run.sh</code></emphasis> is the *nix shell script that will run the example.</para>
+      </listitem>
+    <listitem>
+      <para>
+        <emphasis role="strong">
+          <code>log4j.properties</code>
+        </emphasis>
+        is the Log4J configuration file.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        <emphasis role="strong">
+          <code>jackrabbitConfig.xml</code>
+        </emphasis>
+        is the Jackrabbit configuration file, which is set up to use a transient in-memory repository.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        <emphasis role="strong">
+          <code>jackrabbitNodeTypes.cnd</code>
+        </emphasis>
+        defines the additional JCR node types used by this example.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        <emphasis role="strong">
+          <code>sample1.mp3</code>
+        </emphasis>
+        is a sample MP3 audio file you'll use later to upload into the repository.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        <emphasis role="strong">
+          <code>caution.gif</code>
+        </emphasis>, <emphasis role="strong">
+          <code>caution.png</code>
+        </emphasis>, and <emphasis role="strong">
+          <code>caution.jpg</code>
+        </emphasis>
+        are images that you'll use later and upload into the repository.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        <emphasis role="strong">
+          <code>lib</code>
+        </emphasis>
+        subdirectory contains the JARs for all of the JBoss DNA artifacts as well as those for other libraries required
+    by JBoss DNA and the example.
+      </para>
+    </listitem>
+    </itemizedlist>
+    <note>
+      <para>JBoss DNA 0.1 and the examples are currently tested with <ulink url="http://jackrabbit.apache.org/">Apache Jackrabbit</ulink> version 1.3.3.  
+      This version is stable and used by a number of other projects and applications.  However, you should be able to use a newer
+      version of Jackrabbit, as long as that version uses the same JCR API.  For example, version 1.4.2 was released on March 26, 2008 and
+      should be compatible.
+      </para>
+      <para>Just remember, if the version of Jackrabbit you want to use for these examples is not in the Maven repository,
+      you'll have to either add it or add it locally.  For more information, see the <ulink url="http://maven.apache.org/">Maven documentation</ulink>.
+      </para>
+    </note>
+    </para>
+  </sect1>
+  <sect1 id="running">
+    <title>Running the example</title>
+    <para>This example consists of a client application that sets up an in-memory JCR repository and that allows a user to
+      upload files into that repository. The client also sets up the DNA services with two sequencers so that if any of the
+      uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically extract the image's metadata (e.g., image
+      format, physical size, pixel density, etc.) and store that in the repository.  Alternatively, if the uploaded file 
+      is an MP3 audio file, DNA will extract some of the ID3 metadata (e.g., the author, title, album, year and comment)
+      and store that in the repository.</para>
+    <para>
+      To run the client application, go to the
+      <code>examples/sequencers/target/dna-example-sequencers-basic.dir/
+      </code>
+      directory and type
+      <code>./run.sh</code>
+      . You should see the command-line client and its menus in your terminal:
+      <figure id="xample-sequencer-cli-client">
+        <title>Example Client</title>
+        <graphic align="center" scale="100" fileref="images/example-sequencer-cli-client.png" />
+      </figure>
+      From this menu, you can upload a file into the repository, search for media in the repository, print sequencing statistics,
+      or quit the application.
+    </para>
+    <para>
+      The first step is to upload one of the example images. If you type 'u' and press return, you'll be prompted to supply the
+      path to the file you want to upload. Since the application is running from within the
+      <code>examples/sequencers/target/dna-example-sequencers-basic.dir/
+      </code>
+      directory, you can specify any of the files in that directory without specifying the path:
+      <figure id="example-sequencer-upload">
+        <title>Uploading an image using the Example Client</title>
+        <graphic align="center" scale="100" fileref="images/example-sequencer-upload.png" />
+      </figure>
+      You can specify any fully-qualified or relative path. The application will notify you if it cannot find the file you
+      specified. The example client configures JBoss DNA to sequence and MP3 audio files and image files with one of
+      the following extensions (technically, nodes that have names ending in the following):
+      <code>jpg</code>
+      ,
+      <code>jpeg</code>
+      ,
+      <code>gif</code>
+      ,
+      <code>bmp</code>
+      ,
+      <code>pcx</code>
+      ,
+      <code>png</code>
+      ,
+      <code>iff</code>
+      ,
+      <code>ras</code>
+      ,
+      <code>pbm</code>
+      ,
+      <code>pgm</code>
+      ,
+      <code>ppm</code>
+      , and
+      <code>psd</code>
+      . Files with other extensions in the repository path will be ignored. For your convenience, the example provides several
+      files that will be sequenced (
+      <code>caution.png</code>
+      ,
+      <code>caution.jpg</code>
+      ,
+      <code>caution.gif</code>
+      , and
+      <code>sample1.mp3</code>
+      ) and one image that will not be sequenced (
+      <code>caution.pict</code>
+      ). Feel free to try other files.
+    </para>
+    <para>
+      After you have specified the file you want to upload, the example application asks you where in the repository you'd like to
+      place the file. (If you want to use the suggested location, just press
+      <code>return</code>
+      .) The client application uses the JCR API to upload the file to that location in the repository, creating any nodes (of
+      type
+      <code>nt:folder</code>
+      ) for any directories that don't exist, and creating a node (of type
+      <code>nt:file</code>
+      ) for the file. And, per the JCR specification, the application creates a
+      <code>jcr:content</code>
+      node (of type
+      <code>nt:resource</code>
+      ) under the file node. The file contents are placed on this
+      <code>jcr:content</code>
+      node in the
+      <code>jcr:data</code>
+      property. For example, if you specify
+      <code>/a/b/caution.png</code>
+      , the following structure will be created in the repository:<programlisting>
+    /a   (nt:folder)
+      /b   (nt:folder)
+        /caution.png   (nt:file)
+                    /jcr:content    (nt:resource)
+                                @jcr:data = {contents of the file}
+                                @jcr:mimeType = {mime type of the file}
+                                @jcr:lastModified = {now}
+    </programlisting>
+    Other kinds of files are treated in a similar way.
+    </para>
+  <para>
+    When the client uploads the file using the JCR API, DNA gets notified of the changes, consults the sequencers to see whether
+    any of them are interested in the new or updated content, and if so runs those sequencers. The image sequencer processes image
+    files for metadata, and any metadata found is stored under the
+    <code>/images</code>
+    branch of the repository. The MP3 sequencer processes MP3 audio files for metadata, and any metadata found is stored under the
+    <code>/mp3s</code>
+    branch of the repository.  All of this happens asynchronously, so any DNA activity doesn't impede or slow down the client
+    activities.
+  </para>
+  <para>
+    So, after the file is uploaded, you can search the repository for the image metadata using the "s" menu option:
+    <figure id="example-sequencer-search">
+      <title>Searching for media using the Example Client</title>
+      <graphic align="center" scale="100" fileref="images/example-sequencer-search.png" />
+    </figure>
+    Here are the search results after the <code>sample1.mp3</code> audio file has been uploaded (to the <code>/a/b/sample1.mp3</code> location):
+    <figure id="example-sequencer-search-with-mp3">
+      <title>Searching for media using the Example Client</title>
+      <graphic align="center" scale="100" fileref="images/example-sequencer-search-with-mp3.png" />
+    </figure>
+    You can also display the sequencing statistics using the "d" menu option:
+    <figure id="example-sequencer-statistics">
+      <title>Sequencing statistics using the Example Client</title>
+      <graphic align="center" scale="100" fileref="images/example-sequencer-statistics.png" />
+    </figure>
+    These stats show how many nodes were sequenced, and how many nodes were skipped because they didn't apply to the sequencer's
+    criteria.
+  </para>
+  <note>
+    <para>
+      There will probably be more nodes skipped than sequenced, since there are more
+      <code>nt:folder</code>
+      and
+      <code>nt:resource</code>
+      nodes than there are
+      <code>nt:file</code>
+      nodes with acceptable names.
+    </para>
+  </note>
+  <para>You can repeat this process with other files. Any file that isn't an image or MP3 files (as recognized by the sequencing configurations
+    that we'll describe later) will not be sequenced.</para>
+  </sect1>
+  <sect1 id="downloading_and_running_review">
+    <title>Summarizing what we just did</title>
+    <para>In this chapter you downloaded and installed the example application and used it to upload files into a
+    JCR repository.  JBoss DNA automatically sequenced the image and/or MP3 files you uploaded, extracted the metadata from the
+    files, and stored that metadata inside the repository.  The application allowed you to see this metadata
+    and the sequencing statistics.</para>
+    <para>This application was very simplistic.  In fact, running through the example probably only took you a minute or two.
+    So while this application won't win any awards, it does show the basics of what JBoss DNA can do.</para>
+    <para>In the <link linkend="using_dna">next chapter</link> we'll venture into the code to get an understanding
+    of how JBoss DNA actually works and how you can use it in your own applications.</para>
+  </sect1>
+  </chapter>
+  
+  <!--  ====================================================================================================
+                                                   Chapter 
+        ====================================================================================================   -->
+<chapter id="using_dna">
+  <title>Using JBoss DNA</title>
+  <para>As we've mentioned before, JBoss DNA is able to work with existing JCR repositories.  Your client applications
+  make changes to the information in those repositories, and JBoss DNA automatically uses its sequencers to extract
+  additional information from the uploaded files.</para>
+  <note>
+    <para>Configuring JBoss DNA sequencers is a bit more manual than is ideal. As you'll see, JBoss DNA uses dependency
+      injection to allow a great deal of flexibility in how it can be configured and customized. However, the next release will
+      provide a much easier mechanism for configuring not only the sequencer service but also the upcoming federation engine and
+      JCR implementation.</para>
+  </note>
+  <sect1 id="sequencing_service">
+    <title>Configuring the Sequencing Service</title>
+    <para>
+      The JBoss DNA <emphasis>sequencing service</emphasis> is the component that manages the <emphasis>sequencers</emphasis>
+      , reacting to changes in JCR repositories and then running the appropriate sequencers.
+      This involves processing the changes on a node, determining which (if any) sequencers should be run on that node,
+      and for each sequencer constructing the execution environment, calling the sequencer, and saving the information
+      generated by the sequencer.</para>
+    <para>To set up the sequencing service, an instance is created, and dependent components are injected into
+      the object.  This includes among other things:
+      <itemizedlist>
+        <listitem>
+          <para>An <emphasis>execution context</emphasis> that defines the context in which the service runs, including
+        a factory for JCR sessions given names of the repository and workspace.  This factory must be configured,
+        and is how JBoss DNA knows about your JCR repositories and how to connect to them.  More on this a bit later.</para>
+        </listitem>
+        <listitem>
+          <para>An optional <emphasis>factory for class loaders</emphasis> used to load sequencers.  If no factory is supplied,
+        the service uses the current thread's context class loader (or if that is null, the class loader that loaded the
+        sequencing service class).</para>
+        </listitem>
+        <listitem>
+          <para>An <code>java.util.concurrent.ExecutorService</code> used to execute the sequencing activites.  If none
+        is supplied, a new single-threaded executor is created by calling <code>Executors.newSingleThreadExecutor()</code>.
+        (This can easily be changed by subclassing and overriding the <code>SequencerService.createDefaultExecutorService()</code> method.)</para>
+        </listitem>
+        <listitem>
+          <para>Filters for sequencers and events.  By default, all sequencers are considered for "node added", "property added"
+        and "property changed" events.</para>
+        </listitem>
+      </itemizedlist>
+      </para>
+      <para>As mentioned above, the <code>ExecutionContext</code> provides access to a <code>SessionFactory</code> that is used
+      by JBoss DNA to establish sessions to your JCR repositories.  Two implementations are available:
+      <itemizedlist>
+        <listitem>
+          <para>The <code>JndiSessionFactory</code> looks up JCR <code>Repository</code> instances in JNDI using
+          names that are supplied when creating sessions.  This implementation also has methods to set the
+          JCR <code>Credentials</code> for a given workspace name.</para>
+        </listitem>
+        <listitem>
+          <para>The <code>SimpleSessionFactory</code> has methods to register the JCR <code>Repository</code> instances
+          with names, as well as methods to set the JCR <code>Credentials</code> for a given workspace name.</para>
+        </listitem>
+      </itemizedlist>
+      You can use the <code>SimpleExecutionContext</code> implementation of <code>ExecutionContext</code> and supply
+      a <code>SessionFactory</code> instance, or you can provide your own implementation.
+      </para>
+      <para>Here's an example of how to instantiate and configure the SequencingService:
+      <programlisting>
+SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
+sessionFactory.registerRepository("Main Repository", this.repository);
+Credentials credentials = new SimpleCredentials("jsmith", "secret".toCharArray());
+sessionFactory.registerCredentials("Main Repository/Workspace1", credentials);
+ExecutionContext executionContext = new SimpleExecutionContext(sessionFactory);
+
+// Create the sequencing service, passing in the execution context ...
+SequencingService sequencingService = new SequencingService();
+sequencingService.setExecutionContext(executionContext);</programlisting>
+      </para>
+      <para>After the sequencing service is created and configured, it must be started.  The SequencingService
+      has an <emphasis>administration object</emphasis> (that is an instance of <code>ServiceAdministrator</code>)
+      with <code>start()</code>, <code>pause()</code>, and <code>shutdown()</code> methods.  The latter method will 
+      close the queue for sequencing, but will allow sequencing operations already running to complete normally.
+      To wait until all sequencing operations have completed, simply call the <code>awaitTermination</code> method
+      and pass it the maximum amount of time you want to wait.</para>
+      <para>
+      <programlisting>
+sequencingService.getAdministrator().start();</programlisting>
+      </para>
+      <para>The sequencing service must also be configured with the sequencers that it will use.  This is done using the
+      <code>addSequencer(SequencerConfig)</code> method and passing a <code>SequencerConfig</code> instance that
+      you create.  Here's an example:
+      <programlisting>
+String name = "Image Sequencer";
+String desc = "Sequences image files to extract the characteristics of the image";
+String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
+String[] classpath = null; // Use the current classpath
+String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png))[*]/jcr:content[@jcr:data] => /images/$1"};
+SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
+sequencingService.addSequencer(imageSequencerConfig);
+
+name = "Mp3 Sequencer";
+desc = "Sequences mp3 files to extract the id3 tags of the audio file";
+classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
+String[] mp3PathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data] => /mp3s/$1"};
+SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname, classpath, mp3PathExpressions);
+sequencingService.addSequencer(mp3SequencerConfig);</programlisting>
+      This is pretty self-explanatory, except for the <code>classpath</code> and <code>pathExpression</code> parameters.
+      The classpath parameter defines the classpath that is passed to the class loader factory mentioned above.
+      Our sequencer is on the classpath, so we can simply use <code>null</code> here.
+      </para>
+      <para>The path expression is more complicated.  Sequencer path expressions are used by the sequencing service to
+      determine whether a particular changed node should be sequenced.  The expressions consist of two parts: a selection
+      criteria and an output expression.  Here's a simple example:
+      <programlisting>
+/a/b/c at title =&gt; /d/e/f</programlisting>
+      Here, the <code>/a/b/c at title</code> is the selection criteria that applies when the <code>/a/b/c</code> node has a <code>title</code> property
+      that is added or changed.  When the selection criteria matches a change event, the sequencer will be run
+      and any generated output will be inserted into the repository described by the output expression.  In this example,
+      the generated output would be placed at the <code>/d/e/f</code> node.
+      </para>
+      <note>
+        <para>Sequencer path expressions can be fairly complex and may use wildcards, specificy same-name sibling indexes,
+        provide optional and choice elements, and may capture parts of the selection criteria for use in the output expression.
+        The path expression used in the image sequencer configuration example above shows a more complex example:
+        <programlisting>
+//(*.(jpg|jpeg|gif|bmp|pcx|png))[*]/jcr:content[@jcr:data] => /images/$1</programlisting>
+        This uses "//" to select any node at any level in the repository whose name ends with "." and one of the extensions (e.g., ".jpg", ".jpeg", etc.)
+        and that has a child node named "jcr:content" that has a "jcr:data" property.  It also selects the file name
+        as the first capture group (the first set of parentheses) for use in the output expression.
+        In this example, any sequencer output is placed on a node with that same file name under the "/images" node.
+        </para>
+        <para></para>
+        <para>Other things are possible, too.  For example, the name of the repository/workspace (as used by the <code>SessionFactory</code>)
+        may be specified at the beginning of the select criteria and/or the output expression.  This means it's possible to place
+        the sequencer output in a different repository than the node being sequenced.</para>
+        <para>For more detail about sequencer path expressions, see the <code>org.jboss.dna.repository.sequencer.SequencerPathExpression</code>
+        class and the corresponding <code>org.jboss.dna.repository.sequencer.SequencerPathExpressionTest</code> test case.</para>
+      </note>
+      <para>After the service is started, it is ready to start reacting to changes in the repository.  But it first
+      must be wired to the repositories using a listener.  This is accomplished using the <code>ObservationService</code>
+      described in the <link linkend="observation_service">next section</link>.</para>
+  </sect1>
+  <sect1 id="observation_service">
+    <title>Configuring the Observation Service</title>
+    <para>The JBoss DNA <code>ObservationService</code> is responsible for listening to one or more JCR repositories
+    and multiplexing the events to its listeners.  Unlike JCR events, this framework embeds in the events the
+    name of the repository and workspace that can be passed to a <code>SessionFactory</code> to obtain a session
+    to the repository in which the change occurred.  This simple design makes it very easy for JBoss DNA to
+    concurrently work with multiple JCR repositories.</para>
+    <para>Configuring an observation service is pretty easy, especially if you reuse the same <code>SessionFactory</code>
+    supplied to the sequencing service.  Here's an example:
+    <programlisting>
+this.observationService = new ObservationService(sessionFactory);
+this.observationService.getAdministrator().start();</programlisting>
+    </para> 
+    <note>
+    <para>Both <code>ObservationService</code> and <code>SequencingService</code> implement
+    <code>AdministeredService</code>, which has a <code>ServiceAdministrator</code> used to start, pause, and shutdown the
+    service.  In other words, the lifecycle of the services are managed in the same way.</para>
+    </note>
+    <para>
+    After the observation service is started, listeners can be added.  The <code>SequencingService</code> implements the required
+    interface, and so it may be registered directly:
+    <programlisting>
+observationService.addListener(sequencingService);</programlisting>
+    </para>
+    <para>Finally, the observation service must be wired to monitor one of your JCR repositories.  This is done with
+    one of the <code>monitor(...)</code> methods:
+    <programlisting>
+int eventTypes = Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED;
+observationService.monitor("Main Repository/Workspace1", eventTypes);</programlisting>
+    </para>
+    <para>At this point, the observation service is listening to a JCR repository and forwarding the appropriate events
+    to the sequencing service, which will asynchronously process the changes and sequence the information added to or changed in the repository.
+    </para>
+  </sect1>
+  <sect1 id="shutting_down">
+    <title>Shutting down JBoss DNA services</title>
+    <para>The JBoss DNA services are utilizing resources and threads that must be released before your application is ready to shut down.
+    The safe way to do this is to simply obtain the <code>ServiceAdministrator</code> for each service (via the <code>getServiceAdministrator()</code> method)
+    and call <code>shutdown()</code>.  As previously mentioned, the shutdown method will simply prevent new work from being processed
+    and will not wait for existing work to be completed.  If you want to wait until the service completes all its work, you must wait
+    until the service terminates.  Here's an example that shows how this is done:
+    <programlisting>
+// Shut down the service and wait until it's all shut down ...
+sequencingService.getAdministrator().shutdown();
+sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+
+// Shut down the observation service ...
+observationService.getAdministrator().shutdown();
+observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);</programlisting>
+    </para>
+    <para>At this point, we've covered how to configure and use the JBoss DNA services in your application.
+    The next chapter goes back to the <link linkend="downloading_and_running">sample application</link> to show how all these pieces fit together.</para>
+  </sect1>
+  <sect1 id="example_application_review">
+    <title>Reviewing the example application</title>
+    <para>Recall that the example application consists of a client application that sets up an in-memory JCR repository and
+      that allows a user to upload files into that repository. The client also sets up the DNA services with an image sequencer so
+      that if any of the uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically extract the image's
+      metadata (e.g., image format, physical size, pixel density, etc.) and store that in the repository.  Or, if the client uploads
+      MP3 audio files, the title, author, album, year, and comment are extracted from the audio file and stored in the repository.</para>
+    <para>
+      The example is comprised of 3 classes and 1 interface, located in the
+      <code>src/main/java</code>
+      directory:
+      <programlisting>
+  org/jboss/example/dna/sequencers/ConsoleInput.java
+                                  /MediaInfo.java
+                                  /SequencingClient.java
+                                  /UserInterface.java</programlisting>
+    </para>
+    <para>
+      <code>SequencingClient</code>
+      is the class that contains the main application.
+      <code>MediaInfo</code>
+      is a simple Java object that encapsulates metadata about a media file (as generated by the sequencer), and used by the client to
+      pass information to the
+      <code>UserInterface</code>
+      , which is an interface with methods that will be called at runtime to request data from the user.
+      <code>ConsoleInput</code>
+      is an implementation of this that creates a text user interface, allowing the user to operate the client from the command-line.
+      We can easily create a graphical implementation of
+      <code>UserInterface</code>
+      at a later date. We can also create a mock implementation for testing purposes that simulates a user entering data. This
+      allows us to check the behavior of the client automatically using conventional JUnit test cases, as demonstrated by the
+      code in the
+      <code>src/test/java</code>
+      directory:
+      <programlisting>
+  org/jboss/example/dna/sequencers/SequencingClientTest.java
+                                  /MockUserInterface.java</programlisting>
+    </para>
+    <para>
+      If we look at the
+      <code>SequencingClient</code>
+      code, there are a handful of methods that encapsulate the various activities.
+    </para>
+    <note>
+      <para>To keep the code shown in this book as readable as possible, some of the comments and error handling
+      have been removed.</para>
+    </note>
+    <para>
+      The
+      <code>startRepository()</code>
+      method starts up an in-memory Jackrabbit JCR repository. The bulk of this method is simply gathering and passing the
+      information required by Jackrabbit. Because Jackrabbit's
+      <code>TransientRepository</code>
+      implementation shuts down after the last session is closed, the application maintains a session to ensure that the
+      repository remains open throughout the application's lifetime. And finally, the node type needed by the image sequencer is
+      registered with Jackrabbit.
+    </para>
+    <programlisting>
+public void startRepository() throws Exception {
+    if (this.repository == null) {
+        try {
+
+            // Load the Jackrabbit configuration ...
+            File configFile = new File(this.jackrabbitConfigPath);
+            String pathToConfig = configFile.getAbsolutePath();
+
+            // Find the directory where the Jackrabbit repository data will be stored ...
+            File workingDirectory = new File(this.workingDirectory);
+            String workingDirectoryPath = workingDirectory.getAbsolutePath();
+
+            // Get the Jackrabbit custom node definition (CND) file ...
+            URL cndFile = Thread.currentThread().getContextClassLoader().getResource("jackrabbitNodeTypes.cnd");
+
+            // Create the Jackrabbit repository instance and establish a session to keep the repository alive ...
+            this.repository = new TransientRepository(pathToConfig, workingDirectoryPath);
+            if (this.username != null) {
+                Credentials credentials = new SimpleCredentials(this.username, this.password);
+                this.keepAliveSession = this.repository.login(credentials, this.workspaceName);
+            } else {
+                this.keepAliveSession = this.repository.login();
+            }
+
+            try {
+                // Register the node types (only valid the first time) ...
+                JackrabbitNodeTypeManager mgr = (JackrabbitNodeTypeManager)this.keepAliveSession.getWorkspace().getNodeTypeManager();
+                mgr.registerNodeTypes(cndFile.openStream(), JackrabbitNodeTypeManager.TEXT_X_JCR_CND);
+            } catch (RepositoryException e) {
+                if (!e.getMessage().contains("already exists")) throw e;
+            }
+
+        } catch (Exception e) {
+            this.repository = null;
+            this.keepAliveSession = null;
+            throw e;
+        }
+    }
+}</programlisting>
+    <para>As you can see, this method really has nothing to do with JBoss DNA, other than setting up a JCR repository that JBoss
+      DNA will use.</para>
+    <para>
+      The
+      <code>shutdownRepository()</code>
+      method shuts down the Jackrabbit transient repository by closing the "keep-alive session". Again, this method really does
+      nothing specifically with JBoss DNA, but is needed to manage the JCR repository that JBoss DNA uses.
+      <programlisting>
+public void shutdownRepository() throws Exception {
+    if (this.repository != null) {
+        try {
+            this.keepAliveSession.logout();
+        } finally {
+            this.repository = null;
+            this.keepAliveSession = null;
+        }
+    }
+}</programlisting>
+    </para>
+    <para>
+      The
+      <code>startDnaServices()</code>
+      method first starts the JCR repository (if it was not already started), and proceeds to create and configure the
+      <code>SequencingService</code>
+      as described
+      <link linkend="sequencing_service">earlier</link>
+      . This involes setting up the
+      <code>SessionFactory</code>
+      and
+      <code>ExecutionContext</code>
+      , creating the
+      <code>SequencingService</code>
+      instance, and configuring the image sequencer. The method then continues by setting up the
+      <code>ObservationService</code>
+      as described
+      <link linkend="observation_service">earlier</link>
+      and starting the service.
+      <programlisting>
+public void startDnaServices() throws Exception {
+    if (this.repository == null) this.startRepository();
+    if (this.sequencingService == null) {
+
+        SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
+        sessionFactory.registerRepository(this.repositoryName, this.repository);
+        if (this.username != null) {
+            Credentials credentials = new SimpleCredentials(this.username, this.password);
+            sessionFactory.registerCredentials(this.repositoryName + "/" + this.workspaceName, credentials);
+        }
+        this.executionContext = new SimpleExecutionContext(sessionFactory);
+
+        // Create the sequencing service, passing in the execution context ...
+        this.sequencingService = new SequencingService();
+        this.sequencingService.setExecutionContext(executionContext);
+
+        // Configure the sequencers.
+        String name = "Image Sequencer";
+        String desc = "Sequences image files to extract the characteristics of the image";
+        String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
+        String[] classpath = null; // Use the current classpath
+        String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data] => /images/$1"};
+        SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
+        this.sequencingService.addSequencer(imageSequencerConfig);
+
+        // Set up the MP3 sequencer ...
+        name = "Mp3 Sequencer";
+        desc = "Sequences mp3 files to extract the id3 tags of the audio file";
+        classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
+        String[] mp3PathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data] => /mp3s/$1"};
+        SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname, classpath, mp3PathExpressions);
+        this.sequencingService.addSequencer(mp3SequencerConfig);
+
+        // Use the DNA observation service to listen to the JCR repository (or multiple ones), and
+        // then register the sequencing service as a listener to this observation service...
+        this.observationService = new ObservationService(this.executionContext.getSessionFactory());
+        this.observationService.getAdministrator().start();
+        this.observationService.addListener(this.sequencingService);
+        this.observationService.monitor(this.repositoryName + "/" + this.workspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED);
+    }
+    // Start up the sequencing service ...
+    this.sequencingService.getAdministrator().start();
+}</programlisting>
+    </para>
+    <para>
+      The
+      <code>shutdownDnaServices()</code>
+      method is pretty straightforward: it just calls shutdown on each of the services and waits until they terminate.
+      <programlisting>
+public void shutdownDnaServices() throws Exception {
+    if (this.sequencingService == null) return;
+
+    // Shut down the service and wait until it's all shut down ...
+    this.sequencingService.getAdministrator().shutdown();
+    this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+
+    // Shut down the observation service ...
+    this.observationService.getAdministrator().shutdown();
+    this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+}</programlisting>
+    </para>
+    <para>None of the other methods really do anything with JBoss DNA <emphasis>per se</emphasis>. Instead, they merely work with the repository
+      using the JCR API.</para>
+    <para>
+      The <code>main</code> method of the <code>SequencingClient</code> class creates a <code>SequencingClient</code> instance,
+      and passes a new <code>ConsoleInput</code> instance:
+      <programlisting>
+public static void main( String[] args ) throws Exception {
+    SequencingClient client = new SequencingClient();
+    client.setRepositoryInformation("repo", "default", "jsmith", "secret".toCharArray());
+    client.setUserInterface(new ConsoleInput(client));
+}</programlisting>
+      </para>
+      <para>If we look at the
+      <code>ConsoleInput</code>
+      constructor, it starts the repository, the DNA services, and a thread for the user interface. At this point, the constructor
+      returns, but the main application continues under the user interface thread.  When the user requests to quit,
+      the user interface thread also shuts down the DNA services and JCR repository.
+      <programlisting>
+public ConsoleInput( SequencerClient client ) {
+  try {
+      client.startRepository();
+      client.startDnaServices();
+  
+      System.out.println(getMenu());
+      Thread eventThread = new Thread(new Runnable() {
+          private boolean quit = false;
+          public void run() {
+              try {
+                  while (!quit) {
+                      // Display the prompt and process the requested operation ...
+                  }
+              } finally {
+                  try {
+                      // Terminate ...
+                      client.shutdownDnaServices();
+                      client.shutdownRepository();
+                  } catch (Exception err) {
+                      System.out.println("Error shutting down sequencing service and repository: " + err.getLocalizedMessage());
+                      err.printStackTrace(System.err);
+                  }
+              }
+          }
+      });
+      eventThread.start();
+  } catch (Exception err) {
+      System.out.println("Error: " + err.getLocalizedMessage());
+      err.printStackTrace(System.err);
+  }
+}</programlisting>
+    </para>
+    <para>At this point, we've reviewed all of the interesting code in the example application.  However, feel free
+    to play with the application, trying different things.
+    </para>
+  </sect1>
+  <sect1 id="using_dna_review">
+    <title>Summarizing what we just did</title>
+    <para>In this chapter we covered the different JBoss DNA components and how they can be used in your application.
+      Specifically, we described how the <code>SequencingService</code> and <code>ObservationService</code> can 
+      be configured and used.  And we ended the chapter by reviewing the example application, which not only uses
+      JBoss DNA, but also the repository via the JCR API.
+    </para>
+  </sect1>
+</chapter>
+  
+<!--  ====================================================================================================
+                                               Chapter 
+      ====================================================================================================   -->
+<chapter id="custom_sequencers">
+  <title>Creating custom sequencers</title>
+  <para>The current release of JBoss DNA comes with two sequencers: one that extracts metadata from a variety of image file formats,
+  and another that extracts some of the ID3 metadata from MP3 audio files.  However, it's very easy to create your own
+  sequencers and to then configure JBoss DNA to use them in your own application.
+  </para>
+  <para>
+  Creating a custom sequencer involves the following steps:
+  <itemizedlist>
+    <listitem>
+      <para>Create a Maven 2 project for your sequencer;</para>
+    </listitem>
+    <listitem>
+      <para>Implement the <code>org.jboss.dna.graph.sequencers.StreamSequencer</code> interface with your own implementation, and create unit tests to verify
+      the functionality and expected behavior;</para>
+    </listitem>
+    <listitem>
+      <para>Add the sequencer configuration to the JBoss DNA <code>SequencingService</code> in your application
+      as described in the <link linkend="using_dna">previous chapter</link>; and</para>
+    </listitem>
+    <listitem>
+      <para>Deploy the JAR file with your implementation (as well as any dependencies), and make them available to JBoss DNA
+      in your application.</para>
+    </listitem>
+  </itemizedlist>
+  It's that simple.
+  </para>
+  <sect1 id="custom_sequencer_project">
+    <title>Creating the Maven 2 project</title>
+    <para>The first step is to create the Maven 2 project that you can use to compile your code and build the JARs.
+    Maven 2 automates a lot of the work, and since you're already <link linkend="downloading_and_running">set up to use Maven</link>,
+    using Maven for your project will save you a lot of time and effort.  Of course, you don't have to use Maven 2, but then you'll
+    have to get the required libraries and manage the compiling and building process yourself.</para>
+    <note>
+      <para>JBoss DNA may provide in the future a Maven archetype for creating sequencer projects.  If you'd find this useful
+        and would like to help create it, please <link linkend="preface">join the community</link>.</para>
+    </note>
+  <note>
+    <para>The <code>dna-sequencer-images</code> project is a small, self-contained sequencer implementation that
+    has only the minimal dependencies.  Starting with this project's source and modifying it to suit your needs may be the easiest way to get started.
+    See the subversion repository: <ulink url="http://anonsvn.jboss.org/repos/dna/trunk/sequencers/dna-sequencer-images/">http://anonsvn.jboss.org/repos/dna/trunk/sequencers/dna-sequencer-images/</ulink>
+    </para>
+  </note>
+    <para>You can create your Maven project any way you'd like.  For examples, see the <ulink url="http://maven.apache.org/guides/getting-started/index.html#How_do_I_make_my_first_Maven_project">Maven 2 documentation</ulink>.  
+    Once you've done that, just add the dependencies in your project's <code>pom.xml</code> dependencies section:
+  <programlisting>
+&lt;dependency&gt;
+  &lt;groupId&gt;org.jboss.dna&lt;/groupId&gt;
+  &lt;artifactId&gt;dna-common&lt;/artifactId&gt;
+  &lt;version&gt;0.1&lt;/version&gt;
+&lt;/dependency&gt;
+&lt;dependency&gt;
+  &lt;groupId&gt;org.jboss.dna&lt;/groupId&gt;
+  &lt;artifactId&gt;dna-graph&lt;/artifactId&gt;
+  &lt;version&gt;0.1&lt;/version&gt;
+&lt;/dependency&gt;
+&lt;dependency&gt;
+  &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
+  &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
+&lt;/dependency&gt;
+</programlisting>
+  These are minimum dependencies required for compiling a sequencer.  Of course, you'll have to add
+  other dependencies that your sequencer needs.</para>
+  <para>As for testing, you probably will want to add more dependencies, such as those listed here:
+<programlisting>
+&lt;dependency&gt;
+  &lt;groupId&gt;junit&lt;/groupId&gt;
+  &lt;artifactId&gt;junit&lt;/artifactId&gt;
+  &lt;version&gt;4.4&lt;/version&gt;
+  &lt;scope&gt;test&lt;/scope&gt;
+&lt;/dependency&gt;
+&lt;dependency&gt;
+  &lt;groupId&gt;org.hamcrest&lt;/groupId&gt;
+  &lt;artifactId&gt;hamcrest-library&lt;/artifactId&gt;
+  &lt;version&gt;1.1&lt;/version&gt;
+  &lt;scope&gt;test&lt;/scope&gt;
+&lt;/dependency&gt;
+&lt;!-- Logging with Log4J --&gt;
+&lt;dependency&gt;
+  &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
+  &lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
+  &lt;version&gt;1.4.3&lt;/version&gt;
+  &lt;scope&gt;test&lt;/scope&gt;
+&lt;/dependency&gt;
+&lt;dependency&gt;
+  &lt;groupId&gt;log4j&lt;/groupId&gt;
+  &lt;artifactId&gt;log4j&lt;/artifactId&gt;
+  &lt;version&gt;1.2.14&lt;/version&gt;
+  &lt;scope&gt;test&lt;/scope&gt;
+&lt;/dependency&gt;
+</programlisting>
+  Testing JBoss DNA sequencers does not require a JCR repository or the JBoss DNA services.  (For more detail,
+  see the <link linkend="testing_custom_sequencers">testing section</link>.)  However, if you want to do
+  integration testing with a JCR repository and the JBoss DNA services, you'll need additional dependencies for these libraries.
+<programlisting>
+&lt;dependency&gt;
+  &lt;groupId&gt;org.jboss.dna&lt;/groupId&gt;
+  &lt;artifactId&gt;dna-repository&lt;/artifactId&gt;
+  &lt;version&gt;0.1&lt;/version&gt;
+  &lt;scope&gt;test&lt;/scope&gt;
+&lt;/dependency&gt;
+&lt;!-- Java Content Repository API --&gt;
+&lt;dependency&gt;
+  &lt;groupId&gt;javax.jcr&lt;/groupId&gt;
+  &lt;artifactId&gt;jcr&lt;/artifactId&gt;
+  &lt;version&gt;1.0.1&lt;/version&gt;
+  &lt;scope&gt;test&lt;/scope&gt;
+&lt;/dependency&gt;
+&lt;!-- Apache Jackrabbit (JCR Implementation) --&gt;
+&lt;dependency&gt;
+  &lt;groupId&gt;org.apache.jackrabbit&lt;/groupId&gt;
+  &lt;artifactId&gt;jackrabbit-api&lt;/artifactId&gt;
+  &lt;version&gt;1.3.3&lt;/version&gt;
+  &lt;scope&gt;test&lt;/scope&gt;
+  &lt;!-- Exclude these since they are included in JDK 1.5 --&gt;
+  &lt;exclusions&gt;
+    &lt;exclusion&gt;
+      &lt;groupId&gt;xml-apis&lt;/groupId&gt;
+      &lt;artifactId&gt;xml-apis&lt;/artifactId&gt;
+    &lt;/exclusion&gt;
+    &lt;exclusion&gt;
+      &lt;groupId&gt;xerces&lt;/groupId&gt;
+      &lt;artifactId&gt;xercesImpl&lt;/artifactId&gt;
+    &lt;/exclusion&gt;
+  &lt;/exclusions&gt;
+&lt;/dependency&gt;
+&lt;dependency&gt;
+  &lt;groupId&gt;org.apache.jackrabbit&lt;/groupId&gt;
+  &lt;artifactId&gt;jackrabbit-core&lt;/artifactId&gt;
+  &lt;version&gt;1.3.3&lt;/version&gt;
+  &lt;scope&gt;test&lt;/scope&gt;
+  &lt;!-- Exclude these since they are included in JDK 1.5 --&gt;
+  &lt;exclusions&gt;
+    &lt;exclusion&gt;
+      &lt;groupId&gt;xml-apis&lt;/groupId&gt;
+      &lt;artifactId&gt;xml-apis&lt;/artifactId&gt;
+    &lt;/exclusion&gt;
+    &lt;exclusion&gt;
+      &lt;groupId&gt;xerces&lt;/groupId&gt;
+      &lt;artifactId&gt;xercesImpl&lt;/artifactId&gt;
+    &lt;/exclusion&gt;
+  &lt;/exclusions&gt;
+&lt;/dependency&gt;
+</programlisting>
+  </para>
+  <para>At this point, your project should be set up correctly, and you're ready to move on to 
+  <link linkend="custom_sequencer_implementation">writing the Java implementation</link> for your sequencer.
+  </para>
+  </sect1>
+  <sect1 id="custom_sequencer_implementation">
+    <title>Implementing the StreamSequencer interface</title>
+    <para>After creating the project and setting up the dependencies, the next step is to create a Java class that implements
+    the <code>org.jboss.dna.graph.sequencers.StreamSequencer</code> interface.  This interface is very straightforward
+    and involves a single method:
+    <programlisting>
+public interface StreamSequencer {
+
+    /**
+     * Sequence the data found in the supplied stream, placing the output 
+     * information into the supplied map.
+     *
+     * @param stream the stream with the data to be sequenced; never null
+     * @param output the output from the sequencing operation; never null
+     * @param progressMonitor the progress monitor that should be kept 
+     *   updated with the sequencer's progress and that should be
+     *   frequently consulted as to whether this operation has been cancelled.
+     */
+    void sequence( InputStream stream, SequencerOutput output, 
+                   ProgressMonitor progressMonitor );</programlisting>
+    </para>
+    <para>The job of a stream sequencer is to process the data in the supplied stream, and place into the <code>SequencerOutput</code> 
+    any information that is to go into the JCR repository.  JBoss DNA figures out when your sequencer should be called
+    (of course, using the sequencing configuration you'll add in a bit), and then makes sure the generated information
+    is saved in the correct place in the repository.  
+    </para>
+    <para>The <code>SequencerOutput</code> class is fairly easy to use.  There are basically two methods you need to call.
+    One method sets the property values, while the other sets references to other nodes in the repository.  Use these
+    methods to describe the properties of the nodes you want to create, using relative paths for the nodes and
+    valid JCR property names for properties and references.  JBoss DNA will ensure that nodes are created or updated
+    whenever they're needed.
+    <programlisting>
+public interface SequencerOutput {
+
+  /**
+   * Set the supplied property on the supplied node.  The allowable
+   * values are any of the following:
+   *   - primitives (which will be autoboxed)
+   *   - String instances
+   *   - String arrays
+   *   - byte arrays
+   *   - InputStream instances
+   *   - Calendar instances
+   *
+   * @param nodePath the path to the node containing the property; 
+   * may not be null
+   * @param property the name of the property to be set
+   * @param values the value(s) for the property; may be empty if 
+   * any existing property is to be removed
+   */
+  void setProperty( String nodePath, String property,
+                    Object... values );
+
+  /**
+   * Set the supplied reference on the supplied node.
+   *
+   * @param nodePath the path to the node containing the property; 
+   * may not be null
+   * @param property the name of the property to be set
+   * @param paths the paths to the referenced property, which may be
+   * absolute paths or relative to the sequencer output node;
+   * may be empty if any existing property is to be removed
+   */
+  void setReference( String nodePath, String property,
+                     String... paths );
+}</programlisting>
+    </para>
+      <para>JBoss DNA will create nodes of type <code>nt:unstructured</code> unless you specify the value for the
+      <code>jcr:primaryType</code> property.  You can also specify the values for the <code>jcr:mixinTypes</code> property
+      if you want to add mixins to any node.
+      </para>
+    <para>For a complete example of a sequencer, let's look at the <code>org.jboss.dna.sequencers.image.ImageMetadataSequencer</code> implementation:
+    <programlisting>
+public class ImageMetadataSequencer implements StreamSequencer {
+
+    public static final String METADATA_NODE = "image:metadata";
+    public static final String IMAGE_PRIMARY_TYPE = "jcr:primaryType";
+    public static final String IMAGE_MIXINS = "jcr:mixinTypes";
+    public static final String IMAGE_MIME_TYPE = "jcr:mimeType";
+    public static final String IMAGE_ENCODING = "jcr:encoding";
+    public static final String IMAGE_FORMAT_NAME = "image:formatName";
+    public static final String IMAGE_WIDTH = "image:width";
+    public static final String IMAGE_HEIGHT = "image:height";
+    public static final String IMAGE_BITS_PER_PIXEL = "image:bitsPerPixel";
+    public static final String IMAGE_PROGRESSIVE = "image:progressive";
+    public static final String IMAGE_NUMBER_OF_IMAGES = "image:numberOfImages";
+    public static final String IMAGE_PHYSICAL_WIDTH_DPI = "image:physicalWidthDpi";
+    public static final String IMAGE_PHYSICAL_HEIGHT_DPI = "image:physicalHeightDpi";
+    public static final String IMAGE_PHYSICAL_WIDTH_INCHES = "image:physicalWidthInches";
+    public static final String IMAGE_PHYSICAL_HEIGHT_INCHES = "image:physicalHeightInches";
+
+    /**
+     * {@inheritDoc}
+     */
+    public void sequence( InputStream stream, SequencerOutput output, 
+                          ProgressMonitor progressMonitor ) {
+        progressMonitor.beginTask(10, ImageSequencerI18n.sequencerTaskName);
+
+        ImageMetadata metadata = new ImageMetadata();
+        metadata.setInput(stream);
+        metadata.setDetermineImageNumber(true);
+        metadata.setCollectComments(true);
+
+        // Process the image stream and extract the metadata ...
+        if (!metadata.check()) {
+            metadata = null;
+        }
+        progressMonitor.worked(5);
+        if (progressMonitor.isCancelled()) return;
+
+        // Generate the output graph if we found useful metadata ...
+        if (metadata != null) {
+            // Place the image metadata into the output map ...
+            output.setProperty(METADATA_NODE, IMAGE_PRIMARY_TYPE, "image:metadata");
+            // output.psetProperty(METADATA_NODE, IMAGE_MIXINS, "");
+            output.setProperty(METADATA_NODE, IMAGE_MIME_TYPE, metadata.getMimeType());
+            // output.setProperty(METADATA_NODE, IMAGE_ENCODING, "");
+            output.setProperty(METADATA_NODE, IMAGE_FORMAT_NAME, metadata.getFormatName());
+            output.setProperty(METADATA_NODE, IMAGE_WIDTH, metadata.getWidth());
+            output.setProperty(METADATA_NODE, IMAGE_HEIGHT, metadata.getHeight());
+            output.setProperty(METADATA_NODE, IMAGE_BITS_PER_PIXEL, metadata.getBitsPerPixel());
+            output.setProperty(METADATA_NODE, IMAGE_PROGRESSIVE, metadata.isProgressive());
+            output.setProperty(METADATA_NODE, IMAGE_NUMBER_OF_IMAGES, metadata.getNumberOfImages());
+            output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_WIDTH_DPI, metadata.getPhysicalWidthDpi());
+            output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_HEIGHT_DPI, metadata.getPhysicalHeightDpi());
+            output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_WIDTH_INCHES, metadata.getPhysicalWidthInch());
+            output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_HEIGHT_INCHES, metadata.getPhysicalHeightInch());
+        }
+
+        progressMonitor.done();
+    }
+}</programlisting>
+    </para>
+    <para>
+    Notice how the image metadata is extracted and the output graph is generated.  A single node is created with the name <code>image:metadata</code>
+    and with the <code>image:metadata</code> node type.  No mixins are defined for the node, but several properties are set on the node
+    using the values obtained from the image metadata.  After this method returns, the constructed graph will be saved to the repository
+    in all of the places defined by its configuration.  (This is why only relative paths are used in the sequencer.)
+    </para>
+    <para>Also note how the progress monitor is used.  Reporting progress through the supplied <code>ProgressMonitor</code> is very easy, and it ensures that JBoss DNA
+     can accurately monitor and report the status of sequencing activities to the users.  At the beginning of the operation, call
+     <code>beginTask(...)</code> with a meaningful message describing
+     the operation and a total for the amount of work that will be done by this sequencer. Then perform the sequencing work,
+     periodically reporting work by specifying the incremental amount of work with the <code>worked(double)</code> method, or
+     by creating a subtask with the <code>createSubtask(double)</code> method and reporting work against that subtask
+     monitor.
+     </para>
+     <para>Your method should periodically use the ProgressMonitor's <code>isCancelled()</code> method to check whether the operation has been
+     cancelled.. If this method returns true, the implementation should abort all work as
+     soon as possible and close any resources that were acquired or opened.
+     </para>
+     <para>
+     Finally, when your sequencing operation is completed, it should call <code>done()</code> on the progress monitor.
+     </para>
+  </sect1>
+  <sect1 id="testing_custom_sequencers">
+    <title>Testing custom sequencers</title>
+    <para>The sequencing framework was designed to make testing sequencers much easier.  In particular, the
+    <code>StreamSequencer</code> interface does not make use of the JCR API.  So instead of requiring a fully-configured
+    JCR repository and JBoss DNA system, unit tests for a sequencer can focus on testing that the content is
+    processed correctly and the desired output graph is generated.</para>
+    <note>
+      <para>For a complete example of a sequencer unit test, see the <code>ImageMetadataSequencerTest</code> unit test
+      in the <code>org.jboss.dna.sequencer.images</code> package of the <code>dna-sequencers-image</code> project.
+      </para>
+    </note>
+    <para>The following code fragment shows one way of testing a sequencer, using JUnit 4.4 assertions and 
+      some of the classes made available by JBoss DNA.  Of course,
+      this example code does not do any error handling and does not make all the assertions a real test would.
+    <programlisting>
+Sequencer sequencer = new ImageMetadataSequencer();
+MockSequencerOutput output = new MockSequencerOutput();
+ProgressMonitor progress = new SimpleProgressMonitor("Test activity");
+InputStream stream = null;
+try {
+    stream = this.getClass().getClassLoader().getResource("caution.gif").openStream();
+    sequencer.sequence(stream,output,progress);   // writes to 'output'
+    assertThat(output.getPropertyValues("image:metadata", "jcr:primaryType"), 
+               is(new Object[] {"image:metadata"}));
+    assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"), 
+               is(new Object[] {"image/gif"}));
+    // ... make more assertions here
+    assertThat(output.hasReferences(), is(false));
+} finally {
+    stream.close();
+}</programlisting>
+  </para>
+  <para>It's also useful to test that a sequencer produces no output for something it should not understand:
+    <programlisting>
+Sequencer sequencer = new ImageMetadataSequencer();
+MockSequencerOutput output = new MockSequencerOutput();
+ProgressMonitor progress = new SimpleProgressMonitor("Test activity");
+InputStream stream = null;
+try {
+    stream = this.getClass().getClassLoader().getResource("caution.pict").openStream();
+    sequencer.sequence(stream,output,progress);   // writes to 'output'
+    assertThat(output.hasProperties(), is(false));
+    assertThat(output.hasReferences(), is(false));
+} finally {
+    stream.close();
+}</programlisting>
+    </para>
+    <para>These are just two simple tests that show ways of testing a sequencer.  Some tests may get quite involved,
+    especially if a lot of output data is produced.  
+    </para>
+    <para>It may also be useful to create some integration tests
+    that <link linkend="using_dna">configure JBoss DNA</link> to use a custom sequencer, and to then upload
+    content using the JCR API, verifying that the custom sequencer did run.  However, remember that JBoss DNA
+    runs sequencers asynchronously in the background, and you must sychronize your tests to ensure that the
+    sequencers have a chance to run before checking the results.  (One way of doing this (although, granted, not always reliable) is to wait for a second
+    after uploading your content, shutdown the <code>SequencingService</code> and await its termination,
+    and then check that the sequencer output has been saved to the JCR repository.  For an example of this technique,
+    see the <code>SequencingClientTest</code> unit test in the example application.)
+    </para>  
+  </sect1>
+  <sect1 id="deploying_custom_sequencers">
+    <title>Deploying custom sequencers</title>
+    <para>The first step of deploying a sequencer consists of adding/changing the sequencer configuration (e.g., <code>SequencerConfig</code>)
+    in the <code>SequencingService</code>.  This was covered in the <link linkend="sequencing_service">previous chapter</link>.
+    </para>
+    <para>
+    The second step is to make the sequencer implementation available to JBoss DNA.  At this time, the JAR containing 
+    your new sequencer, as well as any JARs that your sequencer depends on, should be placed on your application classpath.</para>
+    <note>
+      <para>A future goal of JBoss DNA is to allow sequencers, connectors, and other extensions to be easily deployed into
+        a runtime repository.  This process will not only be much simpler, but it will also provide JBoss DNA 
+        with the information necessary to update configurations and create the appropriate class loaders for each extension.
+        Having separate class loaders for each extension helps prevent the pollution of the common classpath, 
+        facilitates an isolated runtime environment to eliminate any dependency conflicts, and may potentially
+        enable hot redeployment of newer extension versions.
+      </para>
+    </note>
+  </sect1>
+</chapter>
+  
+<!--  ====================================================================================================
+                                               Chapter 
+      ====================================================================================================   -->
+<chapter id="future_directions">
+  <title>Looking to the future</title>
+  <para>What's next for JBoss DNA?  Well, the sequencing system is just the beginning.  With this release, the sequencing system
+  is stable enough so that more <link linkend="sequencers">sequencers</link> can be developed and used within your own applications.
+  If you're interested in getting involved with the JBoss DNA project, consider picking up one of the sequencers on our
+  <ulink url="http://jira.jboss.org/jira/browse/DNA?report=com.atlassian.jira.plugin.system.project:roadmap-panel">roadmap</ulink>.
+  Or, check out <ulink url="http://jira.jboss.org/jira/secure/IssueNavigator.jspa?reset=true&amp;mode=hide&amp;pid=12310520&amp;sorter/order=DESC&amp;sorter/field=priority&amp;resolution=-1&amp;component=12311436">JIRA</ulink>
+  for the list of sequencers we've thought of.  If you think of one that's not there, please add it to JIRA!
+  </para>
+  <para>
+  The next release will focus on creating the <link linkend="federation">federation engine</link> and connectors
+  for several popular and ubiquitous systems.  The 0.2 release will likely only federate information in a read-only manner,
+  but updates will soon follow.  Also, during the early part of the next release, the JBoss DNA project will switch to use JDK 6.  
+  Java 5 is being end-of-lifed, so we want to move to a supported JDK. However, a number of JBoss projects and products continue to
+  require Java 5, so our next release will most likely use JDK 6 with Java 5 compatibility.</para>
+  <para>
+  Other components on our roadmap include a web user interface, a REST-ful server, and a view system that allows domain-specific
+  views of information in the repository.  These components are farther out on our roadmap, and at this time have not been
+  targeted to a particular release.  If any of these are of interest to you, please <link linkend="preface">get involved</link> in the community.
+  </para>
+</chapter>
+</book>
\ No newline at end of file

Added: trunk/extensions/dna-sequencer-xml/src/test/resources/plugin.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/plugin.xml	                        (rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/plugin.xml	2008-10-29 18:23:01 UTC (rev 598)
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<!--  (c) 2007 Varsity Gateway LLC.  All rights reserved. -->
+<plugin
+   id="com.metamatrix.metamodels.transformation"
+   name="%pluginName"
+   version="5.5.1"
+   provider-name="%providerName"
+   class="com.metamatrix.metamodels.transformation.TransformationPlugin">
+
+   <runtime>
+      <library name="metamodelsTransformation.jar">
+         <export name="*"/>
+      </library>
+   </runtime>
+   <requires>
+      <import plugin="org.eclipse.emf.mapping" export="true"/>
+      <import plugin="org.eclipse.emf.ecore" export="true"/>
+      <import plugin="org.eclipse.emf.edit" export="true"/>
+      <import plugin="org.eclipse.emf.ecore.edit" export="true"/>
+      <import plugin="org.eclipse.core.runtime" export="true"/>
+      <import plugin="com.metamatrix.core" export="true"/>
+      <import plugin="com.metamatrix.metamodels.core" export="true"/>
+   </requires>
+
+
+<!--
+   	Each extension below represents a single metamodel.  Each metmodel is
+   	registered using under the specified <uri> value which must be the same
+   	eNS_URI value defined in the EPackage class for that metamodel.
+   -->
+   <extension
+         id="transformation"
+         name="%metamodelName"
+         point="com.metamatrix.modeler.core.metamodel">
+      <uri>
+         http://www.metamatrix.com/metamodels/Transformation
+      </uri>
+      <alternateUri>
+         mtkplugin:///com.metamatrix.metamodels.Transformation
+      </alternateUri>
+      <packageClass
+            name="com.metamatrix.metamodels.transformation.TransformationPackage">
+      </packageClass>
+      <adapterClass
+            name="com.metamatrix.metamodels.transformation.provider.TransformationItemProviderAdapterFactory">
+      </adapterClass>
+      <properties
+            createAsPhysical="false"
+            requiresProxies="false"
+            participatoryOnly="true"
+            createAsVirtual="false"
+            supportsDiagrams="false"
+            supportsExtension="true">
+      </properties>
+   </extension>
+   <extension
+         point="org.eclipse.emf.ecore.generated_package">
+      <package
+            uri="http://www.metamatrix.com/metamodels/Transformation"
+            class="com.metamatrix.metamodels.transformation.TransformationPackage">
+      </package>
+   </extension>
+     
+   <extension
+         id="mapping"
+         name="%mappingMetamodelName"
+         point="com.metamatrix.modeler.core.metamodel">
+      <uri>
+         http://www.eclipse.org/emf/2002/Mapping
+      </uri>
+      <alternateUri>
+         mtkplugin:///www.eclipse.org/emf/2002/Mapping
+      </alternateUri>
+      <packageClass
+            name="org.eclipse.emf.mapping.MappingPackage">
+      </packageClass>
+      <adapterClass
+            name="org.eclipse.emf.mapping.provider.MappingItemProviderAdapterFactory">
+      </adapterClass>
+      <properties
+            createAsPhysical="false"
+            requiresProxies="false"
+            participatoryOnly="true"
+            createAsVirtual="false"
+            supportsDiagrams="false"
+            supportsExtension="false">
+      </properties>
+   </extension>
+
+</plugin>

Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml	2008-10-29 17:48:23 UTC (rev 597)
+++ trunk/pom.xml	2008-10-29 18:23:01 UTC (rev 598)
@@ -123,6 +123,7 @@
 		<module>extensions/dna-sequencer-cnd</module>
 		<module>extensions/dna-sequencer-java</module>
 		<module>extensions/dna-sequencer-msoffice</module>
+		<module>extensions/dna-sequencer-xml</module>
 		<module>extensions/dna-sequencer-zip</module>
 		<module>extensions/dna-connector-federation</module>
 		<module>extensions/dna-connector-inmemory</module>




More information about the dna-commits mailing list