dviner      2002/12/27 10:37:24

  Modified:    config   system.xml
               java/src/org/apache/xindice/core Collection.java
                        Database.java
               java/src/org/apache/xindice/server/rpc
                        RPCDefaultMessage.java
  Added:       java/src/org/apache/xindice/core MetaSystemCollection.java
               java/src/org/apache/xindice/core/meta MetaData.java
                        TimeRecord.java package.html
               java/src/org/apache/xindice/server/rpc/messages
                        GetCollectionMeta.java GetDocumentMeta.java
                        SetCollectionMeta.java SetDocumentMeta.java
  Log:
  Implementation of MetaData storage for Xindice.  This
  topic has been extensively discussed on the mailing list. Please
  see the following threads from the mailing list for more information
  http://marc.theaimsgroup.com/?t=104066672500001&r=1&w=2
  http://marc.theaimsgroup.com/?t=103946444400005&r=1&w=2
  http://marc.theaimsgroup.com/?t=103828933700002&r=1&w=2
  
  --dviner
  
  Revision  Changes    Path
  1.9       +3 -2      xml-xindice/config/system.xml
  
  Index: system.xml
  ===================================================================
  RCS file: /home/cvs/xml-xindice/config/system.xml,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- system.xml        2 Nov 2002 06:23:50 -0000       1.8
  +++ system.xml        27 Dec 2002 18:37:23 -0000      1.9
  @@ -6,7 +6,8 @@
     -->
   
   <xindice>
  -   <root-collection dbroot="./db/" name="db">
  +   <root-collection dbroot="./db/" name="db" use-metadata="off">
  +   <!-- Set use-metadata to on to enable metadata usage. -->
         <queryengine>
            <resolver autoindex="false" 
class="org.apache.xindice.core.query.XPathQueryResolver" />
            <resolver 
class="org.apache.xindice.core.xupdate.XUpdateQueryResolver" />
  
  
  
  1.13      +333 -47   
xml-xindice/java/src/org/apache/xindice/core/Collection.java
  
  Index: Collection.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xindice/java/src/org/apache/xindice/core/Collection.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Collection.java   22 Nov 2002 10:15:34 -0000      1.12
  +++ Collection.java   27 Dec 2002 18:37:23 -0000      1.13
  @@ -68,6 +68,7 @@
   import org.apache.xindice.core.filer.Filer;
   import org.apache.xindice.core.indexer.IndexManager;
   import org.apache.xindice.core.indexer.Indexer;
  +import org.apache.xindice.core.meta.MetaData;
   import org.apache.xindice.core.query.QueryEngine;
   import org.apache.xindice.util.Configurable;
   import org.apache.xindice.util.Configuration;
  @@ -133,11 +134,11 @@
      private long document_id = System.currentTimeMillis();
      private Object oidMutex = new Object();
      private String oidTemplate = null;
  - 
  +
      protected String name;
      private String canonicalName;
      private File collectionRoot;
  -   
  +
      private Filer filer = null;
   
      private boolean compressed = false;
  @@ -172,7 +173,7 @@
         // If no Filer is defined, skip Symbols and Indexes
         Configuration filerConfig = config.getChild(FILER);
         if ( filerConfig != null ) {
  -         
  +
            // Symbol Table Setup
            Configuration symConfig = config.getChild(SYMBOLS);
            internalSymbols = (symConfig != null);
  @@ -196,7 +197,7 @@
                  }
               }
            }
  -         
  +
            String className = filerConfig.getAttribute(CLASS);
            try {
               filer = (Filer)Class.forName(className).newInstance();
  @@ -212,7 +213,7 @@
                  log.warn("Filer '"+className+"' not available", e);
               }
            }
  -         
  +
            // Index Manager
            try {
               indexManager = new IndexManager(this);
  @@ -225,10 +226,10 @@
               }
            }
         }
  -      
  +
         super.setConfig(config);
   
  -      // observer      
  +      // observer
         DBObserver.getInstance().setCollectionConfig(this, config);
      }
   
  @@ -245,7 +246,7 @@
         if ( !collectionRoot.exists() )
            collectionRoot.mkdirs();
      }
  -   
  +
      /**
       * getParentCollection returns the parent Collection of this
       * Collection.
  @@ -261,13 +262,13 @@
         getDatabase().flushConfig();
         return success;
      }
  -   
  +
      public final Collection createCollection(String path, Configuration 
config) throws DBException {
         Collection col = super.createCollection(path, config);
         getDatabase().flushConfig();
         return col;
      }
  -   
  +
      // Convenience Methods
   
      /**
  @@ -296,7 +297,7 @@
      public QueryEngine getQueryEngine() throws DBException {
         return getDatabase().getQueryEngine();
      }
  -   
  +
      private void checkFiler(int faultCode) throws DBException {
         if ( filer == null )
            throw new DBException(faultCode, "This Collection '"+name+"' cannot 
store Documents");
  @@ -333,10 +334,10 @@
       */
      public final boolean dropIndexer(Indexer index) throws DBException {
         checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
  -      
  +
         if ( index == null )
            throw new DBException(FaultCodes.IDX_INDEX_NOT_FOUND, "Index Value 
Null");
  -      
  +
         boolean success = indexManager.drop(index.getName());
         getDatabase().flushConfig();
         return success;
  @@ -424,7 +425,7 @@
   
      protected final void setCanonicalName(String canonicalName) {
         this.canonicalName = canonicalName;
  -      
  +
         // Calculate The OID Template
         collection_id = Math.abs(canonicalName.hashCode());
         StringBuffer sb = new StringBuffer("00000000000000000000000000000000");
  @@ -435,7 +436,7 @@
         sb.setLength(32);
         oidTemplate = sb.toString();
      }
  -   
  +
      /**
       * getCanonicalDocumentName returns the canonical name for the specified
       * Key in relation to this Collection.
  @@ -446,10 +447,15 @@
       * @return The canonical name
       */
      public final String getCanonicalDocumentName(Key key) {
  +      return getCanonicalDocumentName(key.toString());
  +   }
  +
  +   public final String getCanonicalDocumentName(String key)
  +   {
         StringBuffer sb = new StringBuffer();
         sb.append(canonicalName);
         sb.append('/');
  -      sb.append(key.toString());
  +      sb.append(key);
         return sb.toString();
      }
   
  @@ -470,6 +476,8 @@
      }
   
      public boolean create() throws DBException {
  +      // update the meta information if necessary
  +      updateCollectionMeta();
         return true;
      }
   
  @@ -477,30 +485,38 @@
         if ( this == getDatabase() )
            throw new DBException(FaultCodes.DBE_CANNOT_DROP, "You Cannot Drop 
The Database");
   
  +
         DBObserver.getInstance().dropCollection(this);
  -      
  +
  +      // drop the meta if necessary
  +      if( isMetaEnabled() )
  +      {
  +         MetaSystemCollection metacol = getMetaSystemCollection();
  +         metacol.dropCollectionMeta(this);
  +      }
  +       
         // Drop Child Collections
         String[] cols = listCollections();
         for ( int i = 0; i < cols.length; i++ )
            dropCollection(getCollection(cols[i]));
  -      
  +
         if ( filer != null ) {
            // Drop Indexers
            String[] idx = indexManager.list();
            for ( int i = 0; i < idx.length; i++ )
               dropIndexer(getIndexer(idx[i]));
  -         
  +
            // Now Drop The Filer
            filer.drop();
         }
  -      
  +
         getCollectionRoot().delete();
         getDatabase().flushConfig();
   
         return true;
      }
   
  -   
  +
      // All Document Handling Code Follows
   
      /**
  @@ -546,10 +562,10 @@
         if ( symbols.isDirty() && !internalSymbols )
            getSystemCollection().saveSymbols(this, symbols);
      }
  -   
  +
      private void putDocument(Key key, Document document /* TODO used this 
variable , boolean create*/) throws DBException {
         checkFiler(FaultCodes.COL_NO_FILER);
  -            
  +
         if ( document instanceof DBDocument ) {
            // This is a shitty shitty hack... Kill immediately
            DBDocument dbDoc = (DBDocument)document;
  @@ -562,7 +578,7 @@
            try {
               byte[] b = DOMCompressor.Compress(document, symbols);
               value = new Value(b);
  -            
  +
               document = new DocumentImpl(b, symbols, new NodeSource(this, 
key));
            }
            catch ( Exception e ) {
  @@ -573,15 +589,15 @@
         }
   
         flushSymbolTable();
  -      
  +
         // Temporary until insert and update are separate
         Document oldDoc = getDocument(key);
         if ( oldDoc != null )
            indexManager.removeDocument(key, oldDoc);
         indexManager.addDocument(key, document);
  -            
  +
         filer.writeRecord(key, value);
  -            
  +
         // Cache Stuff
         if ( documentCache != null ) {
            if ( compressed )
  @@ -590,11 +606,103 @@
               documentCache.putDocument(this, key, document);
         }
   
  -      DBObserver.getInstance().putDocument(this, key, document, 
  +      DBObserver.getInstance().putDocument(this, key, document,
            oldDoc == null);
      }
   
      /**
  +    * update the modified time of this collection when appropriate
  +    */
  +   protected void updateCollectionMeta()
  +   {
  +      // update the meta data if necessary
  +      if( isMetaEnabled() )
  +      {
  +         MetaSystemCollection metacol = getMetaSystemCollection();
  +         MetaData meta = null;
  +         try
  +         {
  +            meta = metacol.getCollectionMeta(this);
  +         } catch (DBException e) {
  +            // something strange has happened.. can't get the
  +            // meta data for this collection
  +            if( log.isWarnEnabled() )
  +               log.warn("Error fetching collection meta. "+e);
  +            return;
  +         }
  +              
  +              if(log.isInfoEnabled())
  +                     log.info("Updating modified time for this collection's 
meta");
  +         long now = System.currentTimeMillis();
  +         if( null == meta )
  +         {
  +            meta = new MetaData(MetaData.COLLECTION, getCanonicalName(), 
  +                                now, now);
  +         }
  +         else
  +         {
  +            // this collection already has a meta.  so update its modified 
time.
  +            meta.setContext(0,now);
  +         }
  +         try {
  +            metacol.setCollectionMeta(this, meta);
  +         } catch(DBException e) {
  +            if( log.isWarnEnabled() )
  +               log.warn("Error setting the collection meta. "+e);
  +            return;
  +         }
  +      }
  +   } 
  +
  +   /**
  +    * update the modified time of this document when appropriate
  +    */
  +   protected void updateDocumentMeta(String id) throws DBException
  +   {
  +      // update the meta data if necessary
  +      if( ! isMetaEnabled() )
  +         return;
  +
  +      Document doc = getDocument(id);
  +      if( null == doc )
  +         throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
  +                "Document " + id + " does not exist");
  +
  +      MetaSystemCollection metacol = getMetaSystemCollection();
  +      MetaData meta = metacol.getDocumentMeta(this, id);
  +
  +      String path = getCanonicalDocumentName(id);
  +
  +
  +      /*
  +      TimeRecord rec = null;
  +      if( null == meta || !meta.hasContext() )
  +         rec = getDatabase().getTime(path);
  +
  +      long created = (null != rec) ? rec.getCreatedTime() : 
System.currentTimeMillis();
  +      long modified = (null != rec) ? rec.getModifiedTime() : 
System.currentTimeMillis();
  +      */
  +
  +      // this is wrong.. but it should work for now...
  +      long created = System.currentTimeMillis();
  +      long modified = System.currentTimeMillis();
  +
  +
  +      if( null == meta )
  +      {
  +         meta = new MetaData(MetaData.DOCUMENT, path, created, modified);
  +      }
  +      else if( !meta.hasContext() )
  +      {
  +         meta.setContext(created, modified);
  +      }
  +      else
  +      {
  +         meta.setContext(0,modified);
  +      }  
  +      metacol.setDocumentMeta(this,id,meta);
  +   }
  +   /**
       * insertDocument inserts a new Document into a Xindice Collection.
       *
       * @param document The Document
  @@ -603,6 +711,8 @@
      public final Key insertDocument(Document document) throws DBException {
         Key key = createNewOID();
         putDocument(key, document /*, true */);
  +      // update the meta information if necessary
  +      updateCollectionMeta();
         return key;
      }
   
  @@ -614,6 +724,8 @@
       */
      public final void insertDocument(Object docKey, Document document) throws 
