// RemoteServletWrapper.java
// $Id: RemoteServletWrapper.java,v 1.10 1998/08/14 11:11:27 bmahe Exp $  
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.servlet;

import javax.servlet.*;

import org.w3c.tools.resources.store.*;
import org.w3c.tools.resources.*;

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

public class RemoteServletWrapper extends ServletWrapper {
    private static final boolean debug = false;

    /**
     * Attribute index - The servlet content base.
     */
    protected static int ATTR_SERVLET_BASE = -1;

    static {
	Class     c = null;
	Attribute a = null;
	try {
	    c = Class.forName("org.w3c.jigsaw.servlet.RemoteServletWrapper");
	} catch (Exception ex) {
	    ex.printStackTrace();
	    System.exit(1);
	}
	// Register the servlet base URL:
	a = new StringAttribute("servlet-base"
				, null
				, Attribute.EDITABLE|Attribute.MANDATORY);
	ATTR_SERVLET_BASE = AttributeRegistry.registerAttribute(c, a);
    }
    /**
     * The ServletLoader instance for loading that servlet.
     */
    protected ServletLoader loader = null;

    /**
     * Check the servlet class, ans try to initialize it.
     * @exception ClassNotFoundException if servlet class can't be found.
     * @exception ServletException if servlet can't be initialized.
     */
    protected void checkServlet() 
	throws ClassNotFoundException, ServletException
    {
	if (! inited)
	    inited = launchServlet();
    }

    /** 
     * Get or create a suitable ServletLoader instance to load that servlet.
     * @return A ServletLoader instance.
     */

    protected synchronized ServletLoader getServletLoader() {
	if ( loader == null ) {
	    loader = new ServletLoader(this);
	}
	return loader;
    }

    /**
     * Get the remote servlet URL base.
     * @return The String encoded base URL for that servlet, or <strong>null
     * </strong> if undefined.
     */

    public String getServletBase() {
	return getString(ATTR_SERVLET_BASE, null);
    }
    
    public void setValue(int idx, Object value) {
	super.setValueOfSuperClass(idx, value);
	try {
	    if ((idx == ATTR_SERVLET_CLASS) && (value != null))
		inited = launchServlet();
	    if ((idx == ATTR_SERVLET_BASE) && (value != null))
		inited = launchServlet();
	} catch (Exception ex) {
	    String msg = ("unable to set servlet class \""+
			  getServletClass()+
			  "\" : "+
			  ex.getMessage());
	    getServer().errlog(msg);
	}
    }

    /**
     * Initialize the servlet.
     * @exception ClassNotFoundException if servlet class can't be found.
     * @exception ServletException if servlet can't be initialized.
     */
    protected boolean launchServlet() 
	throws ClassNotFoundException, ServletException
    {
	if ( debug )
	    System.out.println("Launching servlet: "+getServletClass());
	// Get and check the servlet class:
	if ( servlet != null )
	    destroyServlet();
	// Load appropriate servlet class:
	Class c = null;
	try {
	    // Load the servlet class through the loader:
	    c = getServletLoader().loadClass(getServletClass(), true);
	} catch (ClassFormatError er) {
	    String msg = ("class \""+getServletClass()+"\" loaded from "
			  + getServletBase() + ", invalid format.");
	    if ( debug )
		er.printStackTrace();
	    getServer().errlog(this, msg);
	} catch (ClassNotFoundException ex) {
	    String msg = ("class \""+getServletClass()+"\" loaded from "
			  + getServletBase() + ", not found.");
	    if ( debug )
		ex.printStackTrace();
	    getServer().errlog(this, msg);
	} 
	return (c != null) ? launchServlet(c) : false;
    }


}
