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) { }
     }
 }


Reply via email to