/*
 * Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.enterprise.glassfish.bootstrap.osgi;

import com.sun.enterprise.glassfish.bootstrap.MainHelper;
import com.sun.enterprise.glassfish.bootstrap.Constants;
import org.glassfish.embeddable.BootstrapProperties;
import org.glassfish.embeddable.GlassFishException;
import org.glassfish.embeddable.GlassFishRuntime;
import org.glassfish.embeddable.spi.RuntimeBuilder;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.launch.Framework;

import java.io.*;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import static com.sun.enterprise.glassfish.bootstrap.Constants.HK2_CACHE_DIR;
import static com.sun.enterprise.glassfish.bootstrap.Constants.INHABITANTS_CACHE;
import static com.sun.enterprise.glassfish.bootstrap.osgi.Constants.*;
import static com.sun.enterprise.glassfish.bootstrap.osgi.Constants.PROVISIONING_OPTIONS_PREFIX;
import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN;
import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;

import com.sun.enterprise.glassfish.bootstrap.LogFacade;

/**
 * This RuntimeBuilder can only handle GlassFish_Platform of following types:
 * <p/>
 * {@link Constants.Platform#Felix},
 * {@link Constants.Platform#Equinox},
 * and {@link Constants.Platform#Knopflerfish}.
 * <p/>
 * <p/>It can't handle GenericOSGi platform,
 * because it reads framework configuration from a framework specific file when it calls
 * {@link MainHelper#buildStartupContext(java.util.Properties)}.
 * <p/>
 * This class is responsible for
 * a) setting up OSGi framework,
 * b) installing glassfish bundles,
 * c) starting a configured list of bundles
 * d) obtaining a reference to GlassFishRuntime OSGi service.
 * <p/>
 * Steps #b & #c are handled via {@link BundleProvisioner}.
 * We specify our provisioning bundle details in the properties object that's used to boostrap
 * the system. BundleProvisioner installs and starts such bundles,
 * <p/>
 * If caller does not pass in a properly populated properties object, we assume that we are
 * running against an existing installation of glassfish and set appropriate default values.
 * <p/>
 * <p/>
 * This class is registered as a provider of RuntimeBuilder using META-INF/services file.
 *
 * @author Sanjeeb.Sahoo@Sun.COM
 */
public final class OSGiGlassFishRuntimeBuilder implements RuntimeBuilder {

    /*
     * Not a thread safe class.
     */

    private Framework framework;

    private final Logger logger = LogFacade.BOOTSTRAP_LOGGER;

    private Properties oldProvisioningOptions;
    private Properties newProvisioningOptions;

    // These two should be a part of an external interface of HK2, but they are not, so we have to duplicate them here.
    private OSGiFrameworkLauncher fwLauncher;

    /**
     * Default constructor needed for meta-inf/service lookup to work
     */
    public OSGiGlassFishRuntimeBuilder() {}

    @Override
    public GlassFishRuntime build(BootstrapProperties bsProps) throws GlassFishException {
        try {
            MainHelper.buildStartupContext(bsProps.getProperties());
            Properties properties = bsProps.getProperties();

            // Set the builder name so that when we check for nonEmbedded() inside GlassFishMainActivator,
            // we can identify the environment.
            properties.setProperty(Constants.BUILDER_NAME_PROPERTY, getClass().getName());
            // Step 0: Locate and launch a framework
            long t0 = System.currentTimeMillis();
            fwLauncher = new OSGiFrameworkLauncher(properties);
            framework = fwLauncher.launchOSGiFrameWork();
            long t1 = System.currentTimeMillis();
            logger.logp(Level.FINE, "OSGiGlassFishRuntimeBuilder", "build", "Launched {0}", new Object[]{framework});

            // Step 1: install/update/delete bundles
            if (newFramework()) {
                storeProvisioningOptions(properties);
            } else {
                reconfigure(properties); // this will reconfigure if any provisioning options have changed.
            }
            BundleProvisioner bundleProvisioner = BundleProvisioner.createBundleProvisioner(
                    framework.getBundleContext(), properties);
            List<Long> bundleIds = bundleProvisioner.installBundles();

            if (bundleProvisioner.hasAnyThingChanged()) {
                bundleProvisioner.refresh();
                deleteHK2Cache(properties); // clean hk2 cache so that updated bundle details will go in there.
                // Save the bundle ids for use during restart.
                storeBundleIds(bundleIds.toArray(new Long[bundleIds.size()]));
            }
            if (bundleProvisioner.isSystemBundleUpdationRequired()) {
                logger.log(Level.INFO, LogFacade.UPDATING_SYSTEM_BUNDLE);
                framework.update();
                framework.waitForStop(0);
                framework.init();
                bundleProvisioner.setBundleContext(framework.getBundleContext());
            }

            // Step 2: Start bundles
            bundleProvisioner.startBundles();
            long t2 = System.currentTimeMillis();

            // Step 3: Start the framework, so bundles will get activated as per their start levels
            framework.start();
            long t3 = System.currentTimeMillis();
            printStats(bundleProvisioner, t0, t1, t2, t3);

            // Step 4: Obtain reference to GlassFishRuntime and return the same
            return getGlassFishRuntime();
        } catch (Exception e) {
            throw new GlassFishException(e);
        }
    }