DBException {
         putDocument(createNewKey(docKey), document /*, true */);
  +      // update the meta information if necessary
  +      updateCollectionMeta();
      }
   
      /**
  @@ -625,6 +737,8 @@
       */
      public final void setDocument(Object docKey, Document document) throws 
DBException {
         putDocument(createNewKey(docKey), document /*, false */);
  +      // update the meta for this document
  +      updateDocumentMeta(docKey.toString());
      }
   
      /**
  @@ -635,19 +749,26 @@
       */
      public final void remove(Object key) throws DBException {
         checkFiler(FaultCodes.COL_NO_FILER);
  -      
  +
         Key objKey = createNewKey(key);
   
         Document oldDoc = getDocument(objKey);
         if ( oldDoc != null )
            indexManager.removeDocument(objKey, oldDoc);
  -      
  +
         if ( documentCache != null )
            documentCache.removeDocument(this, objKey);
   
         if ( !filer.deleteRecord(objKey) )
            throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND, "Document 
Does Not Exist");
   
  +      // update the meta for this collection if necessary
  +      updateCollectionMeta();
  +      // remove the document meta
  +      if( isMetaEnabled() )
  +      {
  +         getMetaSystemCollection().dropDocumentMeta(this,objKey.toString());
  +      }
         DBObserver.getInstance().dropDocument(this, objKey);
      }
   
  @@ -657,15 +778,15 @@
       * @param docKey The Document Key
       * @return The Document
       */
  -   public final Document getDocument(Object docKey) throws DBException {     
 
  +   public final Document getDocument(Object docKey) throws DBException {
         checkFiler(FaultCodes.COL_NO_FILER);
  -      
  +
         Key key = createNewKey(docKey);
   
         Document doc = null;
         if ( documentCache != null )
            doc = documentCache.getDocument(this, key);
  -      
  +
         if ( doc == null ) {
            Record record = filer.readRecord(key);
            if ( record == null )
  @@ -681,7 +802,7 @@
            }
            else
               doc = parseDocument(key, value.toString());
  -         
  +
            flushSymbolTable();
   
            DBObserver.getInstance().loadDocument(this, record, doc);
  @@ -835,10 +956,10 @@
       */
      public final DocumentSet getDocumentSet() throws DBException {
         checkFiler(FaultCodes.COL_NO_FILER);
  -      
  +
         return new ColDocumentSet(filer.getRecordSet());
      }
  -   
  +
      /**
       * listDocuments returns a list of all document keys stored by this
       * collection.
  @@ -847,18 +968,18 @@
       */
      public final String[] listDocuments() throws DBException {
         checkFiler(FaultCodes.COL_NO_FILER);
  -      
  +
         RecordSet set = filer.getRecordSet();
         ArrayList temp = new ArrayList();
  -      
  +
         while (set.hasMoreRecords()) {
            Key key = set.getNextKey();
            temp.add(key.toString());
         }
  -      
  +
         return (String[]) temp.toArray(new String[0]);
      }
  -   
  +
      /**
       * getDocumentCount returns the count of Documents being maintained
       * by this Collection.
  @@ -867,7 +988,7 @@
       */
      public final long getDocumentCount() throws DBException {
         checkFiler(FaultCodes.COL_NO_FILER);
  -      
  +
         return filer.getRecordCount();
      }
   
  @@ -882,17 +1003,182 @@
         }
      }
   
  -   
  +   // META DATA RELATED DOCS
  +   /**
  +    * Returns whether or not meta data is enabled.
  +    * @return boolean whether or not meta data is enabled.
  +    */
  +   public boolean isMetaEnabled()
  +   {
  +      return getDatabase().isMetaEnabled();
  +   }
  +
  +   /**
  +    * Return the MetaData for this collection.
  +    * 
  +    * If metadata is not enabled in the configuration, the MetaData object
  +    * returned will be null.
  +    * @return MetaData this collection's metadata.
  +    */
  +   public MetaData getCollectionMeta() throws DBException
  +   {
  +      MetaData meta = null;
  +      if( ! isMetaEnabled() )
  +      {
  +         if(log.isWarnEnabled())
  +         {
  +            log.warn("Meta information requested but not enabled in 
config!");
  +         }
  +         return meta;
  +      }
  +      MetaSystemCollection metacol = getMetaSystemCollection();
  +      meta = metacol.getCollectionMeta(this);
  +      long now = System.currentTimeMillis();
  +      if( null == meta )
  +      {
  +         meta = new MetaData(MetaData.COLLECTION, getCanonicalName(), now, 
now);
  +         metacol.setCollectionMeta(this, meta);
  +      }
  +      return meta;
  +   }
  +
  +   /**
  +    * Reset the metadata object for this collection.
  +    * @param meta the Metadata to use
  +    */
  +   public void setCollectionMeta(MetaData meta) throws DBException
  +   {
  +      if( ! isMetaEnabled() )
  +      {
  +         if(log.isWarnEnabled())
  +         {
  +            log.warn("Meta information requested but not enabled in 
config!");
  +         }
  +         return;
  +      }
  +      if( null != meta )
  +      {
  +         if( meta.getType() != MetaData.COLLECTION )
  +            throw new DBException( FaultCodes.GEN_UNKNOWN,
  +                    "Mismatch type of meta data for collection " +
  +                    getCanonicalName());
  +
  +         MetaSystemCollection metacol = getMetaSystemCollection();
  +         metacol.setCollectionMeta(this, meta);
  +      }
  +   }
  +
  +   /**
  +    * 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
  +    */
  +   public MetaData getDocumentMeta( String id ) throws DBException
  +   {
  +      MetaData meta = null;
  +      if( ! isMetaEnabled() )
  +      {
  +         if(log.isWarnEnabled())
  +         {
  +            log.warn("Meta information requested but not enabled in 
config!");
  +         }
  +         return meta;
  +      }
  +      Document doc = getDocument(id);
  +      if( null == doc )
  +         throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
  +                "Document " + id + " does not exist");
  +
  +      MetaSystemCollection metacol = getMetaSystemCollection();
  +      meta = metacol.getDocumentMeta(this, id);
  +
  +      String path = getCanonicalDocumentName(id);
  +
  +
  +      /*
  +      TimeRecord rec = null;
  +      if( null == meta || !meta.hasContext() )
  +         rec = getDatabase().getTime(path);
  +
  +      long created = (null != rec) ? rec.getCreatedTime() : 
System.currentTimeMillis();
  +      long modified = (null != rec) ? rec.getModifiedTime() : 
System.currentTimeMillis();
  +      */
  +
  +      // this is wrong.. but it should work for now...
  +      long created = System.currentTimeMillis();
  +      long modified = System.currentTimeMillis();
  +
  +
  +      if( null == meta )
  +      {
  +         meta = new MetaData(MetaData.DOCUMENT, path, created, modified);
  +         metacol.setDocumentMeta(this, id, meta);
  +      }
  +      else if( !meta.hasContext() )
  +      {
  +         meta.setContext(created, modified);
  +      }
  +
  +      return meta;
  +   }
  +
  +   /**
  +    * Set the metadata associated with a document within this collection.
  +    * 
  +    * @param id the document name
  +    * @param meta the metadata object to be used.
  +    */
  +   public void setDocumentMeta(String id, MetaData meta) throws DBException
  +   {
  +      if( ! isMetaEnabled() )
  +      {
  +         if(log.isWarnEnabled())
  +         {
  +            log.warn("Meta information requested but not enabled in 
config!");
  +         }
  +         return;
  +      }
  +      Document doc = getDocument(id);
  +      if( null == doc )
  +         throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
  +                "Document " + id + " does not exist");
  +
  +      if( null != meta )
  +      {
  +         if( meta.getType() == MetaData.UNKNOWN ||
  +             meta.getType() == MetaData.COLLECTION )
  +            throw new DBException( FaultCodes.GEN_UNKNOWN,
  +                    "Mismatch type of meta data for document " +
  +                    getCanonicalDocumentName(id));
  +
  +         MetaSystemCollection metacol = getMetaSystemCollection();
  +         metacol.setDocumentMeta(this,id, meta);
  +      }
  +   }
  +
  +   /**
  +    * Return the MetaSystemCollection for the database containing this
  +    * collection.
  +    * 
  +    * @return MetaSystemCollection
  +    */
  +   private MetaSystemCollection getMetaSystemCollection() //throws 
DBException
  +   {
  +      return getDatabase().getMetaSystemCollection();
  +   }
  +
  +
      /**
       * ColDocumentSet
       */
      private class ColDocumentSet implements DocumentSet {
         private RecordSet set;
  -      
  +
         public ColDocumentSet(RecordSet set) {
            this.set = set;
         }
  -      
  +
         public boolean hasMoreDocuments() throws DBException {
            return set.hasMoreRecords();
         }
  @@ -920,7 +1206,7 @@
            }
            return null;
         }
  -      
  +
         public Document getNextDocument() throws DBException {
            Container c = getNextContainer();
            if ( c != null )
  @@ -930,7 +1216,7 @@
         }
      }
   
  -   
  +
      /**
       * ColContainer
       */
  
  
  
  1.17      +93 -10    
