// ServletWrapperFrame.java
// $Id: ServletWrapperFrame.java,v 1.4 1998/02/17 13:43:52 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.servlet;

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

import javax.servlet.*;

import org.w3c.tools.resources.store.*;
import org.w3c.util.*;
import org.w3c.www.mime.*;
import org.w3c.www.http.*;
import org.w3c.jigsaw.http.*;
import org.w3c.jigsaw.frames.*;
import org.w3c.tools.resources.*;

import org.w3c.tools.resources.ProtocolException;
import org.w3c.tools.resources.NotAProtocolException;

/**
 * @author Alexandre Rafalovitch <alex@access.com.au>
 * @author Anselm Baird-Smith <abaird@w3.org>
 * @author Benoit Mahe <bmahe@w3.org>
 */

public class ServletWrapperFrame extends HTTPFrame {

  public static final 
  String STATE_EXTRA_PATH = "org.w3c.jigsaw.servlet.extraPath";

  protected ServletWrapper wrapper = null;

  public void registerResource(FramedResource resource) {
    super.registerOtherResource(resource);
    if (resource instanceof ServletWrapper)
      wrapper = (ServletWrapper) resource;
  }

  /**
   * Create a reply to answer to request on this file.
   * This method will create a suitable reply (matching the given request)
   * and will set all its default header values to the appropriate 
   * values. The reply will not have LastModified field setted.
   * @param request The request to make a reply for.
   * @return An instance of Reply, suited to answer this request.
   */

  public Reply createDefaultReply(Request request, int status) {
    Reply reply = super.createDefaultReply(request, status);
    reply.setLastModified( -1 );
    return reply;
  }

  /**
   * Dispatch the give request to our servlet.
   * <p>If the servlet cannot be inititalized, we just throw an error message
   * otherwise, we just delegate that request processing to the underlying 
   * servlet instance.
   * @param request The request to be processed.
   * @exception ProtocolException If the wrapped servlet is not initialized.
   */

  public ReplyInterface perform(RequestInterface req)
    throws ProtocolException, NotAProtocolException
  {
    ReplyInterface repi = performFrames(req);
    if (repi != null)
      return repi;

    if (! checkRequest(req))
      return null;

    Request request = (Request) req;

    if (wrapper == null) {
      Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
      reply.setContent("Servlet Wrapper Frame not configured properly : "+
		       "must be attached to a ServletWrapper.");
      throw new HTTPException(reply);
    }

    wrapper.checkServletClass();

    // Check that the servlet has been initialized properly:
    if ( ! wrapper.isInited() ) {
      Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
      reply.setContent("Servlet not configured properly");
      throw new HTTPException(reply);
    } 
    // Dispatch the request:
    Reply reply = createDefaultReply(request, HTTP.OK);
    reply.setContentType(MimeType.TEXT_HTML);
    try {
      wrapper.service(request, reply);
    } catch (Exception ex) {
      if ( wrapper.debug )
	ex.printStackTrace();
      reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
      reply.setContent("Servlet has thrown exception:" + ex.toString());
    }
    return reply;
  }
    
  /**
   * Jigsaw's lookup on servlets.
   * Once here, we have reached a leaf servlet (or at least the remaining
   * lookup is to be done at the servlet itself). We keep track of the
   * <em>path info</em> and mark that servlet as the target of request.
   * @param ls The lookup state.
   * @param lr The lookup result.
   * @exception ProtocolException If some error occurs.
   */

  protected boolean lookupOther(LookupState ls, LookupResult lr)
    throws ProtocolException
  {
    // Get the extra path information:
    String extraPath = ls.getRemainingPath(true);
    if ((extraPath == null) || extraPath.equals(""))
      extraPath = "/";
    // Keep this path info into the request, if possible:
    Request request = (Request) ls.getRequest();
    if ( request != null )
      request.setState(STATE_EXTRA_PATH, extraPath);
    lr.setTarget(resource.getResourceReference());
    return super.lookupOther(ls, lr);
  }

}








