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

    package org.w3c.jigsaw.filters;

    import java.io.*;

    import org.w3c.tools.resources.*;
    import org.w3c.www.http.*;
    import org.w3c.jigsaw.http.*;
    import org.w3c.jigsaw.resources.*;

    public class PutFilter extends ResourceFilter {
        /**
         * Attribute index - The companion PutList resource's URL.
         */
        protected static int ATTR_PUTLIST = -1;

        static {
    	Class     c = null;
    	Attribute a = null;

    	try {
    	    c = Class.forName("org.w3c.jigsaw.filters.PutFilter");
    	} catch (Exception ex) {
    	    ex.printStackTrace();
    	    System.exit(1);
    	}
    	// Register the PutList URL attribute:
    	a = new StringAttribute("put-list"
    				, null
    				, Attribute.EDITABLE|Attribute.MANDATORY);
    	ATTR_PUTLIST = AttributeRegistry.registerAttribute(c, a);
        }

        /**
         * Resolve the companion PutList URL attribute into a resource:
         */

        private ResourceReference list = null;
        protected synchronized ResourceReference resolvePutListResource() {
    	// Prepare for lookup:
    	ResourceReference rr_root = null;
    	rr_root = ((httpd) getServer()).getRootReference();
    	FramedResource root = null;
    	root = ((httpd) getServer()).getRoot();
    	String       u  = getPutListURL();
    	if ( u == null )
    	    return null;
    	// Do the lookup:
    	ResourceReference r_target = null;
    	try {
    	    LookupState  ls = new LookupState(u);
    	    LookupResult lr = new LookupResult(rr_root);
    	    root.lookup(ls, lr);
    	    r_target = lr.getTarget();
    	} catch (Exception ex) {
    	    r_target = null;
    	}
    	if (r_target != null) {
    	  try {
    	    Resource target = r_target.lock();
    	    if (! (target instanceof PutListResource) )
    	      r_target = null;
    	    else
    	      list = r_target;
    	  } catch (InvalidResourceException ex) {
    	    // continue
    	  } finally {
    	    r_target.unlock();
    	  }
    	}
    	return r_target;
        }

        /**
         * Get our companion PutListResource's URL.
         * @return The URL encoded as a String, or <strong>null</strong> if
         * undefined.
         */

        public String getPutListURL() {
    	return getString(ATTR_PUTLIST, null);
        }

        /**
         * Catch PUTLIST assignments.
         * @param idx The attribute being updated.
         * @param value It's new value.
         */

        public void setValue(int idx, Object value) {
    	super.setValue(idx, value);
    	if ( idx == ATTR_PUTLIST ) {
    	    synchronized(this) {
    		list = null;
    	    }
    	}
        }

        /**
         * Nothing done in the ingoingFilter.
         * We wait until the outgoigFilter.
         * @param request The request that is about to be processsed.
         */

        public ReplyInterface ingoingFilter(RequestInterface request) {
    	return null;
        }

        /**
         * Catch successfull PUTs, and keep track of them.
         * @param request The original request.
         * @param reply The original reply.
         * @return Always <strong>null</strong>.
         */

        public ReplyInterface outgoingFilter(RequestInterface req,
    					 ReplyInterface rep)
      {
            Request request = (Request) req;
    	Reply   reply   = (Reply) rep;
    	// Is this a successfull PUT request ?
    	if (request.getMethod().equals("PUT")
    	    && ((reply.getStatus()/100) == 2)) {
    	    // Cool, keep track of the modified file:
    	  ResourceReference rr   = null;
    	  PutListResource   l    = null;
    	  boolean           done = false;
    	  synchronized (this) {
    	    rr = resolvePutListResource();
    	    if (rr != null) {
    	      try {
    		l = (PutListResource) rr.lock();
    		if ( l != null ) {
    		  l.registerRequest(request);
    		  done = true;
    		}
    	      } catch (InvalidResourceException ex) {
    		done = false;
    	      } finally {
    		rr.unlock();
    	      }
    	    }
    	  }
    	  // Make sure we did something:
    	  if ( done ) {
    	    httpd s = (httpd) getServer();
    	    s.errlog(getClass().getName()+
    		     ": unable to resolve companion PutListResource at "+
    		     getPutListURL());
    	  }
    	}
    	return null;
        }

        public void initialize(Object values[]) {
    	super.initialize(values);
        }

    }