
package org.eclipse.virgo.nano.war.deployer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

import org.eclipse.gemini.web.core.InstallationOptions;
import org.eclipse.gemini.web.core.WebBundleManifestTransformer;
import org.eclipse.virgo.medic.eventlog.EventLogger;
import org.eclipse.virgo.nano.core.KernelConfig;
import org.eclipse.virgo.nano.deployer.SimpleDeployer;
import org.eclipse.virgo.nano.deployer.StandardDeploymentIdentity;
import org.eclipse.virgo.nano.deployer.api.core.DeploymentIdentity;
import org.eclipse.virgo.nano.deployer.util.BundleInfosUpdater;
import org.eclipse.virgo.util.io.FileSystemUtils;
import org.eclipse.virgo.util.io.IOUtils;
import org.eclipse.virgo.util.io.JarUtils;
import org.eclipse.virgo.util.io.PathReference;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.packageadmin.PackageAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("deprecation")
public class WARDeployer implements SimpleDeployer {

    private static final String WAR = "war";

    private static final boolean STATUS_OK = true;

    private static final boolean STATUS_ERROR = false;

    private static final String PICKUP_DIR = "pickup";

    private static final String INSTALL_BY_REFERENCE_PREFIX = "reference:file:";

    private static final char SLASH = '/';

    private static final char BACKSLASH = '\\';

    private static final char DOT = '.';

    private static final char NEW_LINE = '\n';

    private static final String SUCCESS_MARK = "ok";

    private static final String ERROR_MARK = "error";

    private static final String OP_DEPLOY = "deploy";

    private static final String OP_UNDEPLOY = "undeploy";

    private static final String FEEDBACK_FILE_NAME = ".state";

    private static final String BUNDLE_ID_RECORD = "bundle-id";

    static final String LAST_MODIFIED = "last-modified";

    private static final String DELIMITER = "=";

    static final String EMPTY_STRING = "";

    private static final String WEBAPPS_DIR = "webapps";

    private static final String WEBBUNDLE_PROTOCOL = "webbundle";

    private static final String FILE_PROTOCOL = "file";

    private static final String UNKNOWN = "unknown";

    private static final String HEADER_WEB_CONTEXT_PATH = "Web-ContextPath";

    // private static final String HEADER_BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";

    private static final String DEFAULT_CONTEXT_PATH = "/";

    private static final String ROOT_WAR_NAME = "ROOT";

    private static final String PROPERTY_WAB_HEADERS = "WABHeaders";

    private static final String PROPERTY_VALUE_WAB_HEADERS_STRICT = "strict";

    private static final String PROPERTY_VALUE_WAB_HEADERS_DEFAULTED = "defaulted";

    private static final String HEADER_DEFAULT_WAB_HEADERS = "org-eclipse-gemini-web-DefaultWABHeaders";

    private static final String WEB_BUNDLE_MODULE_TYPE = "web-bundle";

    private EventLogger eventLogger;

    private BundleInfosUpdater bundleInfosUpdaterUtil;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private BundleContext bundleContext;

    private PackageAdmin packageAdmin;

    private WebBundleManifestTransformer webBundleManifestTransformer;

    private long largeFileCopyTimeout = 4000;

    private File pickupDir;

    private File webAppsDir;

    private KernelConfig kernelConfig;

    public WARDeployer() {
        warDeployerInternalInit(null);
    }

    public WARDeployer(BundleContext bundleContext, PackageAdmin packageAdmin, WebBundleManifestTransformer webBundleManifestTransformer,
        EventLogger eventLogger, KernelConfig kernelConfig) {
        warDeployerInternalInit(bundleContext);
        this.packageAdmin = packageAdmin;
        this.webBundleManifestTransformer = webBundleManifestTransformer;
        this.eventLogger = eventLogger;
        this.kernelConfig = kernelConfig;
    }

    public void activate(ComponentContext context) {
        warDeployerInternalInit(context.getBundleContext());
    }

    @Override
    public final boolean deploy(URI path) {
        this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING, new File(path).toString());
        final String warName = extractWarNameFromString(path.toString());
        final File deployedFile = new File(path);
        final File warDir = new File(this.webAppsDir, warName);

        deleteStatusFile(warName, this.pickupDir);

        long bundleId = -1L;
        final long lastModified = deployedFile.lastModified();

