svn commit: r568786 - in /xml/xindice/trunk/java: src/org/apache/xindice/core/ src/org/apache/xindice/core/indexer/ src/org/apache/xindice/core/query/ src/org/apache/xindice/xml/ src/org/apache/xindice/xml/dom/ tests/src/org/apache/xindice/xml/

[email protected]
Newsgroups gmane.text.xml.xindice.devel
Message-ID <[email protected]>
Author: vgritsenko
Date: Wed Aug 22 17:40:57 2007
New Revision: 568786

URL: http://svn.apache.org/viewvc?rev=568786&view=rev
Log:
implemented support for read only symbol tables.
refactor collection to take advantage of that.
catch read only exception, propagate as appropriate.
javadoc.

Modified:
    xml/xindice/trunk/java/src/org/apache/xindice/core/Collection.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/SystemCollection.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexPattern.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java
    xml/xindice/trunk/java/src/org/apache/xindice/xml/SymbolTable.java
    xml/xindice/trunk/java/src/org/apache/xindice/xml/dom/DOMCompressor.java
    xml/xindice/trunk/java/tests/src/org/apache/xindice/xml/SymbolTableTest.java

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/Collection.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/Collection.java?rev=568786&r1=568785&r2=568786&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/Collection.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/Collection.java Wed Aug 22 17:40:57 2007
@@ -218,7 +218,6 @@
     private String oidTemplate;
     private long documentId;
 
-    private boolean internalSymbols;
     private SymbolTable symbols;
 
     private File collectionRoot;
@@ -296,6 +295,7 @@
      *
      * @param config The Indexer's configuration
      * @return The newly created Indexer
