/**
 * Copyright (c) 2008-2012 EBM WebSourcing, 2012-2013 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library 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 Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see <http://www.gnu.org/licenses/>
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.se.jsr181;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.axis2.context.ConfigurationContext;
import org.ow2.petals.component.framework.AbstractComponent;
import org.ow2.petals.component.framework.api.configuration.ConfigurationExtensions;
import org.ow2.petals.component.framework.api.exception.PEtALSCDKException;
import org.ow2.petals.component.framework.jbidescriptor.generated.Jbi;
import org.ow2.petals.component.framework.jbidescriptor.generated.Provides;
import org.ow2.petals.component.framework.su.ServiceEngineServiceUnitManager;
import org.ow2.petals.component.framework.su.ServiceUnitDataHandler;
import org.ow2.petals.se.jsr181.axis.Axis2Deployer;
import org.ow2.petals.se.jsr181.model.JaxConfiguration;
import org.ow2.petals.se.jsr181.model.JaxConfigurationHandler;

/**
 * The Service-Unit manager for the JSR-181 SE.
 *
 * @author Christophe HAMERLING - EBM WebSourcing
 * @author Vincent Zurczak - EBM WebSourcing
 */
public class Jsr181SuManager extends ServiceEngineServiceUnitManager {

	/**
	 * The name of the parameter defining the JAX-WS class name.
	 */
	private final static String CONFIG_CLASS = "class";

	/**
	 * A map associating service-unit names and configuration handlers.
	 */
	private final Map<String,List<JaxConfigurationHandler>> suNameToJaxConfigHandler =
		new HashMap<String,List<JaxConfigurationHandler>> ();



	/**
	 * Constructor.
	 * @param component the service engine instance
	 */
	public Jsr181SuManager( AbstractComponent component ) {
		super( component );
	}


	/*
	 * (non-Javadoc)
	 * @see org.ow2.petals.component.framework.su.AbstractServiceUnitManager
	 * #doDeploy(java.lang.String, java.lang.String, org.ow2.petals.component.framework.jbidescriptor.generated.Jbi)
	 */
	@Override
	public void doDeploy( String serviceUnitName, String suRootPath, Jbi descriptor )
	throws PEtALSCDKException {

		/*
		 * In case where we would like the generate the WSDL at deployment time,
		 * we should also generate the jbi.xml file. Both are too coupled.
		 *
		 * Here is the code to generate the WSDL from the JAX-WS class.
		 *
		 * // Get a JaxConfigurationHandler
		 * ByteArrayOutputStream bos = new ByteArrayOutputStream();
		 * jaxConfigurationHandler.getAxisService().printWSDL( bos );
		 * result = XMLUtil.createDocumentFromString( bos.toString());
		 */

		final List<Provides> providesList = descriptor.getServices().getProvides();
		if( providesList.size() == 0 )
			throw new PEtALSCDKException( "This service-unit does not specify any service (no provides sections)." );

		List<JaxConfigurationHandler> handlers = new ArrayList<JaxConfigurationHandler>( providesList.size());
		for( Provides provides : providesList ) {

			ServiceUnitDataHandler suDataHandler = getSUDataHandlerForProvides( provides );
			if( suDataHandler == null )
				throw new PEtALSCDKException( "Error while processing the JBI descriptor in the component. The SU data handler was null." );

			ConfigurationExtensions extensions = suDataHandler.getConfigurationExtensions( provides );
			String className = extensions.get( CONFIG_CLASS );
			if( className != null )
				className = className.trim();

			if( className == null || className.length() == 0 )
				throw new PEtALSCDKException( "The class name cannot be null or empty." );

			try {
				// Create a JBI URL, not used but required...
				URL serviceURL = new URL( "http://localhost/services/" + provides.getServiceName().getLocalPart());
				String edptName = provides.getEndpointName();

				// Register handlers that will be used at runtime
				JaxConfiguration jaxConfiguration = new JaxConfiguration( serviceURL, suRootPath, className, edptName, serviceUnitName );
				JaxConfigurationHandler jaxConfigHandler = new JaxConfigurationHandler( jaxConfiguration );
				handlers.add( jaxConfigHandler );

				// Register the handler in the component
				((Jsr181Se) this.component).registerJaxConfigurationHandler( edptName, jaxConfigHandler );

			} catch( MalformedURLException e ) {
				throw new PEtALSCDKException( e );
			}
		}

		this.suNameToJaxConfigHandler.put( serviceUnitName, handlers );
	}


	/*
	 * (non-Javadoc)
	 * @see org.ow2.petals.component.framework.su.AbstractServiceUnitManager
	 * #doStart(java.lang.String)
	 */
	@Override
	protected void doStart( String serviceUnitName ) throws PEtALSCDKException {

		List<JaxConfigurationHandler> handlers = this.suNameToJaxConfigHandler.get( serviceUnitName );
		if( handlers == null || handlers.size() == 0 )
            throw new PEtALSCDKException("No service handler was registered for this service-unit.");

		Axis2Deployer deployer = ((Jsr181Se) this.component).getAxis2Deployer();
		for( JaxConfigurationHandler handler : handlers )
			handler.start( deployer, this.logger );
	}

    /*
     * (non-Javadoc)
     * 
     * @see org.ow2.petals.component.framework.su.AbstractServiceUnitManager
     * #doShutdown(java.lang.String)
     */
	@Override
    protected void doShutdown(String serviceUnitName) throws PEtALSCDKException {

		List<JaxConfigurationHandler> handlers = this.suNameToJaxConfigHandler.get( serviceUnitName );
		if( handlers == null || handlers.size() == 0 )
            throw new PEtALSCDKException("No service handler was registered for this service-unit.");

		ConfigurationContext axisContext = ((Jsr181Se) this.component).getAxisContext();
		for( JaxConfigurationHandler handler : handlers )
			handler.stop( axisContext );
	}

    /*
     * (non-Javadoc)
     * 
     * @see org.ow2.petals.component.framework.su.AbstractServiceUnitManager
     * #doUndeploy(java.lang.String)
     */
	@Override
    protected void doUndeploy(String serviceUnitName) throws PEtALSCDKException {

		List<JaxConfigurationHandler> handlers = this.suNameToJaxConfigHandler.remove( serviceUnitName );
		if( handlers != null ) {
			for( JaxConfigurationHandler handler : handlers )
				((Jsr181Se) this.component).removeJaxConfigurationHandler( handler.getEndpointName());
		}
	}
}