        if (!canWrite(path)) {
            this.logger.error("Cannot open the file " + path + " for writing. The configured timeout is " + this.largeFileCopyTimeout + ".");
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING_ERROR, path);
            return STATUS_ERROR;
        }
        final Bundle installed;
        try {
            // extract the war file to the webapps directory
            JarUtils.unpackTo(new PathReference(deployedFile), new PathReference(warDir));
            // make the manifest transformation in the unpacked location
            transformUnpackedManifest(warDir, warName);

            // install the bundle
            installed = this.bundleContext.installBundle(createInstallLocation(warDir));
        } catch (Exception e) {
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING_ERROR, e, path);
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
            return STATUS_ERROR;
        }

        this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLED, installed.getSymbolicName(), installed.getVersion());
        this.eventLogger.log(NanoWARDeployerLogEvents.NANO_WEB_STARTING, installed.getSymbolicName(), installed.getVersion());
        try {
            installed.start();
        } catch (Exception e) {
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_STARTING_ERROR, e, installed.getSymbolicName(), installed.getVersion());
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
            return STATUS_ERROR;
        }

        this.eventLogger.log(NanoWARDeployerLogEvents.NANO_WEB_STARTED, installed.getSymbolicName(), installed.getVersion());

        bundleId = installed.getBundleId();
        // now update bundle's info
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Bundles info will be updated for war with path '" + path + "'.");
        }

        try {
            if (this.bundleInfosUpdaterUtil != null && this.bundleInfosUpdaterUtil.isAvailable()) {
                registerToBundlesInfo(installed);
            }
        } catch (Exception e) {
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_PERSIST_ERROR, e, installed.getSymbolicName(), installed.getVersion());
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
            return STATUS_ERROR;
        }

        createStatusFile(warName, OP_DEPLOY, STATUS_OK, bundleId, lastModified);
        return STATUS_OK;
    }

    @Override
    public boolean isDeployFileValid(File file) {
        JarFile jarFile = null;
        try {
            jarFile = new JarFile(file);
        } catch (IOException e) {
            this.logger.error("The deployed file '" + file.getAbsolutePath() + "' is an invalid zip file.");
            return false;
        } finally {
            try {
                if (jarFile != null) {
                    jarFile.close();
                }
            } catch (IOException e) {
                // do nothing
            }
        }
        return true;
    }

    private String createInstallLocation(final File warDir) {
        return INSTALL_BY_REFERENCE_PREFIX + warDir.getAbsolutePath();
    }

    private String extractWarNameFromString(String path) {
        final String warName = path.substring(path.lastIndexOf(SLASH) + 1, path.length() - 4);
        return warName;
    }

    @Override
    public final boolean undeploy(Bundle bundle) {
        String bundleLocation = removeTrailingFileSeparator(bundle.getLocation());
        String warPath = extractWarPath(bundleLocation);
        final File warDir = new File(warPath);
        String warName = extractWarName(warPath);

        deleteStatusFile(warName, this.pickupDir);

        if (bundle != null) {
            try {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Removing bundle '" + bundle.getSymbolicName() + "' version '" + bundle.getVersion() + "' from bundles.info.");
                }
                if (this.bundleInfosUpdaterUtil != null && this.bundleInfosUpdaterUtil.isAvailable()) {
                    unregisterToBundlesInfo(bundle);
                    this.logger.info("Successfully removed bundle '" + bundle.getSymbolicName() + "' version '" + bundle.getVersion()
                        + "' from bundles.info.");
                } else {
                    this.logger.error("BundleInfosUpdater not available. Failed to remove bundle '" + bundle.getSymbolicName() + "' version '"
                        + bundle.getVersion() + "' from bundles.info.");
                }
                this.eventLogger.log(NanoWARDeployerLogEvents.NANO_STOPPING, bundle.getSymbolicName(), bundle.getVersion());
                bundle.stop();
                this.eventLogger.log(NanoWARDeployerLogEvents.NANO_STOPPED, bundle.getSymbolicName(), bundle.getVersion());
                this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UNINSTALLING, bundle.getSymbolicName(), bundle.getVersion());
                bundle.uninstall();
                FileSystemUtils.deleteRecursively(warDir);
                this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UNINSTALLED, bundle.getSymbolicName(), bundle.getVersion());
            } catch (BundleException e) {
                this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UNDEPLOY_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
                return STATUS_ERROR;
            }
        }

        createStatusFile(warName, OP_UNDEPLOY, STATUS_OK, bundle.getBundleId(), bundle.getLastModified());
        return STATUS_OK;
    }

    private String extractWarName(String warPath) {
        return warPath.substring(warPath.lastIndexOf(File.separatorChar) + 1, warPath.length());
    }

    private String extractWarPath(String bundleLocation) {
        String warPath;
        if (bundleLocation.startsWith(INSTALL_BY_REFERENCE_PREFIX)) {
            warPath = bundleLocation.substring(INSTALL_BY_REFERENCE_PREFIX.length());
        } else {
            warPath = bundleLocation;
        }
        return warPath;
    }

    private String removeTrailingFileSeparator(String bundleLocation) {
        if (bundleLocation.endsWith(File.separator)) {
            bundleLocation = bundleLocation.substring(0, bundleLocation.length() - 1);
        }
        return bundleLocation;
    }

    @Override
    public final boolean update(URI path) {
        final String warName = extractWarNameFromString(path.toString());
        final File updatedFile = new File(path);
        final File warDir = new File(this.webAppsDir, warName);

        if (!warDir.exists()) {
            this.logger.info("Can't update artifact for path '" + path + "'. It is not deployed.");
        }

        deleteStatusFile(warName, this.pickupDir);

        final long bundleId = -1L;
        final long lastModified = updatedFile.lastModified();

        if (!canWrite(path)) {
            this.logger.error("Cannot open the file [" + path + "] for writing. Timeout is [" + this.largeFileCopyTimeout + "].");
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UPDATING_ERROR, path);
            return STATUS_ERROR;
        }

        final Bundle bundle = this.bundleContext.getBundle(createInstallLocation(warDir));
        if (bundle != null) {
            try {
                // extract the war file to the webapps directory
                JarUtils.unpackToDestructive(new PathReference(updatedFile), new PathReference(warDir));
                // make the manifest transformation in the unpacked location
                transformUnpackedManifest(warDir, warName);
                this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UPDATING, bundle.getSymbolicName(), bundle.getVersion());
                bundle.update();
                if (this.packageAdmin != null) {
                    this.packageAdmin.refreshPackages(new Bundle[] { bundle });
                    this.logger.info("Update of file with path [" + path + "] is successful.");
                }
                this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UPDATED, bundle.getSymbolicName(), bundle.getVersion());
            } catch (Exception e) {
                this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UPDATE_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
                createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
                return STATUS_ERROR;
            }

            createStatusFile(warName, OP_DEPLOY, STATUS_OK, bundleId, lastModified);
        } else {
            deploy(path);
        }
        return STATUS_OK;
    }

    public void setLargeFileCopyTimeout(long timeout) {
        if (this.logger.isInfoEnabled()) {
            this.logger.info("setLargeFileCopyTimeout(" + timeout + ")");
        }
        this.largeFileCopyTimeout = timeout;
    }

    private void createStatusFile(String warName, String operation, boolean status, long bundleId, long lastModified) {
        final File stateDir = new File(this.pickupDir, FEEDBACK_FILE_NAME);
        if (!stateDir.exists() && !stateDir.mkdirs()) {
            this.logger.error("Cannot create directory [" + stateDir.getAbsolutePath() + "]. Status file for the operation cannot be created.");
            return;
        }
        final File statusFile = new File(stateDir, warName + DOT + operation + DOT + (status ? SUCCESS_MARK : ERROR_MARK));
        FileWriter fw = null;
        try {
            fw = new FileWriter(statusFile, true);
            fw.write(BUNDLE_ID_RECORD + DELIMITER + bundleId);
            fw.write(NEW_LINE);
            fw.write(LAST_MODIFIED + DELIMITER + lastModified);
            fw.write(NEW_LINE);
            fw.flush();
        } catch (IOException e) {
            this.logger.error("Cannot update the status of operation.", e);
        } finally {
            IOUtils.closeQuietly(fw);
        }
    }

    private void deleteStatusFile(String warName, File pickupDir) {
        final File stateDir = new File(pickupDir, FEEDBACK_FILE_NAME);
        if (stateDir.exists()) {
            File statusFile = new File(stateDir, warName + DOT + OP_DEPLOY + DOT + SUCCESS_MARK);
            if (statusFile.exists() && !statusFile.delete()) {
                this.logger.error("Cannot delete file [" + statusFile.getAbsolutePath() + "].");
            }
            statusFile = new File(stateDir, warName + DOT + OP_DEPLOY + DOT + ERROR_MARK);
            if (statusFile.exists() && !statusFile.delete()) {
                this.logger.error("Cannot delete file [" + statusFile.getAbsolutePath() + "].");
            }
            statusFile = new File(stateDir, warName + DOT + OP_UNDEPLOY + DOT + SUCCESS_MARK);
            if (statusFile.exists() && !statusFile.delete()) {
                this.logger.error("Cannot delete file [" + statusFile.getAbsolutePath() + "].");
            }
            statusFile = new File(stateDir, warName + DOT + OP_UNDEPLOY + DOT + ERROR_MARK);
            if (statusFile.exists() && !statusFile.delete()) {
                this.logger.error("Cannot delete file [" + statusFile.getAbsolutePath() + "].");
            }
        }
    }

    private boolean canWrite(URI path) {
        int tries = -1;
        boolean isWritable = false;
        // Some big files are copied very slowly, but the event is received
        // immediately.
        // So we will wait 0.5 x 240 i.e. 2 minutes
        final long timeout = this.largeFileCopyTimeout / 500;
        while (tries < timeout) {
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(new File(path));
                isWritable = true;
                break;
            } catch (FileNotFoundException e) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("File is still locked.", e);
                }
            } finally {
                IOUtils.closeQuietly(fis);
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                this.logger.error("InterruptedException occurred.", e);
            }
            tries++;
        }
        return isWritable;
    }

    private final void transformUnpackedManifest(File srcFile, String warName) throws IOException {
        if (srcFile == null) {
            throw new NullPointerException("Source file is null.");
        }
        if (!srcFile.isDirectory() || !srcFile.canRead()) {
            throw new IllegalArgumentException("Source file must be a readable directory [" + srcFile + "].");
        }
        File destFile = new File(srcFile, JarFile.MANIFEST_NAME);
        if (!destFile.exists()) {
            destFile.getParentFile().mkdirs();
            destFile.createNewFile();
        }
        if (!destFile.isFile() || !destFile.canRead()) {
            throw new IllegalArgumentException("Destination file must be a readable file [" + destFile + "].");
        }

        FileOutputStream fos = null;
        InputStream mfIS = null;
        try {
            mfIS = new FileInputStream(srcFile + File.separator + JarFile.MANIFEST_NAME);
            BundleManifest manifest = BundleManifestFactory.createBundleManifest(new InputStreamReader(mfIS));
            if (manifest.getModuleType() == null || "web".equalsIgnoreCase(manifest.getModuleType())) {
                boolean strictWABHeaders = getStrictWABHeadersValue();
                if (!strictWABHeaders) {
                    manifest.setHeader(HEADER_DEFAULT_WAB_HEADERS, "true");
                }
                manifest.setModuleType(WEB_BUNDLE_MODULE_TYPE);
                InstallationOptions installationOptions = prepareInstallationOptions(strictWABHeaders, warName, manifest);
                boolean isWebBundle = WebBundleUtils.isWebApplicationBundle(manifest);
                this.webBundleManifestTransformer.transform(manifest, srcFile.toURI().toURL(), installationOptions, isWebBundle);
            } else {
                this.logger.info("Skipping transformation of application '" + warName + "' because it is already a web bundle.");
                return;
            }
            fos = new FileOutputStream(destFile);
            toManifest(manifest.toDictionary()).write(fos);
        } finally {
            IOUtils.closeQuietly(fos);
            IOUtils.closeQuietly(mfIS);
        }
    }

    private InstallationOptions prepareInstallationOptions(boolean strictWABHeaders, String warName, BundleManifest manifest) {
        Map<String, String> map = new HashMap<String, String>();
        String webContextPathHeader = manifest.getHeader(HEADER_WEB_CONTEXT_PATH);
        if (webContextPathHeader == null || webContextPathHeader.trim().length() == 0) {
            if (warName.equals(ROOT_WAR_NAME)) {
                map.put(HEADER_WEB_CONTEXT_PATH, DEFAULT_CONTEXT_PATH);
            } else {
                map.put(HEADER_WEB_CONTEXT_PATH, warName);
            }
        }

        InstallationOptions installationOptions = new InstallationOptions(map);
        installationOptions.setDefaultWABHeaders(!strictWABHeaders);

        return installationOptions;
    }

    private final Manifest toManifest(Dictionary<String, String> headers) {
        Manifest manifest = new Manifest();
        Attributes attributes = manifest.getMainAttributes();
        Enumeration<String> names = headers.keys();

        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String value = headers.get(name);

            attributes.putValue(name, value);
        }
        return manifest;
    }

    private final void registerToBundlesInfo(Bundle bundle) throws URISyntaxException, IOException, BundleException {
        String location = bundle.getLocation().replace(BACKSLASH, SLASH);
        if (!location.contains(WEBBUNDLE_PROTOCOL)) {
            location = location.replaceAll(" ", "%20");
            String scheme = new URI(location).getScheme();
            if (scheme != null && !scheme.equals(FILE_PROTOCOL)) {
                location = new URI(location).getRawSchemeSpecificPart();
            }
            String symbolicName = bundle.getSymbolicName();
            this.bundleInfosUpdaterUtil.addBundleToBundlesInfo(symbolicName == null ? UNKNOWN : symbolicName, new URI(location),
                bundle.getVersion().toString(), SimpleDeployer.HOT_DEPLOYED_ARTIFACTS_START_LEVEL, true);
            this.bundleInfosUpdaterUtil.updateBundleInfosRepository();
        }
    }

    private final void unregisterToBundlesInfo(Bundle bundle) {
        try {
            String location = bundle.getLocation().replace(BACKSLASH, SLASH);
            if (!location.contains(WEBBUNDLE_PROTOCOL)) {
                location = location.replaceAll(" ", "%20");
                String scheme = new URI(location).getScheme();
                if (scheme != null && !scheme.equals(FILE_PROTOCOL)) {
                    location = new URI(location).getRawSchemeSpecificPart();
                }
                String symbolicName = bundle.getSymbolicName();
                this.bundleInfosUpdaterUtil.removeBundleFromBundlesInfo(symbolicName == null ? UNKNOWN : symbolicName, new URI(location),
                    bundle.getVersion().toString(), SimpleDeployer.HOT_DEPLOYED_ARTIFACTS_START_LEVEL, true);
                this.bundleInfosUpdaterUtil.updateBundleInfosRepository();
            }
        } catch (Exception e) {
            this.logger.error("Cannot update bundles info while unregistering [" + bundle.getSymbolicName() + "].", e);
        }
    }

    @Override
    public boolean canServeFileType(String fileType) {
        return fileType.toLowerCase().equals(WAR);
    }

    @Override
    public boolean isDeployed(URI path) {
        final String warName = extractWarNameFromString(path.toString());
        final File warDir = new File(this.webAppsDir, warName);
        if (!warDir.exists()) {
            return false;
        }
        if (this.bundleContext.getBundle(createInstallLocation(warDir)) == null) {
            return false;
        }
        return true;
    }

    @Override
    public DeploymentIdentity getDeploymentIdentity(URI path) {
        final String warName = extractWarNameFromString(path.toString());
        final File warDir = new File(this.webAppsDir, warName);
        if (!warDir.exists()) {
            return null;
        }
        Bundle bundle = this.bundleContext.getBundle(createInstallLocation(warDir));
        if (bundle == null) {
            return null;
        }
        return new StandardDeploymentIdentity(WAR, bundle.getSymbolicName(), bundle.getVersion().toString());
    }

    @Override
    public List<String> getAcceptedFileTypes() {
        List<String> types = new ArrayList<String>();
        types.add(WAR);
        return types;
    }

    private void warDeployerInternalInit(BundleContext bundleContext) {
        String kernelHome = System.getProperty("org.eclipse.virgo.kernel.home");
        File kernelHomeFile = new File(kernelHome);
        File bundlesInfoFile = new File(kernelHomeFile, "configuration/org.eclipse.equinox.simpleconfigurator/bundles.info");
        this.pickupDir = new File(kernelHomeFile, PICKUP_DIR);
        this.webAppsDir = new File(kernelHomeFile, WEBAPPS_DIR);
        this.bundleContext = bundleContext;
        this.bundleInfosUpdaterUtil = new BundleInfosUpdater(bundlesInfoFile, kernelHomeFile);
    }

    private boolean getStrictWABHeadersValue() {
        boolean strictWABHeaders = true;
        String wabHeadersPropertyValue = null;
        if (this.kernelConfig.getProperty(PROPERTY_WAB_HEADERS) != null) {
            wabHeadersPropertyValue = this.kernelConfig.getProperty(PROPERTY_WAB_HEADERS).toString();
        }
        if (wabHeadersPropertyValue != null) {
            if (PROPERTY_VALUE_WAB_HEADERS_DEFAULTED.equals(wabHeadersPropertyValue)) {
                strictWABHeaders = false;
                this.logger.info("Property '%s' has value [defaulted]", new String[] { PROPERTY_WAB_HEADERS });
            } else if (!PROPERTY_VALUE_WAB_HEADERS_STRICT.equals(wabHeadersPropertyValue)) {
                this.logger.error("Property '%s' has invalid value '%s'", new String[] { PROPERTY_WAB_HEADERS, wabHeadersPropertyValue });
            }
        }

        return strictWABHeaders;
    }

    public void bindWebBundleManifestTransformer(WebBundleManifestTransformer transformer) {
        this.webBundleManifestTransformer = transformer;
    }

    public void unbindWebBundleManifestTransformer(WebBundleManifestTransformer transformer) {
        this.webBundleManifestTransformer = null;
    }

    public void bindEventLogger(EventLogger logger) {
        this.eventLogger = logger;
    }

    public void unbindEventLogger(EventLogger logger) {
        this.eventLogger = null;
    }

    public void bindPackageAdmin(PackageAdmin packageAdmin) {
        this.packageAdmin = packageAdmin;
    }

    public void unbindPackageAdmin(PackageAdmin packageAdmin) {
        this.packageAdmin = null;
    }

    public void bindKernelConfig(KernelConfig kernelConfig) {
        this.kernelConfig = kernelConfig;
    }

    public void unbindKernelConfig(KernelConfig kernelConfig) {
        this.kernelConfig = null;
    }

    @Override
    public boolean install(URI uri) {
        this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING, new File(uri).toString());
        final String warName = extractWarNameFromString(uri.toString());
        final File deployedFile = new File(uri);
        final File warDir = new File(this.webAppsDir, warName);
        deleteStatusFile(warName, this.pickupDir);
        final long lastModified = deployedFile.lastModified();

        if (!canWrite(uri)) {
            this.logger.error("Cannot open the file " + uri + " for writing. The configured timeout is " + this.largeFileCopyTimeout + ".");
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, -1L, lastModified);
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING_ERROR, uri);
            return false;
        }
        final Bundle installed;
        try {
            // extract the war file to the webapps directory
            JarUtils.unpackTo(new PathReference(deployedFile), new PathReference(warDir));
            // make the manifest transformation in the unpacked location
            transformUnpackedManifest(warDir, warName);
            // install the bundle
            installed = this.bundleContext.installBundle(createInstallLocation(warDir));
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLED, installed.getSymbolicName(), installed.getVersion());
        } catch (Exception e) {
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING_ERROR, e, uri);
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, -1L, lastModified);
            return false;
        }
        return true;
    }

    @Override
    public boolean start(URI uri) {
        Bundle bundle = getInstalledBundle(uri);
        final String warName = extractWarNameFromString(uri.toString());
        deleteStatusFile(warName, this.pickupDir);
        final long lastModified = new File(uri).lastModified();
        this.eventLogger.log(NanoWARDeployerLogEvents.NANO_WEB_STARTING, bundle.getSymbolicName(), bundle.getVersion());
        try {
            bundle.start();
        } catch (Exception e) {
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_STARTING_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundle.getBundleId(), lastModified);
            return STATUS_ERROR;
        }
        this.eventLogger.log(NanoWARDeployerLogEvents.NANO_WEB_STARTED, bundle.getSymbolicName(), bundle.getVersion());

        // now update bundle's info
        if (!updateBundlesInfo(bundle)) {
            createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundle.getBundleId(), lastModified);
            return STATUS_ERROR;
        }
        createStatusFile(warName, OP_DEPLOY, STATUS_OK, bundle.getBundleId(), lastModified);
        return STATUS_OK;
    }

    private boolean updateBundlesInfo(Bundle bundle) {
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Bundles info will be updated for web app bundle with simbolic name '" + bundle.getSymbolicName() + "' .");
        }
        try {
            if (this.bundleInfosUpdaterUtil != null && this.bundleInfosUpdaterUtil.isAvailable()) {
                registerToBundlesInfo(bundle);
            }
        } catch (Exception e) {
            this.eventLogger.log(NanoWARDeployerLogEvents.NANO_PERSIST_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
            return STATUS_ERROR;
        }
        return STATUS_OK;
    }

    private Bundle getInstalledBundle(URI path) {
        final String warName = extractWarNameFromString(path.toString());
        final File warDir = new File(this.webAppsDir, warName);
        if (!warDir.exists()) {
            return null;
        }
        return this.bundleContext.getBundle(createInstallLocation(warDir));
    }

}
