/**
 *#########################################################################
 *
 * A component of the Gatherer application, part of the Greenstone digital
 * library suite from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * <BR><BR>
 *
 * Author: John Thompson, Greenstone Digital Library, University of Waikato
 *
 * <BR><BR>
 *
 * Copyright (C) 1999 New Zealand Digital Library Project
 *
 * <BR><BR>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * <BR><BR>
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * <BR><BR>
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *########################################################################
 */
package org.greenstone.gatherer.greenstone3;

import java.awt.*;
import java.io.*;
import java.lang.ref.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.*;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.DebugStream;
import org.greenstone.gatherer.util.ArrayTools;
import org.greenstone.gatherer.util.StaticStrings;
import org.greenstone.gatherer.util.Utility;
import org.greenstone.gatherer.util.XMLTools;
import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
import org.w3c.dom.*;

/** This class stores the mapping between sites and servlets available for them. The info is read in from the web.xml file.
 */
public class ServletConfiguration {
    
    static public String ADD_COMMAND        = "?a=s&sa=a&st=collection&sn=";
    static public String DEACTIVATE_COMMAND = "?a=s&sa=d&st=collection&sn=";
    private String gsdl3_web_path = "";
    private String gsdl3_writableweb_path = "";
    private ArrayList sites = null;
    private HashMap site_to_servlet_list_map = null;
    private HashMap servlet_to_site_map = null;

  public ServletConfiguration(String gsdl3_web_path, String gsdl3_writableweb_path) {
	
	this.gsdl3_web_path = gsdl3_web_path;
	this.gsdl3_writableweb_path = gsdl3_writableweb_path;

	if (Gatherer.isGsdlRemote){
	    if (Gatherer.remoteGreenstoneServer.downloadWebXMLFile().equals("")) {
		System.err.println("ServletConfiguration Error: Could not download web.xml.");
		System.exit(0);
	    }
	}

	loadSites();
    }

    public void loadSites() {
	//String web_xml_path = gsdl3_path + File.separator + "web" + File.separator + "WEB-INF"+ File.separator + "web.xml";
	File web_xml;
	File servlets_xml;
	if (Gatherer.isGsdlRemote){
	    web_xml = new File(gsdl3_writableweb_path + "web.xml");
	    servlets_xml = new File(gsdl3_writableweb_path + "servlets.xml");
	}else{
	    web_xml = new File(gsdl3_writableweb_path + "WEB-INF"+ File.separator + "web.xml");
	    servlets_xml = new File(gsdl3_writableweb_path + "WEB-INF"+ File.separator + "web.xml");
	}
	if (!web_xml.exists()) {
	    DebugStream.println("Error: no web.xml found at "+web_xml.toString());
	    return;
	}	
	if (!servlets_xml.exists()) {
	    DebugStream.println("Error: no servlets.xml found at "+servlets_xml.toString());
	    return;
	}
	
	this.sites = new ArrayList();
	if (Gatherer.isGsdlRemote){
	    String sites_on_server = Gatherer.remoteGreenstoneServer.getSiteNames();
	    if (sites_on_server.equals("")) {
		// !! Something went wrong : could not get names of the sites
		System.err.println("ServletConfiguration Error: Could not get names of the sites.");
		System.exit(0);
	    }
	   
	    String[] sites_arr=sites_on_server.split("-----");
	    for (int i=0; i<sites_arr.length; i++){
		if (!(sites_arr[i].trim().equals(""))){
		    this.sites.add(sites_arr[i].trim());
		}
	    }
	}else{
	    // find the sites
	    File start = new File(Utility.getSitesDir(gsdl3_web_path));
	    File possible_sites[] = start.listFiles();
	    ArrayTools.sort(possible_sites);
	    for (int i=0; possible_sites != null && i < possible_sites.length; i++) {
              if ( possible_sites[i].getName().equals("modelsite")) continue;
              File site_config = new File(possible_sites[i], "siteConfig.xml");
              if (site_config.exists()) {
                this.sites.add(possible_sites[i].getName());
              }
	    }
	}

	this.site_to_servlet_list_map = new HashMap();
	this.servlet_to_site_map = new HashMap();
        System.err.println("parsing xml file "+web_xml.getAbsolutePath());
	Document web_config = XMLTools.parseXMLFile(web_xml.getAbsolutePath(), false);
       
	NodeList servlet_mappings = web_config.getElementsByTagName("servlet-mapping");
	// make a little map class
	HashMap url_mappings = new HashMap();
	for (int i=0; i<servlet_mappings.getLength(); i++) {
	    Element map = (Element)servlet_mappings.item(i);
	    String name = XMLTools.getValue(XMLTools.getNodeFromNamed(map, "servlet-name"));
	    String pattern = XMLTools.getValue(XMLTools.getNodeFromNamed(map, "url-pattern"));
 	    url_mappings.put(name, pattern);

	}

	NodeList servlets = web_config.getElementsByTagName("servlet");
	for (int i=0; i<servlets.getLength(); i++) {
	    Element servlet = (Element)servlets.item(i);
            String servlet_class = XMLTools.getValue(XMLTools.getNodeFromNamed(servlet, "servlet-class"));
            if (!servlet_class.equals("org.greenstone.gsdl3.LibraryServlet")) {
              // only want library servlets
              continue;
            }
	    String name = XMLTools.getValue(XMLTools.getNodeFromNamed(servlet, "servlet-name"));
	    String description = XMLTools.getValue(XMLTools.getNodeFromNamed(servlet, "description"));
            String site = getServletSite(servlet);
	    if (site != null) {
		ArrayList this_site = (ArrayList)site_to_servlet_list_map.get(site);
		if (this_site == null) {
		    this_site = new ArrayList();
		}
		String url = (String)url_mappings.get(name);
                if (url != null) { // if its null, there was no mapping for the servlet
                  if(url.endsWith("/*")) { // truncate trailing /*, e.g. /library/* becomes /library
		    url = url.substring(0, url.length()-2);
                  }
                  this_site.add(url);
                  this.site_to_servlet_list_map.put(site, this_site);
                  this.servlet_to_site_map.put(url, site);
                }
            }
	    
	}

	web_config = null;
	url_mappings = null;
    }

    public ArrayList reloadAndGetSites() {
	System.err.println("### reloadAndGetSites called");
	loadSites();
	return getSites();
    }
    
    public ArrayList getSites() {
	return this.sites;
    }

    public ArrayList getServletsForSite(String site) {
	return (ArrayList)this.site_to_servlet_list_map.get(site);
    }
    public String getServletPath(String site) {
	
	// for now, get the first one
	ArrayList servlets = (ArrayList)this.site_to_servlet_list_map.get(site);
	if(servlets == null) {
	    return null;
	}
	return (String)servlets.get(0);
    }

    public String getSiteForServlet(String servlet) {
	return (String)this.servlet_to_site_map.get(servlet);
    }

    private String getServletSite(Element servlet) {

	NodeList params = servlet.getElementsByTagName("init-param");
	if ( params == null || params.getLength() == 0) {
	    return null;
	}
	String site = null;
	for (int i=0; i<params.getLength()&& site == null; i++) {
	    String p_name = XMLTools.getValue(XMLTools.getNodeFromNamed(params.item(i), "param-name"));
	    if (p_name.equals("site_name")) {
		site = XMLTools.getValue(XMLTools.getNodeFromNamed(params.item(i), "param-value"));
	    }
	}
	return site;
    }
}
