package org.codehaus.xfire.plexus.config;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.xfire.plexus.PlexusXFireComponent;
import org.codehaus.xfire.service.Service;

/**
 * Loads in XFire components from the XFire configuration file.
 * 
 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
 */
public class DefaultConfigurationService
    extends PlexusXFireComponent
    implements Initializable, Contextualizable, ConfigurationService
{ 
    private PlexusContainer container;
    
    private Hashtable configurators = new Hashtable();
    
	public void initialize() throws Exception
	{
        List confs = getServiceLocator().lookupList(Configurator.ROLE);
        
        for ( Iterator itr = confs.iterator(); itr.hasNext(); )
        {
            Configurator conf = (Configurator) itr.next();
            
            register( conf );
        }
        
        Reader reader = findConfigurationReader();
             
        if ( reader == null )
        {
           return;
        }             
       
        PlexusConfiguration configuration = new XmlPlexusConfiguration( Xpp3DomBuilder.build(reader) );
        createServices( configuration.getChild("services") );
	}
    
	private void createServices(PlexusConfiguration child) 
        throws Exception
    {
        PlexusConfiguration[] service = child.getChildren("service");
        
        for ( int i = 0; i < service.length; i++ )
        {
            createService( service[i] );
        }
    }
    
    private void createService(PlexusConfiguration c) 
        throws Exception
    {
        String type = c.getChild("type").getValue("simple");
        
        if ( type == null )
        {
            getLogger().error("Service " + c.getAttribute("name") 
                    + " has no type.");
            return;
        }
        
        getLogger().info("Creating service " + c.getChild("name").getValue() + " with type " + type);
        Configurator builder = 
            (Configurator) getServiceLocator().lookup( Configurator.ROLE, type );
        
        if ( builder == null )
        {
            getLogger().error("Creating service " + c.getChild("name").getValue() + " with type " + type
                    + ". Service " + c.getAttribute("name") + " not created.");
            return;
        }
        else
        {
            Service service = builder.createService(c);
        }
    }

	protected Reader findConfigurationReader() throws FileNotFoundException
	{
		String configFileName = System.getProperty("xfire.config");
        
        Reader reader = null;
        
        if ( configFileName == null )
        {
            getLogger().info("No configuration file specified.");
            configFileName = "xfire.xml";
        }

        File file = new File( configFileName );
        
        if ( file.exists() )
        {
            getLogger().info("Found configuration file " + file.getAbsolutePath());
        	reader = new FileReader( file );
        }
        else
        {
            getLogger().info("Could not find configuration file " + file.getAbsolutePath());
            getLogger().info("Looking in the classpath.");
        
            InputStream is = getClass().getResourceAsStream(configFileName);
            
            if ( is == null )
            {
                is = getClass().getResourceAsStream("META-INF/xfire/xfire.xml");
                
                if ( is == null )
                    return null;
            }
            
            reader = new InputStreamReader( is );
        }
        
		return reader;
	}

	/**
	 * @see org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable#contextualize(org.codehaus.plexus.context.Context)
	 */
	public void contextualize(Context context) throws Exception
	{
		container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
	}

    /**
     * @see org.codehaus.xfire.plexus.config.ConfigurationService#register(org.codehaus.xfire.plexus.config.ServiceConfigurator)
     */
    public void register( Configurator configurator )
    {
        configurators.put( configurator.getServiceType(),
                           configurator );
    }
}

@@ -1298,16 +1298,33 @@
 tion%0A%09%7B%0A
+%09    try%0A%09    %7B%0A%09
         
@@ -1387,16 +1387,17 @@
 .ROLE);%0A
+%09
         
@@ -1389,32 +1389,33 @@
 OLE);%0A%09        %0A
+%09
         for ( It
@@ -1462,16 +1462,17 @@
 xt(); )%0A
+%09
         
@@ -1465,32 +1465,33 @@
 ); )%0A%09        %7B%0A
+%09
             Conf
@@ -1529,24 +1529,25 @@
 itr.next();%0A
+%09
             
@@ -1539,32 +1539,33 @@
 ;%0A%09            %0A
+%09
             regi
@@ -1574,24 +1574,25 @@
 er( conf );%0A
+%09
         %7D%0A  
@@ -1581,32 +1581,33 @@
 f );%0A%09        %7D%0A
+%09
         %0A       
@@ -1591,32 +1591,33 @@
     %7D%0A%09        %0A
+%09
         Reader r
@@ -1647,24 +1647,25 @@
 onReader();%0A
+%09
             
@@ -1658,32 +1658,33 @@
 %0A%09             %0A
+%09
         if ( rea
@@ -1689,32 +1689,33 @@
 eader == null )%0A
+%09
         %7B%0A      
@@ -1700,32 +1700,33 @@
 ll )%0A%09        %7B%0A
+%09
            retur
@@ -1720,32 +1720,33 @@
         return;%0A
+%09
         %7D       
@@ -1752,24 +1752,25 @@
        %0A
+%09
        %0A
         
@@ -1753,32 +1753,33 @@
       %0A%09       %0A
+%09
         PlexusCo
@@ -1862,24 +1862,25 @@
 (reader) );%0A
+%09
         crea
@@ -1929,16 +1929,158 @@
 es%22) );%0A
+%09    %7D%0A%09    catch( Exception e )%0A%09    %7B%0A%09        getLogger().error(%22Could not start the configuration service.%22, e);%0A%09        throw e;%0A%09    %7D%0A
 %09%7D%0A    %0A

add some debugging