/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.servicemix.jbi.framework;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.jbi.JBIException;
import javax.jbi.component.Bootstrap;
import javax.jbi.component.Component;
import javax.jbi.management.DeploymentException;
import javax.jbi.management.InstallerMBean;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.ObjectName;

import org.apache.servicemix.jbi.container.JBIContainer;
import org.apache.xbean.classloader.DestroyableClassLoader;
import org.apache.xbean.classloader.JarFileClassLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * InstallerMBean defines standard installation and uninstallation controls for Binding Components and Service Engines.
 * Binding Components and Service Engines.
 * 
 * @version $Revision$
 */
public class InstallerMBeanImpl implements InstallerMBean {
    
    private static final transient Logger LOGGER = LoggerFactory.getLogger(InstallerMBeanImpl.class);
    
    private InstallationContextImpl context;
    private JBIContainer container;
    private ObjectName objectName;
    private ObjectName extensionMBeanName;
    private Bootstrap bootstrap;
    private boolean initialized;

    /**
     * Constructor for the InstallerMBean
     * 
     * @param container
     * @param ic
     * @throws DeploymentException
     */
    public InstallerMBeanImpl(JBIContainer container, 
                              InstallationContextImpl ic) throws DeploymentException {
        this.container = container;
        this.context = ic;
        bootstrap = createBootstrap();
        initBootstrap();
    }
    
    private void initBootstrap() throws DeploymentException {
        try {
            if (!initialized) {
                // Unregister a previously registered extension mbean,
                // in case the bootstrap has not done it
                try {
                    if (extensionMBeanName != null
                            && container.getMBeanServer() != null
                            && container.getMBeanServer().isRegistered(extensionMBeanName)) {
                        container.getMBeanServer().unregisterMBean(extensionMBeanName);
                    }
                } catch (InstanceNotFoundException e) {
                    // ignore
                } catch (MBeanRegistrationException e) {
                    // ignore
                }
                // Init bootstrap
                bootstrap.init(this.context);
                extensionMBeanName = bootstrap.getExtensionMBeanName();
                initialized = true;
            }
        } catch (JBIException e) {
            LOGGER.error("Could not initialize bootstrap", e);
            throw new DeploymentException(e);
        } 
    }
    
    protected void cleanUpBootstrap() throws DeploymentException {
        try {
            bootstrap.cleanUp();
        } catch (JBIException e) {
            LOGGER.error("Could not initialize bootstrap", e);
            throw new DeploymentException(e);
        } finally {
            initialized = false;
        }
    }
    
    private Bootstrap createBootstrap() throws DeploymentException {
        ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
        org.apache.servicemix.jbi.deployment.Component descriptor = context.getDescriptor();
        try {
            ClassLoader cl = buildClassLoader(
                                    context.getInstallRootAsDir(),
                                    descriptor.getBootstrapClassPath().getPathElements(),
                                    descriptor.isBootstrapClassLoaderDelegationParentFirst(),
                                    null);
            Thread.currentThread().setContextClassLoader(cl);
            Class bootstrapClass = cl.loadClass(descriptor.getBootstrapClassName());
            return (Bootstrap) bootstrapClass.newInstance();
        } catch (MalformedURLException e) {
            LOGGER.error("Could not create class loader", e);
            throw new DeploymentException(e);
        } catch (ClassNotFoundException e) {
            LOGGER.error("Class not found: {}", descriptor.getBootstrapClassName(), e);
            throw new DeploymentException(e);
        } catch (InstantiationException e) {
            LOGGER.error("Could not instantiate: {}", descriptor.getBootstrapClassName(), e);
            throw new DeploymentException(e);
        } catch (IllegalAccessException e) {
            LOGGER.error("Illegal access on: {}", descriptor.getBootstrapClassName(), e);
            throw new DeploymentException(e);
        } finally {
            Thread.currentThread().setContextClassLoader(oldCl);
        }
    }

    /**
     * Get the installation root directory path for this BC or SE.
     * 
     * @return the full installation path of this component.
     */
    public String getInstallRoot() {
        return context.getInstallRoot();
    }

    /**
     * Install a BC or SE.
     * 
     * @return JMX ObjectName representing the ComponentLifeCycle for the installed component, or null if the
     * installation did not complete.
     * @throws javax.jbi.JBIException if the installation fails.
     */
    public ObjectName install() throws JBIException {
        if (isInstalled()) {
            throw new DeploymentException("Component is already installed");
        }
        initBootstrap();
        bootstrap.onInstall();
        // TODO: the bootstrap may change the class path for the component,
        // so we need to persist it somehow
        ObjectName result = null;
        try {
            result = activateComponent();
            ComponentMBeanImpl lcc = container.getComponent(context.getComponentName());
            lcc.persistRunningState();
        } finally {
            cleanUpBootstrap();
            context.setInstall(false);
        }
        return result;
    }
    
