/**
 * Copyright (c) 2005-2012 EBM WebSourcing, 2012-2024 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.pojo.su;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

import org.ow2.petals.component.framework.api.configuration.SuConfigurationParameters;
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.se.AbstractServiceEngine;
import org.ow2.petals.component.framework.se.ServiceEngineServiceUnitManager;
import org.ow2.petals.component.framework.su.ServiceUnitDataHandler;
import org.ow2.petals.component.framework.util.ClassLoaderUtil;
import org.ow2.petals.se.pojo.Constants;
import org.ow2.petals.se.pojo.Pojo;
import org.ow2.petals.se.pojo.PojoComponent;

import com.ebmwebsourcing.easycommons.lang.StringHelper;

/**
 * @author Frederic Gardes - EBM WebSourcing
 */
public class SUManager extends ServiceEngineServiceUnitManager {

    public SUManager(final AbstractServiceEngine engine) {
        super(engine);
    }

    @Override
    public void doDeploy(final ServiceUnitDataHandler suDH) throws PEtALSCDKException {

        final Jbi descriptor = suDH.getDescriptor();

        final List<Provides> providesList = descriptor.getServices().getProvides();
        if (providesList == null || providesList.size() != 1) {
            throw new PEtALSCDKException("Only one Provides section supported");
        }
        final Provides provides = providesList.get(0);
        if (provides != null) {
            final SuConfigurationParameters extensions = suDH.getConfigurationExtensions(provides);
            final String className = extensions.get(Constants.CLASS_NAME);
            if (StringHelper.isNullOrEmpty(className)) {
                throw new PEtALSCDKException("Provides section must contains a POJO parameter '"
                        + Constants.CLASS_NAME + "'");
            }
        }
    }

    @Override
    public void doInit(final ServiceUnitDataHandler suDH) throws PEtALSCDKException {
        final Jbi jbiDescriptor = suDH.getDescriptor();
        final Provides provides = jbiDescriptor.getServices().getProvides().get(0);
        final SuConfigurationParameters extensions = suDH.getConfigurationExtensions(provides);
        final String className = extensions.get(Constants.CLASS_NAME);
        Pojo pojo;
        try {
            pojo = createPojo(className, suDH);
            pojo.init();
        } catch (Exception e) {
            if (e instanceof PEtALSCDKException) {
                throw (PEtALSCDKException)e;
            } else {
                throw new PEtALSCDKException(e);
            }
        }
        getComponent().getPojos().put(provides.getEndpointName(), pojo);

    }

    @Override
    public void doShutdown(final ServiceUnitDataHandler suDH) throws PEtALSCDKException {
        final Jbi jbiDescriptor = suDH.getDescriptor();
        final Provides provides = jbiDescriptor.getServices().getProvides().get(0);
        try {
            final Pojo pojo = getComponent().getPojos().remove(provides.getEndpointName());
            pojo.shutdown();
        } catch (Exception e) {
            if (e instanceof PEtALSCDKException) {
                throw (PEtALSCDKException)e;
            } else {
                throw new PEtALSCDKException(e);
            }
        }
    }

    @Override
    public void doStart(final ServiceUnitDataHandler suDH) throws PEtALSCDKException {
        final Jbi jbiDescriptor = suDH.getDescriptor();
        final Provides provides = jbiDescriptor.getServices().getProvides().get(0);
        try {
            getComponent().getPojos().get(provides.getEndpointName()).start();
        } catch (Exception e) {
            if (e instanceof PEtALSCDKException) {
                throw (PEtALSCDKException)e;
            } else {
                throw new PEtALSCDKException(e);
            }
        }
    }

    @Override
    public void doStop(final ServiceUnitDataHandler suDH) throws PEtALSCDKException {
        final Jbi jbiDescriptor = suDH.getDescriptor();
        final Provides provides = jbiDescriptor.getServices().getProvides().get(0);
        try {
            getComponent().getPojos().get(provides.getEndpointName()).stop();
        } catch (Exception e) {
            if (e instanceof PEtALSCDKException) {
                throw (PEtALSCDKException)e;
            } else {
                throw new PEtALSCDKException(e);
            }
        }
    }

    @Override
    public void doUndeploy(final ServiceUnitDataHandler suDH) throws PEtALSCDKException {
        getComponent().getPojos().remove(suDH.getName());
    }

    /**
     * Create the POJO.
     * 
     * @param className
     * @param suDatahandler
     * @return
     * @throws Exception
     */
    private Pojo createPojo(String className, ServiceUnitDataHandler suDatahandler)
            throws Exception {

        // create a classloader from the SU path
        final URL[] arrayOfSuJar = ClassLoaderUtil.getUrls(suDatahandler.getInstallRoot());
        final URLClassLoader classLoader = new URLClassLoader(arrayOfSuJar, this.getClass()
                .getClassLoader());

        // load the pojo class from the classloader
        Class<?> clazz = classLoader.loadClass(className);

        // create the pojo
        return new Pojo(clazz.newInstance(), classLoader, getComponent().getContext(), getComponent().getChannel(),
                logger);
    }

    @Override
    protected PojoComponent getComponent() {
        return (PojoComponent) super.getComponent();
    }

}
