/*
 * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
 * Distributed under the terms of either:
 * - the common development and distribution license (CDDL), v1.0; or
 * - the GNU Lesser General Public License, v2.1 or later
 */
package winstone;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import net.winstone.cluster.Cluster;

import net.winstone.WinstoneException;
import org.slf4j.LoggerFactory;

/**
 * Manages the references to individual hosts within the container. This object handles the mapping of ip addresses and hostnames to groups
 * of webapps, and init and shutdown of any hosts it manages.
 * 
 * @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
 * @version $Id: HostGroup.java,v 1.4 2006/03/24 17:24:21 rickknowles Exp $
 */
public class HostGroup {

    protected static org.slf4j.Logger logger = LoggerFactory.getLogger(HostGroup.class);
    private final static transient String DEFAULT_HOSTNAME = "default";
    /** map of host configuration */
    private final Map<String, HostConfiguration> hostConfigs;
    /** default host name if host mode is on */
    private String defaultHostName;

    /**
     * Build a new instance of HostGroup.
     * 
     * @param commonLibCL
     * @param commonLibCLPaths
     * @param args
     * @throws IOException
     */
    public HostGroup(final ClassLoader commonLibCL, final String jspClasspath, final Map<String, String> args) throws IOException {
        this(null, null, commonLibCL, jspClasspath, args);
    }

    public HostGroup(final Cluster cluster, final ObjectPool objectPool, final ClassLoader commonLibCL, final String jspClasspath, final Map<String, String> args) throws IOException {
        super();
        this.hostConfigs = new HashMap<String, HostConfiguration>();

        // Is this the single or multiple configuration ? Check args
        String hostDirName = (String) args.get("hostsDir");
        String webappsDirName = (String) args.get("webappsDir");

        // If host mode
        if (hostDirName == null) {
            addHostConfiguration(webappsDirName, DEFAULT_HOSTNAME, cluster, objectPool, commonLibCL, jspClasspath, args);
            this.defaultHostName = DEFAULT_HOSTNAME;
            logger.debug("Initialized in non-virtual-host mode");
        } // Otherwise multi-host mode
        else {
            initMultiHostDir(hostDirName, cluster, objectPool, commonLibCL, jspClasspath, args);
            logger.debug("Initialized in virtual host mode with {} hosts: hostnames - {}", this.hostConfigs.size() + "", this.hostConfigs.keySet() + "");
        }
    }

    public HostConfiguration getHostByName(String hostname) {
        HostConfiguration host = (HostConfiguration) this.hostConfigs.get(hostname);
        return host != null ? host : this.hostConfigs.get(this.defaultHostName);
    }

    public void destroy() {
        Set<String> hostnames = new HashSet<String>(this.hostConfigs.keySet());
        for (Iterator<String> i = hostnames.iterator(); i.hasNext();) {
            String hostname = i.next();
            HostConfiguration host = (HostConfiguration) this.hostConfigs.get(hostname);
            host.destroy();
            this.hostConfigs.remove(hostname);
        }
        this.hostConfigs.clear();
    }

    /**
     * Initialize an host.
     * 
     * @param webappsDirName
     * @param hostname
     * @param cluster
     * @param objectPool
     * @param commonLibCL
     * @param commonLibCLPaths
     * @param args
     * @throws IOException
     */
    protected final void addHostConfiguration(String webappsDirName, String hostname, Cluster cluster, ObjectPool objectPool,
            ClassLoader commonLibCL, String jspClasspath, Map<String, String> args) throws IOException {
        logger.debug("Deploying host found at {}", hostname);
        HostConfiguration config = new HostConfiguration(hostname, cluster, objectPool, commonLibCL, jspClasspath, args, webappsDirName);
        this.hostConfigs.put(hostname, config);
    }

    /**
     * Initialize a group host.
     * 
     * @param hostsDirName
     * @param cluster
     * @param objectPool
     * @param commonLibCL
     * @param commonLibCLPaths
     * @param args
     * @throws IOException
     */
    protected final void initMultiHostDir(String hostsDirName, Cluster cluster, ObjectPool objectPool, ClassLoader commonLibCL, String jspClasspath, Map<String, String> args) throws IOException {
        if (hostsDirName == null) {
            // never reach in this implementation
            hostsDirName = "hosts";
        }
        File hostsDir = new File(hostsDirName);
        if (!hostsDir.exists()) {
            throw new WinstoneException("Hosts dir " + hostsDirName + " not foundd");
        } else if (!hostsDir.isDirectory()) {
            throw new WinstoneException("Hosts dir " + hostsDirName + " is not a directory");
        } else {
            File children[] = hostsDir.listFiles();
            if ((children == null) || (children.length == 0)) {
                throw new WinstoneException("Hosts dir " + hostsDirName + " is empty (no child webapps found)");
            }
            for (int n = 0; n < children.length; n++) {
                String childName = children[n].getName();

                // Mount directories as host dirs
                if (children[n].isDirectory()) {
                    if (!this.hostConfigs.containsKey(childName)) {
                        addHostConfiguration(children[n].getCanonicalPath(), childName, cluster, objectPool, commonLibCL, jspClasspath, args);
                    }
                }
                // set default host name
                if ((defaultHostName == null) || childName.equals(DEFAULT_HOSTNAME)) {
                    this.defaultHostName = childName;
                }
            }
        }
    }

    /**
     * Finalize threads.
     */
    @Override
    protected void finalize() throws Throwable {
        try {
            destroy();
        } catch (Throwable e) {
        }
        super.finalize();
    }
}

@@ -2779,16 +2779,22 @@
 tByName(
+final 
 String h
@@ -2836,36 +2836,16 @@
 n host =
- (HostConfiguration)
  this.ho
@@ -2981,24 +2981,105 @@
 destroy() %7B%0A
+        if (this.hostConfigs != null) %7B%0A            // obtain a copy of name%0A    
         Set%3C
@@ -3146,16 +3146,20 @@
 Set());%0A
+    
         
@@ -3226,32 +3226,36 @@
 ) %7B%0A            
+    
 String hostname 
@@ -3282,58 +3282,12 @@
     
-HostConfiguration host = (HostConfiguration) this.
+    
 host
@@ -3311,26 +3311,8 @@
 ame)
-;%0A            host
 .des
@@ -3323,37 +3323,36 @@
 ();%0A            
-this.
+    
 hostConfigs.remo
@@ -3373,26 +3373,33 @@
         
-%7D%0A
+    %7D%0A   
         
 this.hos
@@ -3382,32 +3382,33 @@
    %7D%0A           
+ 
 this.hostConfigs
@@ -3413,24 +3413,34 @@
 gs.clear();%0A
+        %7D%0A
     %7D%0A%0A    /

check some issue