/*
 * 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.ode.jbi;

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

import javax.jbi.management.DeploymentException;
import javax.xml.namespace.QName;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Representation of a JBI service unit. A JBI service unit may actually consist
 * of multiple processes.
 */
class OdeServiceUnit {
    private static final Logger __log = LoggerFactory.getLogger(OdeServiceUnit.class);

    private static final Messages __msgs = Messages.getMessages(Messages.class);

    /** The ever-present context. */
    private OdeContext _ode;

    /** Our own directory managed by JBI */
    private File _serviceUnitRootPath;

    /** Our JBI indentifier. */
    private String _serviceUnitID;

    private Collection<QName> _registered = new ArrayList<QName>();

    private static final String LIB_DIR = "lib";

    /** Ctor. */
    OdeServiceUnit(OdeContext ode, String serviceUnitID, String serviceUnitRootPath) {
        _ode = ode;
        _serviceUnitID = serviceUnitID;
        _serviceUnitRootPath = new File(serviceUnitRootPath);
    }

    public void deploy() throws DeploymentException {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(getConfigurationClassLoader());
            // JBI ServiceUnits don't use autoincrement version,
            // because in ServiceMix redeploying component yields to redeploying dependent
            // ServiceUnits, and we don't want to create new processes versions
            // on such redeployments
            _ode._store.deploy(_serviceUnitRootPath, false);
        } catch (Exception ex) {
            String errmsg = __msgs.msgOdeProcessDeploymentFailed(_serviceUnitRootPath, _serviceUnitID);
            __log.error(errmsg, ex);
            throw new DeploymentException(errmsg, ex);
        } finally {
            Thread.currentThread().setContextClassLoader(cl);
        }
    }

    public void undeploy() throws Exception {
        try {
            Collection<QName> undeployed = _ode._store.undeploy(_serviceUnitRootPath);
            for (QName pqname : undeployed) {
                _ode._server.unregister(pqname);
            }

        } catch (Exception ex) {
            String errmsg = __msgs.msgOdeProcessUndeploymentFailed(null);
            __log.error(errmsg, ex);
            throw new DeploymentException(errmsg, ex);
        }
    }

    public void init() throws Exception {
        // TODO Auto-generated method stub

    }

    public void shutdown() throws Exception {
        // TODO Auto-generated method stub

    }

    public void start() throws Exception {
        List<QName> pids = _ode._store.listProcesses(_serviceUnitRootPath.getName());
        if (pids == null) {
            __log.error(_serviceUnitRootPath.getName() + " not found in process store. ");
            throw new IllegalStateException("Process store and JBI out of synch.");
        }

        Exception e = null;
        for (QName pid : pids) {
            try {
                _ode._server.register(_ode._store.getProcessConfiguration(pid));
                _registered.add(pid);
            } catch (Exception ex) {
                e = ex;
                __log.error("Unable to load " + pid, ex);
                break;
            }
        }
        if (_registered.size() != pids.size()) {
            for (QName pid : new ArrayList<QName>(_registered))
                try {
                    _ode._server.unregister(pid);
                    _registered.remove(pid);
                } catch (Exception ex) {
                    __log.error("Unable to unload " + pid, ex);
                }
        }

        if (e != null)
            throw e;
    }

    public void stop() throws Exception {
        for (QName pid : new ArrayList<QName>(_registered)) {
            try {
                _ode._server.unregister(pid);
                _registered.remove(pid);
            } catch (Exception ex) {
                __log.error("Unable to unload " + pid, ex);
            }
        }
    }

    public ClassLoader getConfigurationClassLoader() throws DeploymentException {
        return new URLClassLoader(getDefaultLocations(), getClass().getClassLoader());
    }

    protected URL[] getDefaultLocations() throws DeploymentException {
        try {
            File[] jars = new File(_serviceUnitRootPath, LIB_DIR).listFiles(new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    name = name.toLowerCase();
                    return name.endsWith(".jar") || name.endsWith(".zip");
                }
            });
            URL[] urls = new URL[jars != null ? jars.length + 1 : 1];
            urls[0] = _serviceUnitRootPath.toURI().toURL();
            if (jars != null) {
                for (int i = 0; i < jars.length; i++) {
                    urls[i + 1] = jars[i].toURI().toURL();
                }
            }
            if (__log.isDebugEnabled()) {
                for (URL u : urls) {
                    __log.debug("in classpath for "+_serviceUnitID+" using url: "+u);
                }
            }
            return urls;
        } catch (MalformedURLException e) {
            throw new DeploymentException("Unable to get default classpath locations", e);
        }
    }

}