+     * @throws DBException if operation failed
      */
     public final Indexer createIndexer(Configuration config) throws DBException {
         checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
@@ -380,7 +380,7 @@
         getCollectionRoot().delete();
 
         // Drop symbols
-        if (!internalSymbols) {
+        if (!symbols.isReadOnly()) {
             getSystemCollection().dropSymbols(this);
         }
 
@@ -389,7 +389,7 @@
     }
 
     /**
-     * @see org.apache.xindice.core.CollectionManager#dropCollection(org.apache.xindice.core.Collection)
+     * @see CollectionManager#dropCollection(Collection)
      */
     public final boolean dropCollection(Collection collection) throws DBException {
         boolean success = super.dropCollection(collection);
@@ -403,6 +403,7 @@
      *
      * @param index The Indexer to drop
      * @return Whether or not the Indexer was dropped
+     * @throws DBException if operation failed
      */
     public final boolean dropIndexer(Indexer index) throws DBException {
         checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
@@ -425,10 +426,10 @@
     }
 
     /**
-     * @throws DBException
+     * @throws DBException if operation failed
      */
     public final void flushSymbolTable() throws DBException {
-        if (symbols.isDirty() && !internalSymbols) {
+        if (symbols.isDirty()) {
             getSystemCollection().saveSymbols(this, symbols);
         }
     }
@@ -516,6 +517,7 @@
      * returned will be null.
      *
      * @return MetaData this collection's metadata.
+     * @throws DBException if operation failed
      */
     public MetaData getCollectionMeta() throws DBException {
         if (!isMetaEnabled()) {
@@ -550,6 +552,7 @@
      *
      * @param docKey The Document Key
      * @return The Container
+     * @throws DBException if operation failed
      */
     public final Container getContainer(Object docKey) throws DBException {
         Key key = createNewKey(docKey);
@@ -571,6 +574,7 @@
      *
      * @param key The Document Key
      * @return The Document
+     * @throws DBException if operation failed
      */
     public final Document getDocument(Object key) throws DBException {
         if (log.isDebugEnabled()) {
@@ -596,6 +600,7 @@
      * by this Collection.
      *
      * @return The Document count
+     * @throws DBException if operation failed
      */
     public final long getDocumentCount() throws DBException {
         // a collection in which you are unable to file documents will have no filer
@@ -606,9 +611,11 @@
 
     /**
      * Return the MetaData object for a document within this collection.
-     *
      * If metadata is not enabled, the MetaData object returned will be null.
+     *
      * @param id the document whose metadata you want
+     * @return meta data for requested resource
+     * @throws DBException if operation failed
      */
     public MetaData getDocumentMeta(String id) throws DBException {
         if (!isMetaEnabled()) {
@@ -661,6 +668,7 @@
      * by this Collection.
      *
      * @return The DocumentSet
+     * @throws DBException if operation failed
      */
     public final DocumentSet getDocumentSet() throws DBException {
         // a collection in which you are unable to file documents will have no filer
@@ -841,6 +849,7 @@
      *
      * @param name The Indexer name
      * @return The Indexer (or null)
+     * @throws DBException if operation failed
      */
     public final Indexer getIndexer(String name) throws DBException {
         checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
@@ -851,6 +860,7 @@
      * return the IndexManager being used by this Collection.
      *
      * @return The IndexManager
+     * @throws DBException if operation failed
      */
     public final IndexManager getIndexManager() throws DBException {
         checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
@@ -878,6 +888,7 @@
      *
      * @param key The Document Key
      * @return an Castable XMLSerializable Instance
+     * @throws DBException if operation failed
      */
     public final XMLSerializable getObject(Object key) throws DBException {
         if (log.isDebugEnabled()) {
@@ -918,6 +929,7 @@
      * Collection.
      *
      * @return The parent Collection (or null)
+     * @throws DBException if operation failed
      */
     public final Collection getParentCollection() throws DBException {
         return parent;
@@ -927,6 +939,7 @@
      * getQueryEngine returns the Database's Query Engine
      *
      * @return The Query Engine
+     * @throws DBException if operation failed
      */
     public QueryEngine getQueryEngine() throws DBException {
         return getDatabase().getQueryEngine();
@@ -972,6 +985,7 @@
      *
      * @param docKey The document Key
      * @param bytes The document to insert
+     * @return key for the inserted binary
      * @throws DBException if inline-metadata is not enabled, the key is
      *         already in the database, or an error occurs while saving.
      */
@@ -998,6 +1012,7 @@
      *
      * @param document The Document
      * @return The new Object Identifier
+     * @throws DBException if operation failed
      */
     public final Key insertDocument(Document document) throws DBException {
         return insertDocument(null, document);
@@ -1008,6 +1023,8 @@
      *
      * @param docKey The document Key
      * @param document The document to insert
+     * @return key for inserted document
+     * @throws DBException if operation failed
      */
     public final Key insertDocument(Object docKey, Document document) throws DBException {
         Key key = createNewKey(docKey);
@@ -1028,6 +1045,7 @@
      *
      * @param obj The Object to insert
      * @return The newly generated Key
+     * @throws DBException if operation failed
      */
     public final Key insertObject(XMLSerializable obj) throws DBException {
         return insertObject(null, obj);
@@ -1040,6 +1058,8 @@
      *
      * @param objKey The Key to use
      * @param obj The Object to insert
+     * @return key for the inserted object
+     * @throws DBException if operation failed
      */
     public final Key insertObject(String objKey, XMLSerializable obj) throws DBException {
         Key key = createNewKey(objKey);
@@ -1076,6 +1096,7 @@
      * collection.
      *
      * @return the list of entry keys
+     * @throws DBException if operation failed
      */
     public final String[] listDocuments() throws DBException {
         // a collection in which you are unable to file documents will have no filer
@@ -1104,6 +1125,7 @@
      * as an array of String.
      *
      * @return The Indexer list
+     * @throws DBException if operation failed
      */
     public final String[] listIndexers() throws DBException {
         checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
@@ -1121,6 +1143,7 @@
      * @param key The key to use when caching
      * @param xml The string to parse
      * @return A parsed DOM document or null if failure
+     * @throws DBException if operation failed
      */
     private Document parseDocument(Key key, String xml) throws DBException {
         try {
@@ -1350,6 +1373,7 @@
      * @param query The query to execute
      * @param nsMap The namespace Map (if any)
      * @return The resulting NodeSet
+     * @throws DBException if operation failed
      */
     public final NodeSet queryCollection(String style, String query, NamespaceMap nsMap) throws DBException {
         if (log.isDebugEnabled()) {
@@ -1371,6 +1395,7 @@
      * @param nsMap The namespace Map (if any)
      * @param key The Document to query
      * @return The resulting NodeSet
+     * @throws DBException if operation failed
      */
     public final NodeSet queryDocument(String style, String query, NamespaceMap nsMap, Object key) throws DBException {
         if (log.isInfoEnabled()) {
@@ -1392,6 +1417,7 @@
      * regardless of it's type.
      *
      * @param key The Object's Key
+     * @throws DBException if operation failed
      */
     public final void remove(Object key) throws DBException {
         if (log.isInfoEnabled()) {
@@ -1445,7 +1471,9 @@
 
     /**
      * Reset the metadata object for this collection.
+     *
      * @param meta the Metadata to use
+     * @throws DBException if operation failed
      */
     public void setCollectionMeta(MetaData meta) throws DBException {
         if (!isMetaEnabled()) {
@@ -1525,15 +1553,14 @@
 
             // Symbol Table Setup
             Configuration symConfig = config.getChild(SYMBOLS);
-            internalSymbols = (symConfig != null);
-            if (internalSymbols) {
+            if (symConfig != null) {
                 if (log.isTraceEnabled()) {
                     log.trace(localDebugHeader +
                               "Internal symbols=<" + TextWriter.toString(symConfig.getElement()) + ">");
                 }
 
                 try {
-                    symbols = new SymbolTable(symConfig.getElement());
+                    symbols = new SymbolTable(symConfig.getElement(), true);
                 } catch (Exception e) {
                     if (log.isWarnEnabled()) {
                         log.warn(localDebugHeader + "Error building symbol table from internal symbols", e);
@@ -1600,6 +1627,7 @@
      *
      * @param docKey The Document Key
      * @param document The Document
+     * @throws DBException if operation failed
      */
     public final boolean setDocument(Object docKey, Document document) throws DBException {
         if (log.isInfoEnabled()) {
@@ -1620,6 +1648,7 @@
      *
      * @param docKey The document Key
      * @param bytes The document to insert
+     * @return true if new binary was created, false otherwise
      * @throws DBException if inline-metadata is not enabled, the key is
      *         already in the database, or an error occurs while saving.
      */
@@ -1648,6 +1677,7 @@
      *
      * @param id the document name
      * @param meta the metadata object to be used.
+     * @throws DBException if operation failed
      */
     public void setDocumentMeta(String id, MetaData meta) throws DBException {
         if (!isMetaEnabled()) {
@@ -1682,10 +1712,10 @@
     }
 
     /**
-     * @param string
+     * @param name collection name
      */
-    protected void setName(String string) {
-        name = string;
+    protected void setName(String name) {
+        this.name = name;
     }
 
     /**
@@ -1695,6 +1725,7 @@
      *
      * @param key The Key to use
      * @param obj The Object to set
+     * @throws DBException if operation failed
      */
     public final void setObject(Object key, XMLSerializable obj) throws DBException {
         if (log.isInfoEnabled()) {
@@ -1748,6 +1779,9 @@
 
     /**
      * update the modified time of this document when appropriate
+     *
+     * @param record database record for which metadata should be updated
+     * @throws DBException if operation failed
      */
     protected void updateDocumentMeta(Record record) throws DBException {
         // update the meta data if necessary

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/SystemCollection.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/SystemCollection.java?rev=568786&r1=568785&r2=568786&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/SystemCollection.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/SystemCollection.java Wed Aug 22 17:40:57 2007
@@ -126,7 +126,7 @@
         if (symbols != null) {
             String name = getSymbolTableName(collection);
             getCollection(SYMBOLS).setObject(name, symbols);
-            symbols.setDirty(false);
+            symbols.resetDirty();
         }
     }
 

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java?rev=568786&r1=568785&r2=568786&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java Wed Aug 22 17:40:57 2007
@@ -19,18 +19,21 @@
 
 package org.apache.xindice.core.indexer;
 
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.Attributes;
-import org.apache.xindice.xml.sax.CompressionHandler;
-import org.apache.xindice.xml.sax.SAXEventGenerator;
-import org.apache.xindice.xml.SymbolTable;
-import org.apache.xindice.util.ObjectStack;
-import org.apache.xindice.core.data.Key;
-import org.apache.xindice.core.DBException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.xindice.core.DBException;
+import org.apache.xindice.core.data.Key;
+import org.apache.xindice.util.ObjectStack;
+import org.apache.xindice.util.ReadOnlyException;
+import org.apache.xindice.xml.SymbolTable;
+import org.apache.xindice.xml.sax.CompressionHandler;
+import org.apache.xindice.xml.sax.SAXEventGenerator;
+
 import org.w3c.dom.Document;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
 
 /**
  * DocumentHandler actually performs the work of adding and removing Indexer
@@ -39,6 +42,9 @@
  * @version $Revision$, $Date$
  */
 class DocumentHandler implements ContentHandler, CompressionHandler {
+
+    private static final Log log = LogFactory.getLog(DocumentHandler.class);
+
     static final int ACTION_CREATE = 0;
     static final int ACTION_DELETE = 1;
 
@@ -53,8 +59,6 @@
 
     public StackInfo info; // Current State
 
-    private static final Log log = LogFactory.getLog(DocumentHandler.class);
-
     public DocumentHandler(SymbolTable symbols, Key key, Document doc, int action, Indexer[] list) {
         this.symbols = symbols;
         this.key = key;
@@ -173,23 +177,27 @@
         }
     }
 
-    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
-        // Modify the stack info to normalize the symbolID
-        if (namespaceURI != null && namespaceURI.length() > 0) {
-            info.symbolID = symbols.getNormalizedSymbol(localName, namespaceURI, true);
-        }
-
-        int size = atts.getLength();
-        for (int i = 0; i < size; i++) {
-            String nsURI = atts.getURI(i);
-            short id;
-            if (nsURI != null && nsURI.length() > 0) {
-                id = symbols.getNormalizedSymbol(atts.getLocalName(i), nsURI, true);
-            } else {
-                id = symbols.getSymbol(atts.getQName(i), true);
+    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+        try {
+// Modify the stack info to normalize the symbolID
+            if (namespaceURI != null && namespaceURI.length() > 0) {
+                info.symbolID = symbols.getNormalizedSymbol(localName, namespaceURI, true);
             }
 
-            processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
+            int size = atts.getLength();
+            for (int i = 0; i < size; i++) {
+                String nsURI = atts.getURI(i);
+                short id;
+                if (nsURI != null && nsURI.length() > 0) {
+                    id = symbols.getNormalizedSymbol(atts.getLocalName(i), nsURI, true);
+                } else {
+                    id = symbols.getSymbol(atts.getQName(i), true);
+                }
+
+                processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
+            }
+        } catch (ReadOnlyException e) {
+            throw new SAXException(e);
         }
     }
 

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexPattern.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexPattern.java?rev=568786&r1=568785&r2=568786&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexPattern.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexPattern.java Wed Aug 22 17:40:57 2007
@@ -19,7 +19,9 @@
 
 package org.apache.xindice.core.indexer;
 
+import org.apache.xindice.core.FaultCodes;
 import org.apache.xindice.core.filer.Streamable;
+import org.apache.xindice.util.ReadOnlyException;
 import org.apache.xindice.xml.NamespaceMap;
 import org.apache.xindice.xml.SymbolTable;
 
@@ -53,24 +55,30 @@
     private short attrID = PATTERN_NONE;
 
 
-    public IndexPattern(SymbolTable symbols, String pattern, NamespaceMap nsMap) {
+    public IndexPattern(SymbolTable symbols, String pattern, NamespaceMap nsMap) throws IndexerException {
         this.symbols = symbols;
         StringTokenizer st = new StringTokenizer(pattern.trim(), "@");
-        elemName = st.nextToken();
-        if (elemName.equals("*")) {
-            elemID = PATTERN_WILDCARD;
-        } else {
-            elemID = symbols.getNormalizedSymbol(elemName, nsMap, true);
-        }
-
-        if (st.hasMoreTokens()) {
-            attrName = st.nextToken();
-            if (attrName.equals("*")) {
-                attrID = PATTERN_WILDCARD;
+
+        try {
+            elemName = st.nextToken();
+            if (elemName.equals("*")) {
+                elemID = PATTERN_WILDCARD;
             } else {
-                attrID = elemID == PATTERN_WILDCARD ? PATTERN_NAME
-                        : symbols.getNormalizedSymbol(attrName, nsMap, true);
+                elemID = symbols.getNormalizedSymbol(elemName, nsMap, true);
+            }
+
+            if (st.hasMoreTokens()) {
+                attrName = st.nextToken();
+                if (attrName.equals("*")) {
+                    attrID = PATTERN_WILDCARD;
+                } else {
+                    attrID = elemID == PATTERN_WILDCARD ? PATTERN_NAME
+                            : symbols.getNormalizedSymbol(attrName, nsMap, true);
+                }
             }
+        } catch (ReadOnlyException e) {
+            throw new IndexerException(FaultCodes.IDX_NOT_SUPPORTED,
+                                       "Pattern '" + pattern + "' is not allowed in this collection.", e);
         }
     }
 

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java?rev=568786&r1=568785&r2=568786&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java Wed Aug 22 17:40:57 2007
@@ -919,7 +919,7 @@
             return null;
         }
 
-        private Object funcStartsWith(String owner, List args) {
+        private Object funcStartsWith(String owner, List args) throws Exception {
             if (args.size() == 2) {
                 Object o = args.get(0);
                 Object s = args.get(1);
@@ -1114,7 +1114,7 @@
          * @param right The right Operand
          * @return The resulting Keys (if any)
          */
-        private Object queryComparison(int op, String owner, Object left, Object right) {
+        private Object queryComparison(int op, String owner, Object left, Object right) throws Exception {
             op = OPMAP[op - OpCodes.OP_NOTEQUALS];
 
             if (left instanceof XObject) {

Modified: xml/xindice/trunk/java/src/org/apache/xindice/xml/SymbolTable.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/xml/SymbolTable.java?rev=568786&r1=568785&r2=568786&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/xml/SymbolTable.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/xml/SymbolTable.java Wed Aug 22 17:40:57 2007
@@ -19,6 +19,8 @@
 
 package org.apache.xindice.xml;
 
+import org.apache.xindice.util.ReadOnlyException;
+
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -45,9 +47,10 @@
     private transient boolean dirty;
     private transient long lastModified = System.currentTimeMillis();
 
+    private short maxSymbol = -1;
     private final Map symbols = new HashMap(); // String to SymbolInfo
     private final Map names = new HashMap();   // Short to SymbolInfo
-    private short maxSymbol = -1;
+    private boolean readOnly;
 
 
     public static final class SymbolInfo implements Serializable {
@@ -55,14 +58,14 @@
         private final String qname;
         private final short symbol;
 
-        private SymbolInfo(String qname, String namespaceURI, short symbol) {
-            this.namespaceURI = namespaceURI;
+        private SymbolInfo(String qname, short symbol) {
+            this.namespaceURI = null;
             this.qname = qname;
             this.symbol = symbol;
         }
 
-        private SymbolInfo(String qname, short symbol) {
-            this.namespaceURI = null;
+        private SymbolInfo(String qname, String namespaceURI, short symbol) {
+            this.namespaceURI = namespaceURI;
             this.qname = qname;
             this.symbol = symbol;
         }
@@ -87,23 +90,50 @@
     public SymbolTable() {
     }
 
-    public SymbolTable(Element elem) {
-        streamFromXML(elem);
+    public SymbolTable(Element symbols) {
+        streamFromXML(symbols);
+    }
+
+    public SymbolTable(Element symbols, boolean readOnly) {
+        this(symbols);
+        this.readOnly = readOnly;
     }
 
+    /**
+     * @return true if symbol table has been modified
+     */
     public final boolean isDirty() {
         return dirty;
     }
 
-    public final void setDirty(boolean dirty) {
-        this.dirty = dirty;
+    /**
+     * Set dirty flag to true and update last modified
+     * time stamp.
+     */
+    private void markDirty() {
+        this.dirty = true;
         this.lastModified = System.currentTimeMillis();
     }
 
+    /**
+     * Reset dirty flag to false. Should be invoked
+     * once symbol table is successfully saved.
+     */
+    public final void resetDirty() {
+        this.dirty = false;
+    }
+
     public final long getLastModified() {
         return lastModified;
     }
 
+    /**
+     * @return true if symbol table is read only
+     */
+    public final boolean isReadOnly() {
+        return readOnly;
+    }
+
     //
     // Lookup by symbol id
     //
@@ -127,26 +157,40 @@
     //
 
     public final short getSymbol(String qname) {
-        return getSymbol(qname, false);
+        try {
+            return getSymbol(qname, false);
+        } catch (ReadOnlyException e) {
+            // Won't happen
+            throw new IllegalStateException();
+        }
     }
 
     public final short getSymbol(String qname, String namespaceURI) {
-        return getSymbol(qname, namespaceURI, false);
+        try {
+            return getSymbol(qname, namespaceURI, false);
+        } catch (ReadOnlyException e) {
+            // Won't happen
+            throw new IllegalStateException();
+        }
     }
 
-    public final short getSymbol(String qname, boolean create) {
+    public final short getSymbol(String qname, boolean create) throws ReadOnlyException {
         SymbolInfo info = (SymbolInfo) symbols.get(qname);
         if (info != null) {
             return info.symbol;
         }
 
         if (create) {
+            if (readOnly) {
+                throw new ReadOnlyException();
+            }
+
             synchronized (symbols) {
                 short id = ++maxSymbol;
                 info = new SymbolInfo(qname, id);
                 symbols.put(qname, info);
                 names.put(new Short(id), info);
-                setDirty(true);
+                markDirty();
                 return id;
             }
         }
@@ -154,7 +198,7 @@
         return -1;
     }
 
-    public final short getSymbol(String qname, String namespaceURI, boolean create) {
+    public final short getSymbol(String qname, String namespaceURI, boolean create) throws ReadOnlyException {
         String lookupName = getLookupName(qname, namespaceURI);
 
         SymbolInfo info = (SymbolInfo) symbols.get(lookupName);
@@ -163,12 +207,16 @@
         }
 
         if (create) {
+            if (readOnly) {
+                throw new ReadOnlyException();
+            }
+
             synchronized (symbols) {
                 short id = ++maxSymbol;
                 info = new SymbolInfo(qname, namespaceURI, id);
                 symbols.put(lookupName, info);
                 names.put(new Short(id), info);
-                setDirty(true);
+                markDirty();
                 return id;
             }
         }
@@ -181,7 +229,12 @@
     //
 
     public final short getNormalizedSymbol(String localName, String namespaceURI) {
-        return getNormalizedSymbol(localName, namespaceURI, false);
+        try {
+            return getNormalizedSymbol(localName, namespaceURI, false);
+        } catch (ReadOnlyException e) {
+            // Won't happen
+            throw new IllegalStateException();
+        }
     }
 
     /**
@@ -191,9 +244,10 @@
      * @param namespaceURI element (attribute) namespace URI
      * @param create when true, creates symbol if it is missing
      * @return symbol id or -1
+     * @throws ReadOnlyException if 'create' option specified and the symbol is missing
      */
-    public final short getNormalizedSymbol(String localName, String namespaceURI, boolean create) {
-        String normalizedQName = SymbolTable.getNormalizedQName(localName, namespaceURI);
+    public final short getNormalizedSymbol(String localName, String namespaceURI, boolean create) throws ReadOnlyException {
+        String normalizedQName = getNormalizedQName(localName, namespaceURI);
         return getSymbol(normalizedQName, namespaceURI, create);
     }
 
@@ -212,8 +266,9 @@
      * @param nsMap namespace map
      * @param create when true, creates symbol if it is missing
      * @return symbol id or -1
+     * @throws ReadOnlyException if 'create' option specified and the symbol is missing
      */
-    public final short getNormalizedSymbol(String lookup, NamespaceMap nsMap, boolean create) {
+    public final short getNormalizedSymbol(String lookup, NamespaceMap nsMap, boolean create) throws ReadOnlyException {
         // Parse [<namespaceURI>]<nsPrefix>:<localName> with optional nsPrefix
         if (lookup.startsWith("[")) {
             int idx = lookup.indexOf(']');
@@ -300,7 +355,7 @@
     // Implementation methods
     //
 
-    private static String getNormalizedQName(String localName, String namespaceURI) {
+    private String getNormalizedQName(String localName, String namespaceURI) {
         return "ns" + namespaceURI.hashCode() + ':' + localName;
     }
 

Modified: xml/xindice/trunk/java/src/org/apache/xindice/xml/dom/DOMCompressor.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/xml/dom/DOMCompressor.java?rev=568786&r1=568785&r2=568786&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/xml/dom/DOMCompressor.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/xml/dom/DOMCompressor.java Wed Aug 22 17:40:57 2007
@@ -21,11 +21,13 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.xindice.util.ReadOnlyException;
 import org.apache.xindice.xml.Signatures;
 import org.apache.xindice.xml.SymbolTable;
 import org.apache.xindice.xml.XMLCompressedOutput;
 
 import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
@@ -56,6 +58,8 @@
      *
      * @param node the node to write
      * @throws IOException if the write to underlying stream has failed
+     * @throws DOMException if used symbol table is read only and some of
+     *         node's content can not be serialized.
      */
     public void writeNode(Node node) throws IOException {
         // Check if it's node of ours
@@ -85,9 +89,21 @@
                     String nsURI = node.getNamespaceURI();
                     short symbolID;
                     if (nsURI != null) {
-                        symbolID = st.getSymbol(node.getNodeName(), nsURI, true);
+                        try {
+                            symbolID = st.getSymbol(node.getNodeName(), nsURI, true);
+                        } catch (ReadOnlyException e) {
+                            throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+                                                   "Element can not be serialized (read only symbol table). " +
+                                                   "Name: '" + node.getNodeName() + "', namespace: " + nsURI);
+                        }
                     } else {
-                        symbolID = st.getSymbol(node.getNodeName(), true);
+                        try {
+                            symbolID = st.getSymbol(node.getNodeName(), true);
+                        } catch (ReadOnlyException e) {
+                            throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+                                                   "Element can not be serialized (read only symbol table). " +
+                                                   "Name: '" + node.getNodeName() + "'");
+                        }
                     }
 
                     byte signature = Signatures.NODE_ELEM;
@@ -118,9 +134,21 @@
                     String nsURI = attr.getNamespaceURI();
                     short symbolID;
                     if (nsURI != null) {
-                        symbolID = st.getSymbol(attr.getName(), nsURI, true);
+                        try {
+                            symbolID = st.getSymbol(attr.getName(), nsURI, true);
+                        } catch (ReadOnlyException e) {
+                            throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+                                                   "Attribute can not be serialized (read only symbol table). " +
+                                                   "Name: '" + attr.getName() + "', namespace: " + nsURI);
+                        }
                     } else {
-                        symbolID = st.getSymbol(attr.getName(), true);
+                        try {
+                            symbolID = st.getSymbol(attr.getName(), true);
+                        } catch (ReadOnlyException e) {
+                            throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+                                                   "Attribute can not be serialized (read only symbol table). " +
+                                                   "Name: '" + attr.getName() + "'");
+                        }
                     }
                     writeShort(symbolID);
 
@@ -178,7 +206,13 @@
                         // TODO symbol =
                     } else {
                         encoding = 2;
-                        symbol = st.getSymbol(value, true);
+                        try {
+                            symbol = st.getSymbol(value, true);
+                        } catch (ReadOnlyException e) {
+                            throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+                                                   "Entity reference can not be serialized (read only symbol table). " +
+                                                   "Value: '" + value + "'");
+                        }
                         signature |= (byte) (Signatures.ENT_DEFINED);
                     }
                     writeByte(signature);

Modified: xml/xindice/trunk/java/tests/src/org/apache/xindice/xml/SymbolTableTest.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/tests/src/org/apache/xindice/xml/SymbolTableTest.java?rev=568786&r1=568785&r2=568786&view=diff
==============================================================================
--- xml/xindice/trunk/java/tests/src/org/apache/xindice/xml/SymbolTableTest.java (original)
+++ xml/xindice/trunk/java/tests/src/org/apache/xindice/xml/SymbolTableTest.java Wed Aug 22 17:40:57 2007
@@ -19,6 +19,7 @@
 
 package org.apache.xindice.xml;
 
+import org.apache.xindice.util.ReadOnlyException;
 import org.apache.xindice.xml.dom.DOMParser;
 
 import junit.framework.TestCase;
@@ -44,7 +45,7 @@
     }
 
 
-    public void testMissingSymbol() {
+    public void testMissingSymbol() throws Exception {
         assertNull(symbols.getSymbolInfo((short) 123));
 
         assertEquals(-1, symbols.getSymbol("missing"));
@@ -95,7 +96,7 @@
         assertFalse(symbols.isDirty());
     }
 
-    public void testAddSymbol() {
+    public void testAddSymbol() throws Exception {
         assertEquals(-1, symbols.getSymbol("missing"));
         assertTrue(symbols.getSymbol("missing", true) != -1);
         assertTrue(symbols.isDirty());
@@ -109,7 +110,7 @@
         assertEquals(s, si.getSymbolID());
     }
 
-    public void testAddNamespacedSymbol() {
+    public void testAddNamespacedSymbol() throws Exception {
         assertEquals(-1, symbols.getSymbol("missing", "urn:unknown"));
         assertTrue(symbols.getSymbol("missing", "urn:unknown", true) != -1);
         assertTrue(symbols.isDirty());
@@ -123,7 +124,7 @@
         assertEquals(s, si.getSymbolID());
     }
 
-    public void testGetNormalizedSymbol() {
+    public void testGetNormalizedSymbol() throws Exception {
         assertEquals(1, symbols.getNormalizedSymbol("simple", (NamespaceMap) null, false));
 
         assertEquals(-1, symbols.getNormalizedSymbol("[http://www.w3.org/1999/xhtml]spaced", (NamespaceMap) null, false));
@@ -140,5 +141,16 @@
         NamespaceMap m = new NamespaceMap();
         m.setNamespace("z", "http://www.w3.org/1999/xhtml");
         assertEquals(s, symbols.getNormalizedSymbol("z:spaced", m, false));
+    }
+
+    public void testReadOnly() throws Exception {
+        symbols = new SymbolTable(DOMParser.toDocument(SYMBOLS).getDocumentElement(), true);
+
+        assertEquals(-1, symbols.getSymbol("foo"));
+
+        try {
+            symbols.getSymbol("foo", true);
+            fail();
+        } catch (ReadOnlyException e) { }
     }
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.