    public ObjectName activateComponent() throws JBIException {
        ObjectName result = null;
        ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
        org.apache.servicemix.jbi.deployment.Component descriptor = context.getDescriptor();
        try {
            ClassLoader cl = buildClassLoader(
                                    context.getInstallRootAsDir(),
                                    (String[]) context.getClassPathElements().toArray(new String[0]),
                                    descriptor.isComponentClassLoaderDelegationParentFirst(),
                                    context.getSharedLibraries());
            Thread.currentThread().setContextClassLoader(cl);
            Class componentClass = cl.loadClass(descriptor.getComponentClassName());
            Component component = (Component) componentClass.newInstance();
            result = container.activateComponent(
                                    context.getInstallRootAsDir(), 
                                    component, 
                                    context.getComponentDescription(),
                                    (ComponentContextImpl) context.getContext(), 
                                    context.isBinding(), 
                                    context.isEngine(), 
                                    context.getSharedLibraries());
        } catch (MalformedURLException e) {
            LOGGER.error("Could not create class loader", e);
            throw new DeploymentException(e);
        } catch (NoClassDefFoundError e) {
            LOGGER.error("Class not found: {}", descriptor.getBootstrapClassName(), e);
            throw new DeploymentException(e);
        } catch (ClassNotFoundException e) {
            LOGGER.error("Class not found: {}", descriptor.getBootstrapClassName(), e);
            throw new DeploymentException(e);
        } catch (InstantiationException e) {
            LOGGER.error("Could not instantiate: {}", descriptor.getBootstrapClassName(), e);
            throw new DeploymentException(e);
        } catch (IllegalAccessException e) {
            LOGGER.error("Illegal access on: {}", descriptor.getBootstrapClassName(), e);
            throw new DeploymentException(e);
        } catch (JBIException e) {
            LOGGER.error("Could not initialize: {}", descriptor.getBootstrapClassName(), e);
            throw new DeploymentException(e);
        }  finally {
            Thread.currentThread().setContextClassLoader(oldCl);
        }
        return result;
    }

    /**
     * Determine whether or not the component is installed.
     * 
     * @return true if this component is currently installed, false if not.
     */
    public boolean isInstalled() {
        return !context.isInstall();
    }

    /**
     * Uninstall a BC or SE. This completely removes the component from the JBI system.
     * 
     * @throws javax.jbi.JBIException if the uninstallation fails.
     */
    public void uninstall() throws javax.jbi.JBIException {
        // TODO: check component status
        // the component must not be started and not have any SUs deployed
        if (!isInstalled()) {
            throw new DeploymentException("Component is not installed");
        }
        String componentName = context.getComponentName();
        try {
            container.deactivateComponent(componentName);
            //keep tck happy.
            bootstrap.init(this.context);
            bootstrap.getExtensionMBeanName();            
            bootstrap.onUninstall();
        } finally {
            cleanUpBootstrap();
            context.setInstall(true);
            // If it was found by a destroyable classloader destroy it
            // XXX Should we be holding the classloader as a member as always destroying it?
            if (bootstrap.getClass().getClassLoader() instanceof DestroyableClassLoader) {
                ((DestroyableClassLoader) bootstrap.getClass().getClassLoader()).destroy();
            }
            System.gc();
            container.getEnvironmentContext().removeComponentRootDirectory(componentName);
        }
    }

    /**
     * Get the installer configuration MBean name for this component.
     * 
     * @return the MBean object name of the Installer Configuration MBean.
     * @throws javax.jbi.JBIException if the component is not in the LOADED state or any error occurs during processing.
     */
    public ObjectName getInstallerConfigurationMBean() throws javax.jbi.JBIException {
        return extensionMBeanName;
    }
    /**
     * @return Returns the objectName.
     */
    public ObjectName getObjectName() {
        return objectName;
    }
    /**
     * @param objectName The objectName to set.
     */
    public void setObjectName(ObjectName objectName) {
        this.objectName = objectName;
    }

    /**
     * Buld a Custom ClassLoader
     * 
     * @param dir
     * @param classPathNames
     * @param parentFirst
     * @param list
     * @return ClassLoader
     * @throws MalformedURLException
     * @throws MalformedURLException
     * @throws DeploymentException
     */
    private ClassLoader buildClassLoader(
                    File dir,
                    String[] classPathNames, 
                    boolean parentFirst,
                    String[] list) throws MalformedURLException, DeploymentException {
        
        // Make the current ClassLoader the parent
        ClassLoader[] parents;
        
        // Create a new parent if there are some shared libraries
        if (list != null && list.length > 0) {
            parents = new ClassLoader[list.length];
            for (int i = 0; i < parents.length; i++) {
                org.apache.servicemix.jbi.framework.SharedLibrary sl = 
                    container.getRegistry().getSharedLibrary(list[i]);
                if (sl == null) {
                    throw new DeploymentException("Shared library " + list[i] + " is not installed");
                }
                parents[i] = sl.getClassLoader();
            }
        } else {
            parents = new ClassLoader[] {getClass().getClassLoader() };
        }
        
        List urls = new ArrayList();
        for (int i = 0; i < classPathNames.length; i++) {
            File file = new File(dir, classPathNames[i]);
            if (!file.exists()) {
                LOGGER.warn("Unable to add File {} to class path as it doesn't exist: {}",
                        file, file.getAbsolutePath());
            }
            urls.add(file.toURL());
        }

        ClassLoader cl = new JarFileClassLoader(
                        "Component ClassLoader",
                        (URL[]) urls.toArray(new URL[urls.size()]),
                        parents, 
                        !parentFirst,
                        new String[0],
                        new String[] {"java.", "javax." }); 
        LOGGER.debug("Component class loader: {}", cl);
        return cl;
    }

}