xml-xindice/java/src/org/apache/xindice/core/Database.java
  
  Index: Database.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xindice/java/src/org/apache/xindice/core/Database.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- Database.java     30 Nov 2002 18:32:07 -0000      1.16
  +++ Database.java     27 Dec 2002 18:37:23 -0000      1.17
  @@ -63,6 +63,7 @@
   import org.apache.xindice.util.Configuration;
   import org.apache.xindice.util.Named;
   import org.apache.xindice.util.XindiceException;
  +import org.apache.xindice.core.meta.TimeRecord;
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  @@ -84,19 +85,27 @@
      private static final String QUERYENGINE = "queryengine";
      private static final String DATABASE = "database";
      private static final String COLKEY = "database.xml";
  +   private static final String METADATA = "use-metadata";
      public static final String NAME = "name";
   
  +
      private static Log log = LogFactory.getLog("org.apache.xindice.core");
   
      public static final String PROP_XINDICE_HOME = "xindice.home";
  -   
  +
      private static final Map databases = new HashMap(); // String to Database
   
      private DocumentCache docCache = new DocumentCache();
  -   
  +
      private SystemCollection sysCol = null;
   
  +   private MetaSystemCollection metaCol = null;
  +
      private boolean sysInit = false;
  +   private boolean metaInit = false;
  +   private boolean metaEnabled = false;
  +   // key = canonical name, value = timerecord
  +   private Map timestamps = new HashMap();
   
      private QueryEngine engine = new QueryEngine(this);
   
  @@ -113,7 +122,7 @@
   
         name = config.getAttribute(NAME);
         setCanonicalName('/' + getName());
  -      
  +
         String dbroot = config.getAttribute(DBROOT);
         File dbrootDir = new File(dbroot);
         if (!dbrootDir.isAbsolute()) {
  @@ -150,7 +159,7 @@
            collections.put(sysCol.getName(), sysCol);
            sysInit = true;
         }
  -      
  +
         try {
            // Bootstrap from the database itself...  This is accomplished
            // by intercepting the setConfig call and using a Configuration
  @@ -164,7 +173,7 @@
               colDoc.appendChild(root);
               
sysCol.getCollection(SystemCollection.CONFIGS).setDocument(COLKEY, colDoc);
            }
  -         
  +
            super.setConfig(new Configuration(colDoc.getDocumentElement(), 
false));
         }
         catch ( Exception e ) {
  @@ -176,7 +185,34 @@
         // Register the Database with the VM
         databases.put(getName(), this);
   
  -      // observer 
  +      // initialize the meta collection
  +      // but only if it's turned on in the config.
  +      String metaCfg = config.getAttribute(METADATA);
  +      if ( metaCfg.equalsIgnoreCase("on") )
  +      {
  +         metaEnabled = true;
  +         if (!metaInit)
  +         {
  +            metaCol = new MetaSystemCollection(this);
  +            try {
  +               metaCol.init();
  +            }
  +            catch ( XindiceException e ) {
  +               if (log.isDebugEnabled()) {
  +                  log.debug("Error initializing the meta collection", e);
  +               }
  +            }
  +            // should this attach the meta collection to the database?
  +
  +            collections.put(metaCol.getName(), metaCol);
  +            metaInit = true;
  +            if (log.isInfoEnabled()) {
  +               log.info("Meta information initialized");
  +            }
  +         }
  +      }
  +
  +      // observer
         DBObserver.getInstance().setDatabaseConfig(this, collections, config);
      }
   
  @@ -184,6 +220,25 @@
         return sysCol;
      }
   
  +   /**
  +    * Return the MetaSystem collection for this database.
  +    * 
  +    * It will return null if metadata is not enabled on this database.
  +    * @return MetaSystemCollection
  +    */
  +   public MetaSystemCollection getMetaSystemCollection() {
  +      return metaCol;
  +   }
  +   
  +   /**
  +    * Return whether or not metadata is enabled on this database.
  +    * @return boolean
  +    */
  +   public boolean isMetaEnabled()
  +   {
  +      return metaEnabled;
  +   }
  +
      public Database getDatabase() {
         return this;
      }
  @@ -202,16 +257,16 @@
               log.error("Error Writing Configuration '"+name+"', for database 
"+getName(), e);
            }
         }
  -      // observer      
  +      // observer
         DBObserver.getInstance().flushDatabaseConfig(this, config);
      }
  -  
  +
      public boolean close() throws DBException {
         flushConfig();
         databases.remove( getName() );
         return true;
      }
  -      
  +
      /**
       * getDocumentCache returns the Database-level Document Cache.
       *
  @@ -229,6 +284,34 @@
       */
      public QueryEngine getQueryEngine() {
         return engine;
  +   }
  +
  +   // methods for recording the times when meta data is enabled.
  +   public synchronized void recordTime( String path, long created, long 
modified )
  +   {
  +      TimeRecord rec = (TimeRecord)timestamps.get(path);
  +      if( null == rec ) {
  +         rec = new TimeRecord(created, modified);
  +         timestamps.put(path, rec);
  +      }
  +      else
  +      {
  +         if( created > 0 )
  +            rec.setCreatedTime(created);
  +         if( modified > 0 )
  +            rec.setModifiedTime(modified);
  +      }
  +   }
  +
  +   public synchronized void removeTime( String path )
  +   {
  +      timestamps.remove(path);
  +   }
  +
  +   public synchronized TimeRecord getTime( String path )
  +   {
  +      TimeRecord rec = (TimeRecord)timestamps.get(path);
  +      return rec;
      }
   }
   
  
  
  
  1.1                  
