// PropertyEditor.java
// $Id: PropertyEditor.java,v 1.9 1997/03/07 12:42:22 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.config ;

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

import w3c.util.*;
import w3c.jigsaw.resources.*;
import w3c.jigsaw.http.*;
import w3c.jigsaw.formedit.FormEditorFactory;
import w3c.jigsaw.html.*;
import w3c.www.http.*;

public class PropertyEditor extends HTTPResource {
    Dictionary propsets = null;
    Dictionary editors  = null;

    /**
     * Save edited our properties.
     * @param request The request that triggered the save.
     * @exception HTTPException If saving the properties failed.
     */

    protected Reply saveProperties (Request request)
	throws HTTPException
    {
	ObservableProperties props = getServer().getProperties();

	File propfile = new File((String)props.get(httpd.PROPS_P));
	// Did we guessed were the place to save the property file ?
	if ( propfile == null ) {
	    Reply         r = request.makeReply(HTTP.OK) ;
	    HtmlGenerator g = new HtmlGenerator ("Error while saving props") ;
	    g.append ("<h1>Error while saving properties</h1>") ;
	    g.append ("<p>Your current setting deson't provide a root "
		      + " directory for the server which is required "
		      + " in order to save properties."
		      + "<p>Set the <code>Root directory</code> or the "
		      + " <code>Config directory</code> property "
		      + " and try saving the properties again.") ;
	    r.setStream (g) ;
	    return r ;
	}
	// We have a suitable file handle, save properties.
	try {
	    FileOutputStream fout = new FileOutputStream(propfile);
	    getServer().getProperties().save (fout, "Jigsaw written") ;
	    fout.close() ;
	} catch (IOException ex) {
	    Reply         r = request.makeReply(HTTP.OK) ;
	    HtmlGenerator g = new HtmlGenerator ("Error while saving props");
	    g.append ("<h1>Error while saving properties</h1>") ;
	    g.append ("<p>The following error occured while saving properties"
		      + " to <code>" + propfile + "</code>:</p><pre>"
		      + ex.getMessage()
		      + "</pre>") ;
	    r.setStream (g) ;
	    return r ;
	}
	getServer().errlog ("properties " + propfile + " have been saved.");
	return null ;
    }

    /**
     * Lookup for a property set editor.
     * After checking that the set was registered, this method will either
     * reuse a cached editor, or create a fresh one for the given set, that
     * will be returned to complete lookup.
     * @param ls The current lookup state.
     * @param lr The lookup result under construction.
     * @exception HTTPException If some error occurs.
     * @return A boolean, <strong>true</strong> if lookup is done, 
     * <strong>false</strong> otherwise.
     */

    public boolean lookup(LookupState ls, LookupResult lr) 
	throws HTTPException
    {
	// No more components, return straight:
	if ( ! ls.hasMoreComponents() )
	    return super.lookup(ls, lr);
	// Is this one of our property sets ?
	String      setkey  = ls.getNextComponent();
	PropertySet propset = (PropertySet) propsets.get(setkey);
	if ( propset == null ) {
	    // This property set is not defined:
	    lr.setTarget(null);
	    return true;
	} else {
	    HTTPResource editor = (HTTPResource) editors.get(setkey);
	    if ( editor == null ) {
		editor = FormEditorFactory.getEditor(propset);
		Hashtable defs = new Hashtable(11);
		defs.put("parent", this);
		defs.put("url", getURLPath()+"/"+setkey);
		defs.put("target", propset);
		defs.put("context", getContext());
		editor.initialize(defs);
		editors.put(setkey, editor);
	    }
	    return editor.lookup(ls, lr);
	}
	// not reached !
    }

    /**
     * Register a given set of resources for editing.
     * @param set The PropertySet to provide an editor for.
     */

    public void registerPropertySet(PropertySet set) {
	propsets.put(set.getIdentifier(), set);
    }

    /**
     * Get the content of the property editor.
     * Display some links to the registered sets of properties.
     * @param request The incoming request.
     * @return A suitable reply.
     * @exception HTTPException If something breaks.
     */

    public Reply get(Request request) 
	throws HTTPException
    {
	String cmd = request.getQueryString();
	if ( cmd != null ) {
	    // Execute the command before proceeding:
	    if ( cmd.equalsIgnoreCase("save") ) {
		// Save current properties definition:
		Reply reply = saveProperties(request);
		if ( reply != null )
		    return reply;
	    } else if ( cmd.equalsIgnoreCase("restart") ) {
		// Restart the server:
		getServer().restart();
		Reply reply = request.makeReply(HTTP.OK);
		reply.setContent("Restarting "+getServer().getURL());
		return reply;
	    } else if ( cmd.equalsIgnoreCase("checkpoint") ) {
		String msg = null;
		try {
		    getServer().checkpoint();
		} catch (Exception ex) {
		    msg = "An error occured during checkpoint'ing.";
		}
		if ( msg != null ) {
		    Reply reply = request.makeReply(HTTP.OK);
		    reply.setContent(msg);
		    return reply;
		} else {
		    Reply reply = request.makeReply(HTTP.NO_CONTENT);
		    return reply;
		}
	    }
	}
	Enumeration   e = propsets.keys();
	HtmlGenerator g = new HtmlGenerator("Property sets");
	g.append("<ul>");
	while ( e.hasMoreElements() ) {
	    String      setkey  = (String) e.nextElement();
	    PropertySet propset = (PropertySet) propsets.get(setkey);
	    g.append("<li>");
	    g.append("<a href=\"", getURLPath()+"/"+setkey, "\">");
	    g.append(propset.getTitle());
	    g.append("</a></li>");
	}
	g.append("</ul><hr><p>Commands: ");
	g.append("<p><a href=\"", getURLPath(), "?save\">Save Properties</a>");
	g.append(" <a href=\"", getURLPath(), "?restart\">Restart Server</a>");
	g.append(" <a href=\"", getURLPath(), "?checkpoint\">Checkpoint</a>");
	Reply reply = createDefaultReply(request, HTTP.OK);
	reply.setStream(g);
	return reply;
    }

    /**
     * Initialize the property editor.
     * @param values The default attribute values for the editor.
     */

    public void initialize(Object values[]) {
	super.initialize(values);
	this.propsets = new ArrayDictionary(5, 5);
	this.editors  = new ArrayDictionary(5, 5);
	// Register ourself to the server, so that he know who we are:
	getServer().registerPropertyEditor(this);
    }

    public PropertyEditor() {
    }

}
