    // ExternalContainer.java
    // $Id: ExternalContainer.html,v 1.2 1999/10/27 22:10:34 ylafon Exp $
    // (c) COPYRIGHT MIT and INRIA, 1996.
    // Please first read the full copyright statement in file COPYRIGHT.html

    package org.w3c.tools.resources ;

    import java.util.*;
    import java.io.*;

    /**
     * A Container which manage an external store, outside the space.
     */
    public abstract class ExternalContainer extends ContainerResource {

      /**
       * Our transientFlag, is true that container must not be saved.
       */
      protected boolean transientFlag = false;

      /**
       * Our external repository.
       */
      protected File    repository    = null;

      public  ResourceReference createDefaultResource(String name) {
        throw new RuntimeException("not extensible");
      }

      /**
       * Mark this resource as having been modified.
       */
      public void markModified() {
        if (transientFlag) {
          setValue(ATTR_LAST_MODIFIED, new Long(System.currentTimeMillis()));
        } else {
          super.markModified();
        }
      }

      /**
       * acquire children and notify space if we will be saved.
       */
      protected synchronized void acquireChildren() {
        if (!acquired) {
          ResourceSpace space = getSpace();
          if (repository != null) {
    	space.acquireChildren( getChildrenSpaceEntry() ,
    			       repository,
    			       transientFlag );
          } else {
    	// if we have been saved one time yet.
    	space.acquireChildren( getChildrenSpaceEntry() );
          }
          acquired = true;
        }
      }

      /**
       * Delete this Resource instance , and remove it from its store.
       * This method will erase definitely this resource, for ever, by removing
       * it from its resource store (when doable).
       */

      public synchronized void delete()
        throws MultipleLockException
      {
        if (transientFlag) {
          // transient, so don't try to delete myself.
          ResourceSpace space = getSpace();
          if (space != null) {
    	acquireChildren();
    	// check for lock on children
    	Enumeration       e        = enumerateResourceIdentifiers();
    	ResourceReference rr       = null;
    	Resource          resource = null;
    	while (e.hasMoreElements()) {
    	  rr = lookup((String) e.nextElement());
    	  if (rr != null) {
    	    try {
    	      synchronized (rr) {
    		resource = rr.lock();
    		resource.delete();
    	      }
    	    } catch (InvalidResourceException ex) {
    	      // nothing, remove invalid resource.
    	    } finally {
    	      rr.unlock();
    	    }
    	  }
    	}
    	space.deleteChildren(getChildrenSpaceEntry());
          }
        } else {
          super.delete();
        }
      }

      /**
       * Get The repository for this external container.
       * Warning: called in the constructor!
       * @param context The container context.
       * @return A File instance
       */
      abstract public File getRepository(ResourceContext context);

      public void initialize(Object values[]) {
        super.initialize(values);
        if (repository == null)
          repository = getRepository(getContext());
      }

      /**
       * @param id The identifier.
       * @param context The default context.
       * @param transientFlag The transient flag.
       */

      public ExternalContainer (String id,
    			    ResourceContext context,
    			    boolean transientFlag)
      {
        Hashtable h = new Hashtable(3);
        h.put("identifier", id);
        h.put("context", context);
        initialize(h);
        this.acquired      = false;
        this.transientFlag = transientFlag;
        if (transientFlag)
          context.setResourceReference( new DummyResourceReference(this));
      }

      public ExternalContainer () {
        super();
        this.acquired      = false;
        this.transientFlag = false;
        this.repository    = null;
      }
    }