xml-xindice/java/src/org/apache/xindice/core/MetaSystemCollection.java
  
  Index: MetaSystemCollection.java
  ===================================================================
  package org.apache.xindice.core;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xindice" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2001, The dbXML
   * Group, L.L.C., http://www.dbxmlgroup.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $Id: MetaSystemCollection.java,v 1.1 2002/12/27 18:37:23 dviner Exp $
   */
  
  
  import org.apache.xindice.util.Configuration;
  import org.apache.xindice.core.*;
  import org.apache.xindice.core.meta.MetaData;
  import org.apache.xindice.server.*;
  import org.apache.xindice.xml.*;
  import org.apache.xindice.xml.dom.*;
  import org.apache.xindice.tools.*;
  import org.apache.xindice.util.*;
  
  import org.w3c.dom.*;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import java.io.File;
  import java.util.StringTokenizer;
  
  
  
  /**
   * MetaSystemCollection represents the Meta System Collection.  Beyond
   * standard Collection operations, this class will provide facilities
   * for Meta data management.
   */
  public final class MetaSystemCollection extends Collection
  {
      public static final String METACOL      = "meta";
      public static final String METAS        = "Metas";
      public static final String COLLECTION_META_DATA = "_META_DATA_";
  
      private String dbCanonicalName;
      private String metaCanonicalName;
        private static Log log = LogFactory.getLog("org.apache.xindice.core");
  
      public MetaSystemCollection(Database db)
      {
          super(db);
      }
  
      public void init() throws DBException
      {
          // Bootstrap the System Collection
  
          String MetaCol =
           "<collection name=\""+METACOL+"\">"
           // Meta System Collections
         + "   <collections>"
           // Meta Collections
         + "      <collection name=\""+METAS+"\" compressed=\"true\">"
         + "         <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" 
/>"
         + "      </collection>"
  
         + "   </collections>"
         + "</collection>";
  
          try {
              Document metaDoc = DOMParser.toDocument(MetaCol);
              Configuration metaCfg = new Configuration(metaDoc, false);
              setConfig(metaCfg);
          }
          catch ( Exception e ) {
                        if (log.isFatalEnabled()) {
                  log.fatal("FATAL ERROR: Generating System Collection 
'"+METACOL+"'", e);
              }
              System.exit(1);
          }
  
          // set the canonical names
          dbCanonicalName = getParentCollection().getCanonicalName();
          metaCanonicalName = getCanonicalName();
      }
  
      /**
       * Returns the corresponding Meta Collection for the given
       * collection, optionally creating the hierarchy
         *
         * @param collection the collection whose meta you want
         * @param create whether or not to create the meta if its missing
         * @return collection the meta collection for the requested collection
       */
      public Collection getMetaCollection(Collection collection,
          boolean create)
      throws DBException
      {
          String path = collection.getCanonicalName();
  
          // different database
          if( !path.startsWith(dbCanonicalName) )
              return null;
  
          // this is a meta collection
          if( path.startsWith(metaCanonicalName) )
              return null;
  
          Collection current = getCollection(METAS);
          StringTokenizer st = new StringTokenizer(
              path.substring(dbCanonicalName.length()), "/");
  
          while( current != null && st.hasMoreTokens() )
          {
              String segment = st.nextToken().trim();
              if ( segment.length() == 0 )
                 continue;
  
              Collection childcol = current.getCollection(segment);
              if( null == childcol )
              {
                  if( !create )
                      return null;
  
                  String cfgText =
                  "<collection name=\""+segment+"\" compressed=\"true\">" +
                  "  <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" 
/>" +
                  "</collection>";
  
                  try
                  {
                      Document cfgDoc = DOMParser.toDocument(cfgText);
                      Configuration cfg = new Configuration(cfgDoc, false);
                      childcol = current.createCollection(segment, cfg);
                  }
                  catch( DBException de )
                  {
                      throw de;
                  }
                  catch( Exception e )
                  {
                      throw new DBException(FaultCodes.getFaultCode(e));
                  }
              }
              current = childcol;
          }
  
          return current;
      }
  
      /**
       * dropCollectionMeta removes the MetaData for the specified
       * Collection.
       *
       * @param collection The Collection whose meta is required
       */
      public void dropCollectionMeta(Collection collection)
      throws DBException
      {
          Collection mcol = getMetaCollection(collection, false);
          if( null != mcol )
          {
              try {
                  mcol.drop();
              }
              catch( DBException e ) {
                  // fail silently
              }
          }
      }
  
      /**
       * getCollectionMeta retrieves the MetaData for the specified
       * Collection.  Assumption is that the corresponding collection
       * must already exist.
       *
       * @param collection The Collection whose meta is required
       * @return The requested MetaData
       */
      public MetaData getCollectionMeta(Collection collection)
      throws DBException
      {
          Collection mcol = getMetaCollection(collection, true);
  
          if( null != mcol )
          {
              MetaData meta = (MetaData)mcol.getObject(COLLECTION_META_DATA);
              if ( meta == null )
                  meta = new MetaData();
  
              if( meta.getType() == MetaData.UNKNOWN )
                  meta.setType(MetaData.COLLECTION);
              meta.setOwner(collection.getCanonicalName());
              meta.setDirty(false);
              return meta;
          }
          return null;
      }
  
      /**
       * setCollectionMeta save the Meta for the specified Collection.
       *
       * @param collection The Collection that owns the MetaData
       * @param meta The MetaData
       */
      public void setCollectionMeta(Collection collection, MetaData meta)
      throws DBException
      {
          if( null == meta )
              return;
  
          Collection mcol = getMetaCollection(collection, true);
          if( null != mcol )
          {
              mcol.setObject(COLLECTION_META_DATA, meta);
              meta.setDirty(false);
          }
      }
  
      /**
       * dropDocumentMeta removes the MetaData for the specified
       * Document.
       *
       * @param collection The Collection whose meta is required
       * @param id the Document id
       */
      public void dropDocumentMeta(Collection collection, String id)
      throws DBException
      {
          Collection mcol = getMetaCollection(collection, false);
          if( null != mcol )
          {
              try {
                  mcol.remove(id);
              }
              catch( DBException e ) {
                  // fail silently
              }
          }
      }
  
      /**
       * getDocumentMeta retrieves the MetaData for the specified
       * document.
       *
       * @param collection The Collection whose meta is required
       * @param id the ID
       * @return The requested MetaData
       */
      public MetaData getDocumentMeta(Collection collection, String id)
      throws DBException
      {
          Collection mcol = getMetaCollection(collection, true);
          if( null != mcol )
          {
              MetaData meta = (MetaData)mcol.getObject(id);
              if ( meta == null )
                  meta = new MetaData();
  
              if( meta.getType() == MetaData.UNKNOWN )
                  meta.setType(MetaData.DOCUMENT);
              meta.setOwner(collection.getCanonicalName() + "/" + id);
              meta.setDirty(false);
              return meta;
          }
          return null;
      }
  
      /**
       * setDocumentMeta save the Meta for the specified Collection.
       *
       * @param collection The Collection that owns the MetaData
       * @param id
       * @param meta The MetaData
       */
      public void setDocumentMeta(Collection collection, String id, MetaData 
meta)
      throws DBException
      {
          if( null == meta )
              return;
  
          Collection mcol = getMetaCollection(collection, true);
          if( null != mcol )
          {
              mcol.setObject(id, meta);
              meta.setDirty(false);
          }
      }
  }
  
  
  
  
  1.1                  
xml-xindice/java/src/org/apache/xindice/core/meta/MetaData.java
  
  Index: MetaData.java
  ===================================================================
  package org.apache.xindice.core.meta;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xindice" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2001, The dbXML
   * Group, L.L.C., http://www.dbxmlgroup.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $Id: MetaData.java,v 1.1 2002/12/27 18:37:24 dviner Exp $
   */
  
  import org.w3c.dom.Node;
  import org.w3c.dom.DOMException;
  import org.w3c.dom.Element;
  import org.w3c.dom.Comment;
  import org.w3c.dom.Document;
  import org.w3c.dom.NodeList;
  
  import java.util.Date;
  import java.util.Enumeration;
  import java.util.Vector;
  import java.util.Hashtable;
  
  import org.apache.xindice.xml.XMLSerializable;
  import org.apache.xindice.xml.dom.DocumentImpl;
  import org.apache.xindice.xml.TextWriter;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /**
   * Implements the MetaData interface.
   *
   * <pre>
   * &lt;meta&gt;
   *   &lt;system [type="doc|col"] [href="uri"]/&gt;
   *   &lt;attrs&gt;
   *     &lt;attr name="name" value="value"/&gt;
   *     &lt;attr name="name" value="value"/&gt;
   *   &lt;/attrs&gt;
   *   &lt;custom&gt;
   *     ...
   *   &lt;/custom&gt;
   * &lt;/meta&gt;
   * </pre>
   *
   * @author ku
   * @author Dave Viner <[EMAIL PROTECTED]>
   */
  public class MetaData implements XMLSerializable
  {
      public final static short UNKNOWN       = 0;
      public final static short COLLECTION    = 1;
      public final static short DOCUMENT      = 2;
      public final static short LINK          = 3;
  
        public final static String NS_URI       = 
"http://apache.org/xindice/metadata";;
        //public final static String NS_PREFIX    = "md";
        public final static boolean USE_NS      = true;
        
      private static final String E_META      = "meta";
      private static final String E_SYSTEM    = "system";
      private static final String E_ATTRS     = "attrs";
      private static final String E_ATTR      = "attr";
      private static final String E_CUSTOM    = "custom";
      private static final String E_CREATED   = "created";
      private static final String E_MODIFIED  = "modified";
  
      private static final String A_NAME      = "name";
      private static final String A_VALUE     = "value";
      private static final String A_TYPE      = "type";
      private static final String A_HREF      = "href";
        
      private static final Enumeration EMPTY =
          (new Vector()).elements();
  
      private transient boolean dirty = false;
      private transient long created = 0;
      private transient long modified = 0;
      private transient String owner = null;
  
        private static Log log = LogFactory.getLog("org.apache.xindice.core");
        
      private short type = UNKNOWN;
      private String link = null;
      private Hashtable attrs = null;
      private Document custom = null;
  
      public MetaData()
      {}
  
        /**
         * @param owner the owner of this metadata.
         */
      public MetaData( String owner )
      {
          this.owner = owner;
      }
  
  
        /**
         * @param type the type of object for this metadata
         * @param owner the owner of this metadata
         * @param created the time when this was created
         * @param modified the time when this was modified.
         */
      public MetaData( short type, String owner, long created, long modified )
      {
          this.type = type;
          this.owner = owner;
          this.created = created;
          this.modified = modified;
      }
  
        /**
         * @param elem an XML representation of the desired metadata.
         */
      public MetaData(Element elem)
      {
          streamFromXML(elem);
      }
  
        /**
         * Returns whether this MetaData is dirty
         *
         * @return boolean
         */
      public final boolean isDirty()
      {
          return dirty;
      }
  
        /**
         * Reset the dirtiness of this object
         *
         * @param dirty
         */
      public final void setDirty(boolean dirty)
      {
          this.dirty = dirty;
      }
  
      /**
       * Returns the time of creation
       * @return long creation time
       */
      public long getCreatedTime()
      {
          return created;
      }
  
      /**
       * Returns the time of last modification
       * @return long last modified time
       */
      public long getLastModifiedTime()
      {
          return modified;
      }
  
      /**
       * Returns the type of the owner object, e.g., COLLECTION,
       * DOCUMENT, or LINK
       * @return short the object type
       */
      public short getType()
      {
          return type;
      }
  
      /**
       * Returns the canonical name of the owner object.
       * @return String the canonical name of the owner object
       */
      public String getOwner()
      {
          return owner;
      }
  
      /**
       * Returns enumeration of all attributes
       * @return Enumeration of attributes
       */
      public Enumeration getAttributeKeys()
      {
          if( null == attrs )
              return EMPTY;
  
          return attrs.keys();
      }
  
      /**
       * Retrieves the attribute by name
       * @param name the attribute name
       * @return String the value of attribute, or null if not found
       */
      public Object getAttribute( final Object name )
      {
          if( null == attrs )
              return null;
  
          return attrs.get(name);
      }
  
      public Boolean getAttributeAsBoolean( final Object name )
      {
          Object o = getAttribute(name);
          if( null == o )
              return null;
  
          if( o instanceof Boolean )
              return (Boolean)o;
  
          if( o instanceof Number )
          {
              Number n = (Number)o;
              return new Boolean(n.intValue() != 0);
          }
  
          String s = o.toString();
          return new Boolean(s.equalsIgnoreCase("true"));
      }
  
      public Integer getAttributeAsInteger( final Object name )
      {
          Object o = getAttribute(name);
          if( null == o )
              return null;
  
          if( o instanceof Integer )
              return (Integer)o;
  
          if( o instanceof Number )
          {
              Number n = (Number)o;
              return new Integer(n.intValue());
          }
  
          try
          {
              int v = Integer.parseInt(o.toString());
              return new Integer(v);
          }
          catch( Exception e )
          {
              return null;
          }
      }
  
      public Long getAttributeAsLong( final Object name )
      {
          Object o = getAttribute(name);
          if( null == o )
              return null;
  
          if( o instanceof Long )
              return (Long)o;
  
          if( o instanceof Number )
          {
              Number n = (Number)o;
              return new Long(n.longValue());
          }
  
          try
          {
              long v = Long.parseLong(o.toString());
              return new Long (v);
          }
          catch( Exception e )
          {
              return null;
          }
      }
  
      public Short getAttributeAsShort( final Object name )
      {
          Object o = getAttribute(name);
          if( null == o )
              return null;
  
          if( o instanceof Short )
              return (Short)o;
  
          if( o instanceof Number )
          {
              Number n = (Number)o;
              return new Short(n.shortValue());
          }
  
          try
          {
              short v = Short.parseShort(o.toString());
              return new Short(v);
          }
          catch( Exception e )
          {
              return null;
          }
      }
  
      /**
       * Sets the attribute by name
       * @param name the attribute name
       * @param value the attribute value
       * @return Object the old value, if any
       */
      public Object setAttribute( final Object name, final Object value )
      {
          if( null == attrs )
          {
              attrs = new Hashtable();
              dirty = true;
          }
          Object prev = attrs.put(name, value);
          if( prev == null || !prev.equals(value) )
              dirty = true;
  
          return prev;
      }
  
      /**
       * Remove an attribute by name
       * @param name the attribute to remove
       * @return Object the removed value
       */
      public Object removeAttribute( final Object name )
      {
          if( null == attrs )
              return null;
  
          Object prev = attrs.remove(name);
          if( null != prev )
              dirty = true;
  
          return prev;
      }
  
      /**
       * Returns the (optional) custom meta document
       * @return Document the custom meta document
       */
      public Document getCustomDocument()
      {
          return custom;
      }
  
      /**
       * Sets the (optional) custom meta document
       * @param doc the Document
       */
      public void setCustomDocument( Document doc )
      {
          this.custom = doc;
          this.dirty = true;
      }
  
      /**
       * Copies from another meta data
       * @param from the meta to copy from
       */
      public void copyFrom( final MetaData meta )
      {
          this.created = meta.getCreatedTime();
          this.modified = meta.getLastModifiedTime();
          this.owner = meta.getOwner();
          this.type = meta.getType();
          this.link = meta.getLinkTargetURI();
          this.attrs = null;
          for( Enumeration e = meta.getAttributeKeys(); e.hasMoreElements(); )
          {
              Object key = e.nextElement();
              Object value = meta.getAttribute(key);
              if( null == this.attrs )
                  this.attrs = new Hashtable();
              this.attrs.put(key, value);
          }
          this.custom = null;
  
          Document doc = meta.getCustomDocument();
          if( null != doc )
          {
              this.custom = new DocumentImpl();
              this.custom.appendChild(
                  this.custom.importNode(doc.getDocumentElement(), true));
          }
          this.dirty = false;
      }
  
      /**
       * Returns the linked target URI, if this is a link
       * @return String the URI of the linked target
       */
      public String getLinkTargetURI()
      {
          return link;
      }
  
      //
      // Serialization to/from XML
      //
  
        /**
         * Stream this MetaData into an xml document
         * @param doc the xml document to be populated.
         */
      public final Element streamToXML(Document doc)
      throws DOMException
      {
          return streamToXML(doc, false);
      }
  
        /**
         * Stream this MetaData into an xml document
         * @param doc the xml document to populate
         * @param includeTime whether or not to include the create/modified 
times
         * @return Element the root element
         */
      public final Element streamToXML(Document doc, boolean includeTime )
      throws DOMException
      {
                Element root = null;
                if( !USE_NS )
                {
                        root = doc.createElement(E_META);
                }
                else
                {
                        root = doc.createElementNS(NS_URI, E_META);
                        root.setAttribute("xmlns",NS_URI);
                }
          doc.appendChild(root);
  
                Element systemElement = null;
                if(!USE_NS)
                {
                        systemElement = doc.createElement(E_SYSTEM);
                }
                else
                {
                        systemElement = doc.createElementNS(NS_URI, E_SYSTEM);
                }
          systemElement.setAttribute(A_TYPE, getTypeString(type));
          root.appendChild(systemElement);
          if( includeTime )
          {
              if( created > 0 )
              {
                  String message = "Create time is " + (new Date(created));
                  Comment comment = doc.createComment(message);
                  systemElement.appendChild(comment);
              }
                        
                        Element timeElement = null;
                        if(!USE_NS)
                        {
                                timeElement = doc.createElement(E_ATTR);
                        }
                        else
                        {
                                timeElement = doc.createElementNS(NS_URI, 
E_ATTR);
                        }
              timeElement.setAttribute(A_NAME, E_CREATED);
              timeElement.setAttribute(A_VALUE, Long.toString(created));
              systemElement.appendChild(timeElement);
  
              if( modified > 0 )
              {
                  String message = "Modified time is " + (new Date(modified));
                  Comment comment = doc.createComment(message);
                  systemElement.appendChild(comment);
              }
                        if(!USE_NS)
                        {
                                timeElement = doc.createElement(E_ATTR);
                        }
                        else
                        {
                                timeElement = doc.createElementNS(NS_URI, 
E_ATTR);
                        }
              timeElement.setAttribute(A_NAME, E_MODIFIED);
              timeElement.setAttribute(A_VALUE, Long.toString(modified));
              systemElement.appendChild(timeElement);
          }
          if( null != link )
          {
              systemElement.setAttribute(A_HREF, link);
          }
  
          if( null != attrs && attrs.size() > 0 )
          {
                        Element attrsElement = null;
                        if(!USE_NS)
                        {
                                attrsElement = doc.createElement(E_ATTRS);
                        }
                        else
                        {
                                attrsElement = doc.createElementNS(NS_URI, 
E_ATTRS);
                        }
              root.appendChild(attrsElement);
  
              for( Enumeration e = attrs.keys(); e.hasMoreElements(); )
              {
                  Object key = e.nextElement();
                  Object value = attrs.get(key);
  
                  if( null == key )
                      continue;
  
                                Element attrElement = null;
                                if(!USE_NS)
                                {
                                        attrElement = doc.createElement(E_ATTR);
                                }
                                else
                                {
                                        attrElement = 
doc.createElementNS(NS_URI, E_ATTR);
                                }
                  attrsElement.appendChild(attrElement);
  
                  attrElement.setAttribute(A_NAME, key.toString());
                  if( null != value )
                      attrElement.setAttribute(A_VALUE, value.toString());
              }
          }
  
          if( null != custom )
          {
                        Element customElement = null;
                        if(!USE_NS)
                        {
                                customElement = doc.createElement(E_CUSTOM);
                        }
                        else
                        {
                                customElement = doc.createElementNS(NS_URI, 
E_CUSTOM);
                        }
  
                        root.appendChild(
                  doc.importNode(custom.getDocumentElement(), true));
          }
  
          return root;
      }
  
        /**
         * Given some xml, populate the metadata.
         * @param source The xml to populate metadata with
         */
      public final void streamFromXML(Element source)
      throws DOMException
      {
          streamFromXML(source, false);
      }
  
        /**
         * Given some xml, populate the metadata.
         * @param source The xml to populate the metadata with
         * @param includeTime Whether or not to reset the create/modified times
         */
      public final void streamFromXML(Element source, boolean includeTime )
      throws DOMException
      {
          this.link = null;
          this.attrs = null;
          this.custom = null;
  
                String systemElemName = E_SYSTEM;
                String attrsElemName  = E_ATTRS;
                String customElemName = E_CUSTOM;
                String attrElemName   = E_ATTR;
  
          NodeList list = source.getChildNodes();
          for( int i = 0; i < list.getLength(); i++ )
          {
              Node node = list.item(i);
  
              if( node.getNodeType() != Node.ELEMENT_NODE )
                  continue;
  
              Element element = (Element)node;
              String elementName = element.getNodeName();
                        String prefix = element.getPrefix();
  
              if( systemElemName.equals(elementName) )
              {
                  String attrStr = element.getAttribute(A_TYPE);
                  if( null != attrStr )
                      this.type = parseTypeString(attrStr);
  
                  if( this.type == LINK )
                      this.link = element.getAttribute(A_HREF);
  
                  if( includeTime )
                  {
                      NodeList children = element.getChildNodes();
                      for( int j = 0; j < children.getLength(); j++ )
                      {
                          Node childNode = children.item(j);
                          if( !(childNode instanceof Element) )
                              continue;
  
                          Element child = (Element)childNode;
                          String childName = child.getNodeName();
  
                                                
                          if( attrElemName.equals(childName) )
                          {
                              String nameStr = child.getAttribute(A_NAME);
                              String valueStr = child.getAttribute(A_VALUE);
                              if( null != nameStr && null != valueStr )
                              {
                                  if( E_CREATED.equals(nameStr) )
                                      this.created = Long.parseLong(valueStr);
                                  else
                                  if( E_MODIFIED.equals(nameStr) )
                                      this.modified = Long.parseLong(valueStr);
                              }
                          }
                                                else
                                                {
                                                        if(log.isDebugEnabled())
                                                                
log.debug("Ignorning unknown child elem "+childName);
                                                }
                      }
                  }
              }
              else
              if( attrsElemName.equals(elementName) )
              {
                  NodeList attrList = 
element.getElementsByTagName(attrElemName);
                  for( int j = 0; j < attrList.getLength(); j++ )
                  {
                      Element e = (Element)attrList.item(j);
  
                      String attrName = e.getAttribute(A_NAME);
                      if( null == attrName) continue;
  
                      if( null == this.attrs )
                          this.attrs = new Hashtable();
                      this.attrs.put( attrName, e.getAttribute(A_VALUE));
                  }
              }
              else
              if( customElemName.equals(elementName) )
              {
                  this.custom = new DocumentImpl();
                                Node custdoc = 
this.custom.importNode(element,true);
                                
                                /* if you want really verbose debugging try 
this */ 
                                if(log.isTraceEnabled())
                                {
                                        log.trace("Appending custom element 
"+elementName
                                                + "\nwhose complete original 
content is: \n" + TextWriter.toString(source) 
                                                + "\nwhose original content is: 
\n" + TextWriter.toString(element)
                                                + "\nwhose imported content is: 
\n" + TextWriter.toString(custdoc));
                                }
                  this.custom.appendChild(custdoc);
              }
              else
              {
                  // ignore
                                if(log.isDebugEnabled())
                                        log.debug("ignoring unknown xml element 
"+elementName);
              }
          }
      }
  
      //
      // Support methods
      //
  
        /**
         * Return a string representing which type passed in.
         * It will be either doc, col, link, none.
         * @param type The type you want translated.
         * @return String representing this type
         */
      public static String getTypeString( short type )
      {
          switch( type )
          {
              case DOCUMENT:
                  return "doc";
              case COLLECTION:
                  return "col";
              case LINK:
                  return "link";
              default:
                  return "none";
          }
      }
  
        /**
         * Return a short representing the string given.
         * The string should be doc, col, or link.
         * @param str The string to parse
         * @return short The short for this string.
         */
      public static short parseTypeString( final String str )
      {
          if( str.equalsIgnoreCase("doc") )
              return DOCUMENT;
          if( str.equalsIgnoreCase("col") )
              return COLLECTION;
          if( str.equalsIgnoreCase("link") )
              return LINK;
  
          return UNKNOWN;
      }
  
      //
      // Modifiers
      //
  
        /**
         * Determine whether this obect has created or modified times set
         * @return boolean
         */
      public boolean hasContext()
      {
          if( created > 0 || modified > 0 )
              return true;
          else
              return false;
      }
  
        /**
         * Set the created and modified times
         * @param created the new creation time
         * @param modified the new modified time
         */
      public void setContext( long created, long modified )
      {
          if( created > 0 )
              this.created = created;
          if( modified > 0 )
              this.modified = modified;
      }
  
        /**
         * Set the type for this object.
         * If the type is already set to the value passed in, nothing is 
changed.
         * @param type the type for this object.
         */
      public void setType( short type )
      {
          if( this.type != type )
          {
              this.type = type;
              this.dirty = true;
          }
      }
  
        /**
         * Set the owner of this object
         * @param owner the owner to be ass
         */
      public void setOwner( String owner )
      {
          if( owner != this.owner ||
              null == owner ||
              null == this.owner ||
              !owner.equals(this.owner) )
          {
              this.owner = owner;
              this.dirty = true;
          }
      }
  
      public void setLinkTargetURI( String link )
      {
          if( link != this.link ||
              null == link ||
              null == this.link ||
              !link.equals(this.link) )
          {
              this.link = link;
              this.dirty = true;
          }
      }
  
      /**
       * Return a string representing this MetaData
         * It will look like:
         *  META[doc owner=OWNER created=CREATED modified=MODIFIED link=LINK
         *      attrs=ATTRS]
         *
         * @return String
       */
      public String toString()
      {
          StringBuffer buffer = new StringBuffer();
  
          buffer.append("META[");
          buffer.append(getTypeString(type));
          if( owner != null )
              buffer.append(" owner=" + owner);
          if( created > 0 )
              buffer.append(" created=" + (new Date(created)).toString());
          if( modified > 0 )
              buffer.append(" modified=" + (new Date(modified)).toString());
          if( link != null )
              buffer.append(" link=" + link);
          if( attrs != null )
              buffer.append(" attrs=" + attrs);
          buffer.append("]");
          return buffer.toString();
      }
  }
  
  
  
  
  1.1                  
xml-xindice/java/src/org/apache/xindice/core/meta/TimeRecord.java
  
  Index: TimeRecord.java
  ===================================================================
  package org.apache.xindice.core.meta;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xindice" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2001, The dbXML
   * Group, L.L.C., http://www.dbxmlgroup.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $Id: TimeRecord.java,v 1.1 2002/12/27 18:37:24 dviner Exp $
   */
  
  import java.util.Date;
  import java.util.Hashtable;
  /**
   * Encapsulates the modified/create times used in MetaData.
   * 
   */
  public class TimeRecord
  {
     long created = 0;
     long modified = 0;
  
  
     public TimeRecord( long created, long modified )
     {
        this.created = created;
        this.modified = modified;
     }
  
     /**
      * Returns the create time stored here.
        *
        * @return long
      */
     public long getCreatedTime()
     {
        return created;
     }
  
     /**
      * Returns the modified time stored here.
        *
        * @return long
      */
     public long getModifiedTime()
     {
        return modified;
     }
  
     /**
      * Sets the create time stored here.
        *
        * @param created The new create time
      */
     public void setCreatedTime(long created)
     {
           this.created = created;
     }
  
     /**
      * Sets the modified time stored here.
        *
        * @param mod The new modified time
      */
     public void setModifiedTime(long mod)
     {
           this.modified = mod;
     }
  
     /**
      * Return a string version of the times encapsulated. It should look like
        *   [cr=CREATE mod=MOD]
        *
        * @return The string representing the time
      */
     public String toString()
     {
        StringBuffer buffer = new StringBuffer();
        buffer.append("[");
        if( created > 0 )
           buffer.append("cr=" + (new Date(created)).toString());
        if( modified > 0 )
           buffer.append("mod=" + (new Date(modified)).toString());
        buffer.append("]");
        return buffer.toString();
     }
  }
  
  
  
  1.1                  
xml-xindice/java/src/org/apache/xindice/core/meta/package.html
  
  Index: package.html
  ===================================================================
  <html>
    <title>Xindice MetaData.</title>
    <body>
      <p>Defines and implements the Xindice MetaData storage and retrieval.</p>
   </body>
  </html>
  
  
  
  
  
  1.7       +4 -1      
xml-xindice/java/src/org/apache/xindice/server/rpc/RPCDefaultMessage.java
  
  Index: RPCDefaultMessage.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xindice/java/src/org/apache/xindice/server/rpc/RPCDefaultMessage.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- RPCDefaultMessage.java    23 Dec 2002 21:39:05 -0000      1.6
  +++ RPCDefaultMessage.java    27 Dec 2002 18:37:24 -0000      1.7
  @@ -82,6 +82,7 @@
      public static final String QUERY = "query";
      public static final String NAMESPACES = "namespaces";
      public static final String CONFIGURATION = "configuration";
  +   public static final String META = "meta";
   
      public static final String MISSING_COLLECTION_PARAM = "Required parameter 
'collection' not found.";
      public static final String MISSING_NAME_PARAM = "Required parameter 
'name' not found.";
  @@ -91,6 +92,8 @@
      public static final String MISSING_QUERY_PARAM = "Required parameter 
'query' not found.";
      public static final String MISSING_TIMESTAMP_PARAM = "For compressed 
results a timestamp must be provided.";
      public static final String MISSING_CONFIGURATION_PARAM = "You must either 
provide a document containing the configuration or specify the 'name' and 
'patter' parameters.";
  +   public static final String MISSING_META_CONFIGURATION = "Meta information 
requested but not enabled";
  +   public static final String MISSING_META_PARAM = "Required parameter 
'meta' not found";
   
      /**
       * Retrieves a Collection instance based on the path provided in name.
  
  
  
  1.1                  
xml-xindice/java/src/org/apache/xindice/server/rpc/messages/GetCollectionMeta.java
  
  Index: GetCollectionMeta.java
  ===================================================================
  package org.apache.xindice.server.rpc.messages;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xindice" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2001, The dbXML
   * Group, L.L.C., http://www.dbxmlgroup.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $Id: GetCollectionMeta.java,v 1.1 2002/12/27 18:37:24 dviner Exp $
   */
  
  import org.apache.xindice.core.Collection;
  import org.apache.xindice.core.Database;
  import org.apache.xindice.core.meta.MetaData;
  import org.apache.xindice.server.rpc.RPCDefaultMessage;
  import org.apache.xindice.xml.TextWriter;
  import org.apache.xindice.xml.dom.DocumentImpl;
  
  import org.w3c.dom.*;
  import org.apache.xerces.dom.DOMImplementationImpl;
  
  import java.util.Hashtable;
  
  /**
   * XML-RPC message to fetch the meta data associated with a document
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Dave Viner</a>
   */
  public class GetCollectionMeta extends RPCDefaultMessage {
  
     /**
      * Return the MetaData object for the requested collection.
        * 
        * This method expects the Hashtable to contain the name of the 
collection
        * in the RPCDefaultMessage.COLLECTION key.  It will return an XML
        * representation of the MetaData object associated with this collection.
        * The XML will be stored in the RPCDefaultMessage.RESULT key.
        * 
        * @param message the parameters passed to the xmlrpc method.
        * @return Hashtable containing the XML for the requested MetaData 
object.
      */
     public Hashtable execute(Hashtable message) throws Exception {
        Collection col = getCollection( (String) message.get(COLLECTION) );
        Hashtable result = new Hashtable();
        if( !col.isMetaEnabled() )
        {
           // meta information is not enabled !
           throw new Exception(MISSING_META_CONFIGURATION);
        }
        MetaData meta = col.getCollectionMeta();
        Document doc = new DocumentImpl();
        meta.streamToXML(doc, true);
  
        result.put( RESULT, TextWriter.toString( doc ) );
        return result;
     }
  }
  
  
  
  1.1                  
xml-xindice/java/src/org/apache/xindice/server/rpc/messages/GetDocumentMeta.java
  
  Index: GetDocumentMeta.java
  ===================================================================
  package org.apache.xindice.server.rpc.messages;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xindice" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2001, The dbXML
   * Group, L.L.C., http://www.dbxmlgroup.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $Id: GetDocumentMeta.java,v 1.1 2002/12/27 18:37:24 dviner Exp $
   */
  
  import org.apache.xindice.core.Collection;
  import org.apache.xindice.core.Database;
  import org.apache.xindice.core.meta.MetaData;
  import org.apache.xindice.server.rpc.RPCDefaultMessage;
  import org.apache.xindice.xml.TextWriter;
  import org.apache.xindice.xml.dom.DocumentImpl;
  
  import org.w3c.dom.*;
  
  import java.util.Hashtable;
  
  /**
   * XML-RPC message to fetch the meta data associated with a document
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Dave Viner</a>
   */
  public class GetDocumentMeta extends RPCDefaultMessage {
                
     /**
      * Return the MetaData object for the requested document.
        * 
        * This method expects the Hashtable to contain the name of the 
collection
        * in the RPCDefaultMessage.COLLECTION key, and the name of the document
        * in the RPCDefaultMessage.NAME key.
        * It will return an XML representation of the MetaData object 
associated 
        * with this document. The XML will be stored in the 
        * RPCDefaultMessage.RESULT key.
        * 
        * @param message the parameters passed to the xmlrpc method.
        * @return Hashtable containing the XML for the requested MetaData 
object.
      */                
     public Hashtable execute(Hashtable message) throws Exception {
        Collection col = getCollection( (String) message.get(COLLECTION) );
        Hashtable result = new Hashtable();
        if( !col.isMetaEnabled() )
        {
           // meta information is not enabled !
           throw new Exception(MISSING_META_CONFIGURATION);
        }
  
        if(!message.containsKey(NAME)) {
           throw new Exception(MISSING_NAME_PARAM);
        }
        String docname = (String)message.get(NAME);
        MetaData meta = col.getDocumentMeta(docname);
        Document doc = new DocumentImpl();
        meta.streamToXML(doc, true);
  
        result.put( RESULT, TextWriter.toString( doc ) );
        return result;
     }
  }
  
  
  
  1.1                  
xml-xindice/java/src/org/apache/xindice/server/rpc/messages/SetCollectionMeta.java
  
  Index: SetCollectionMeta.java
  ===================================================================
  package org.apache.xindice.server.rpc.messages;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xindice" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2001, The dbXML
   * Group, L.L.C., http://www.dbxmlgroup.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $Id: SetCollectionMeta.java,v 1.1 2002/12/27 18:37:24 dviner Exp $
   */
  
  
  import org.apache.xindice.core.Collection;
  import org.apache.xindice.core.Database;
  import org.apache.xindice.core.meta.MetaData;
  import org.apache.xindice.server.rpc.RPCDefaultMessage;
  import org.apache.xindice.xml.TextWriter;
  import org.apache.xindice.xml.dom.DocumentImpl;
  import org.apache.xindice.xml.dom.DOMParser;
  
  import org.w3c.dom.*;
  
  import java.util.Hashtable;
  
  /**
   * XML-RPC message to set the meta data associated with a collection
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Dave Viner</a>
   */
  public class SetCollectionMeta extends RPCDefaultMessage {
  
     /**
      * Set the MetaData object for the requested collection.
        * 
        * This method expects the Hashtable to contain the name of the 
collection
        * in the RPCDefaultMessage.COLLECTION key, and the XML for the new 
MetaData
        * object in the RPCDefaultMessage.META key.  It will return an XML
        * representation of the MetaData object associated with this collection.
        * The XML will be stored in the RPCDefaultMessage.RESULT key.
        * 
        * @param message the parameters passed to the xmlrpc method.
        * @return Hashtable containing XML of the newly created MetaData object.
      */
     public Hashtable execute(Hashtable message) throws Exception {
  
        if(!message.containsKey(COLLECTION)) {
           throw new Exception(MISSING_COLLECTION_PARAM);
         }
  
        if(!message.containsKey(META)) {
           throw new Exception(MISSING_META_PARAM);
        }
  
        String collection = (String)message.get(COLLECTION);
        Collection col = getCollection( collection );
        Hashtable result = new Hashtable();
        if( !col.isMetaEnabled() )
        {
           // meta information is not enabled !
           throw new Exception(MISSING_META_CONFIGURATION);
        }
        String metaxml = (String)message.get(META);
        MetaData meta = new MetaData();
  
        Document doc = DOMParser.toDocument( metaxml );
        meta.streamFromXML(doc.getDocumentElement());
        col.setCollectionMeta(meta);
  
          MetaData ret_meta = col.getCollectionMeta();
        Document ret_doc = new DocumentImpl();
        ret_meta.streamToXML(ret_doc, true);
          
        result.put( RESULT, TextWriter.toString( ret_doc ) );
        return result;
     }
  }
  
  
  
  1.1                  
xml-xindice/java/src/org/apache/xindice/server/rpc/messages/SetDocumentMeta.java
  
  Index: SetDocumentMeta.java
  ===================================================================
  package org.apache.xindice.server.rpc.messages;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xindice" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2001, The dbXML
   * Group, L.L.C., http://www.dbxmlgroup.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $Id: SetDocumentMeta.java,v 1.1 2002/12/27 18:37:24 dviner Exp $
   */
  
  
  import org.apache.xindice.core.Collection;
  import org.apache.xindice.core.Database;
  import org.apache.xindice.core.meta.MetaData;
  import org.apache.xindice.server.rpc.RPCDefaultMessage;
  import org.apache.xindice.xml.TextWriter;
  import org.apache.xindice.xml.dom.DocumentImpl;
  import org.apache.xindice.xml.dom.DOMParser;
  
  import org.w3c.dom.*;
  
  import java.util.Hashtable;
  
  /**
   * XML-RPC message to set the meta data associated with a document
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Dave Viner</a>
   */
  public class SetDocumentMeta extends RPCDefaultMessage {
  
  
     /**
      * Set the MetaData object for the requested document.
        * 
        * This method expects the Hashtable to contain the name of the 
collection
        * in the RPCDefaultMessage.COLLECTION key, the name of the document in
        * the RPCDefaultMessage.NAME key, and the XML for the new MetaData
        * object in the RPCDefaultMessage.META key.  It will return an XML
        * representation of the newly created MetaData object associated with 
this
        * document. The XML will be stored in the RPCDefaultMessage.RESULT key.
        * 
        * @param message the parameters passed to the xmlrpc method.
        * @return Hashtable containing XML of the newly created MetaData object.
      */
     public Hashtable execute(Hashtable message) throws Exception {
  
        if(!message.containsKey(COLLECTION)) {
           throw new Exception(MISSING_COLLECTION_PARAM);
        }
        if(!message.containsKey(NAME)) {
           throw new Exception(MISSING_NAME_PARAM);
        }
        if(!message.containsKey(META)) {
           throw new Exception(MISSING_META_PARAM);
        }
  
        String collection = (String)message.get(COLLECTION);
        String docname = (String)message.get(NAME);
        Collection col = getCollection( collection );
        Hashtable result = new Hashtable();
        if( !col.isMetaEnabled() )
        {
           // meta information is not enabled !
           throw new Exception(MISSING_META_CONFIGURATION);
        }
        String metaxml = (String)message.get(META);
        MetaData meta = new MetaData();
  
        Document doc = DOMParser.toDocument( metaxml );
  
        meta.streamFromXML(doc.getDocumentElement());
        col.setDocumentMeta(docname,meta);
  
          MetaData ret_meta = col.getDocumentMeta(docname);
        Document ret_doc = new DocumentImpl();
        ret_meta.streamToXML(ret_doc, true);
                  
        result.put( RESULT, TextWriter.toString( ret_doc ) );
        return result;
     }
  }
  
  
  

Reply via email to