    @Override
    public boolean handles(BootstrapProperties bsProps) {
        // See GLASSFISH-16743 for the reason behind additional check
        final String builderName = bsProps.getProperty(Constants.BUILDER_NAME_PROPERTY);
        if (builderName != null && !builderName.equals(getClass().getName())) {
            return false;
        }
        /*
         * This builder can't handle GOSGi platform, because we read framework configuration from a framework
         * specific file in MainHelper.buildStartupContext(properties);
         */
        String platformStr = bsProps.getProperty(Constants.PLATFORM_PROPERTY_KEY);
        if (platformStr != null && platformStr.trim().length() != 0) {
            try {
                Constants.Platform platform = Constants.Platform.valueOf(platformStr);
                switch (platform) {
                    case Felix:
                    case Equinox:
                    case Knopflerfish:
                        return true;
                }
            } catch (IllegalArgumentException ex) {
                // might be a plugged-in custom platform.
            }
        }
        return false;
    }

    private GlassFishRuntime getGlassFishRuntime() throws GlassFishException {
        final ServiceReference reference =
                framework.getBundleContext().getServiceReference(GlassFishRuntime.class.getName());
        if (reference != null) {
            GlassFishRuntime embeddedGfr = (GlassFishRuntime) framework.getBundleContext().getService(reference);
            return new OSGiGlassFishRuntime(embeddedGfr, framework);
        }
        throw new GlassFishException("No GlassFishRuntime available");
    }

    private void deleteHK2Cache(Properties properties) throws GlassFishException {
        // This is a HACK - thanks to some weired optimization trick
        // done for GlassFish. HK2 maintains a cache of inhabitants and
        // that needs  to be recreated when there is a change in modules dir.
        final String cacheDir = properties.getProperty(HK2_CACHE_DIR);
        if (cacheDir != null) {
            File inhabitantsCache = new File(cacheDir, INHABITANTS_CACHE);
            if (inhabitantsCache.exists()) {
                if (!inhabitantsCache.delete()) {
                    throw new GlassFishException("cannot delete cache:" +
                            inhabitantsCache.getAbsolutePath());
                }
            }
        }
    }

    private void printStats(BundleProvisioner bundleProvisioner, long t0, long t1, long t2, long t3) {
        logger.logp(Level.FINE, "OSGiGlassFishRuntimeBuilder", "build",
                "installed = {0}, updated = {1}, uninstalled = {2}",
                new Object[]{bundleProvisioner.getNoOfInstalledBundles(),
                        bundleProvisioner.getNoOfUpdatedBundles(),
                        bundleProvisioner.getNoOfUninstalledBundles()});
        logger.logp(Level.FINE, "OSGiGlassFishRuntimeBuilder", "build",
                "Total time taken (in ms) to initialize framework = {0}, " +
                        "to install/update/delete/start bundles = {1}, " +
                        "to start framework= {2}",
                new Object[]{t1 - t0, t2 - t1, t3 - t2});
    }

    private boolean newFramework() {
        BundleContext context = framework.getBundleContext();
        return context == null || context.getBundles().length == 1;
    }

