// PutFilter.java
// $Id: PutFilter.java,v 1.6 1998/02/10 14:56:50 bmahe 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);
    }

}