    /**
     * This method helps in situations where glassfish installation directory has been moved or
     * certain initial provisoning options have changed, etc. If such thing has happened, it uninstalls
     * all the bundles that were installed from GlassFish installation location.
     */
    private void reconfigure(Properties properties) throws Exception {
        if (hasBeenReconfigured(properties)) {
            logger.log(Level.INFO, LogFacade.PROVISIONING_OPTIONS_CHANGED);
            framework.stop();
            framework.waitForStop(0);
            properties.setProperty(FRAMEWORK_STORAGE_CLEAN,
                    FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
            fwLauncher = new OSGiFrameworkLauncher(properties);
            framework = fwLauncher.launchOSGiFrameWork();
            logger.logp(Level.FINE, "OSGiGlassFishRuntimeBuilder", "reconfigure", "Launched {0}",
                    new Object[]{framework});
            storeProvisioningOptions(properties);
        }
    }

    private boolean hasBeenReconfigured(Properties properties) {
        logger.logp(Level.FINE, "OSGiGlassFishRuntimeBuilder", "hasBeenReconfigured", "oldProvisioningOptions = {0}",
                new Object[]{getOldProvisioningOptions()});
        logger.logp(Level.FINE, "OSGiGlassFishRuntimeBuilder", "hasBeenReconfigured", "newProvisioningOptions = {0}",
                new Object[]{getNewProvisioningOptions(properties)});
        return !getNewProvisioningOptions(properties).equals(getOldProvisioningOptions());
    }

    /**
     * @return properties used by BundleProvisioner
     */
    private Properties getNewProvisioningOptions(Properties properties) {
        if (newProvisioningOptions == null) {
            Properties props = new Properties();
            for (String key : properties.stringPropertyNames()) {
                if (key.startsWith(PROVISIONING_OPTIONS_PREFIX)) {
                    props.setProperty(key, properties.getProperty(key));
                }
            }
            newProvisioningOptions = props;
        }
        return newProvisioningOptions;
    }

    private void storeBundleIds(Long[] bundleIds) {
        ObjectOutputStream os = null;
        try {
            File f = framework.getBundleContext().getDataFile(BUNDLEIDS_FILENAME);
            // GLASSFISH-19623: f can be null
            if (f == null) {
                logger.log(Level.WARNING, LogFacade.CANT_STORE_BUNDLEIDS);
                return;
            }
            os = new ObjectOutputStream(new FileOutputStream(f));
            os.writeObject(bundleIds);
            os.flush();
            logger.logp(Level.FINE, "OSGiGlassFishRuntimeBuilder", "storeBundleIds", "Stored bundle ids in {0}",
                    new Object[]{f.getAbsolutePath()});
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    // ignored
                }
            }
        }
    }

    private void storeProvisioningOptions(Properties properties) {
        BundleContext context = framework.getBundleContext();
        if (context == null) {
            throw new IllegalStateException("No bundle context available!");
        }
        File f = context.getDataFile(PROVISIONING_OPTIONS_FILENAME);
        // GLASSFISH-19623: f can be null
        if (f == null) {
            logger.log(Level.WARNING, LogFacade.CANT_STORE_PROVISIONING_OPTIONS);
            return;
        }
        try (FileOutputStream os = new FileOutputStream(f)) {
            getNewProvisioningOptions(properties).store(os, "");
            os.flush();
            logger.logp(Level.CONFIG, "OSGiGlassFishRuntimeBuilder", "storeProvisioningOptions",
                "Stored provisioning options in {0}", new Object[] {f.getAbsolutePath()});
        } catch (IOException e) {
            logger.log(Level.WARNING, "Storing provisioning options failed.", e);
        }
    }

    private Properties getOldProvisioningOptions() {
        if (oldProvisioningOptions == null) {
            Properties options = new Properties();
            try {
                File f = framework.getBundleContext().getDataFile(PROVISIONING_OPTIONS_FILENAME);
                if (f != null && f.exists()) {
                    options.load(new FileInputStream(f));
                    logger.logp(Level.FINE, "OSGiGlassFishRuntimeBuilder", "getOldProvisioningOptions",
                            "Read provisioning options from {0}", new Object[]{f.getAbsolutePath()});
                    oldProvisioningOptions = options;
                }
            } catch (Exception e) {
                logger.log(Level.WARNING, "Loading provisioning options failed.", e);
            }
        }
        return oldProvisioningOptions;
    }

}
