/*
 * 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.sling.maven.slingstart;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.felix.cm.file.ConfigurationHandler;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.sling.commons.osgi.BSNRenamer;
import org.apache.sling.provisioning.model.ArtifactGroup;
import org.apache.sling.provisioning.model.Configuration;
import org.apache.sling.provisioning.model.Feature;
import org.apache.sling.provisioning.model.FeatureTypes;
import org.apache.sling.provisioning.model.Model;
import org.apache.sling.provisioning.model.ModelConstants;
import org.apache.sling.provisioning.model.RunMode;
import org.apache.sling.provisioning.model.Section;
import org.apache.sling.provisioning.model.io.ModelWriter;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
import org.codehaus.plexus.util.FileUtils;

/**
 * Prepare the sling start applications.
 */
@Mojo(
        name = "prepare-package",
        defaultPhase = LifecyclePhase.PROCESS_SOURCES,
        requiresDependencyResolution = ResolutionScope.TEST,
        threadSafe = true
    )
public class PreparePackageMojo extends AbstractSlingStartMojo {

    private static final String ALL_RUNMODES_KEY = "_all_";

    private static final String BASE_DESTINATION = "resources";

    private static final String BOOT_DIRECTORY = "bundles";

    private static final String ARTIFACTS_DIRECTORY = "install";

    private static final String CONFIG_DIRECTORY = "config";

    private static final String PROVISIONING_DIRECTORY = "provisioning";

    private static final String EMBEDDED_MODEL_FILENAME = "model.txt";

    private static final String BOOTSTRAP_FILE = "sling_bootstrap.txt";

    private static final String PROPERTIES_FILE = "sling_install.properties";

    /**
     * To look up Archiver/UnArchiver implementations
     */
    @Component
    private ArchiverManager archiverManager;

    @Component
    private ArtifactHandlerManager artifactHandlerManager;

    /**
     * Used to look up Artifacts in the remote repository.
     *
     */
    @Component
    private ArtifactResolver resolver;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        final Model model = ProjectHelper.getEffectiveModel(this.project, getResolverOptions());

        execute(model);
    }

    void execute(final Model model) throws MojoExecutionException {
        this.prepareGlobal(model);
        this.prepareStandaloneApp(model);
        this.prepareWebapp(model);
    }

    /**
     * Prepare the global map for the artifacts.
     */
    private void prepareGlobal(final Model model) throws MojoExecutionException {
        final Map<String, File> globalContentsMap = new HashMap<String, File>();
        this.buildContentsMap(model, (String)null, globalContentsMap);

        this.project.setContextValue(BuildConstants.CONTEXT_GLOBAL, globalContentsMap);
    }

    /**
     * Prepare the standalone application.
     */
    private void prepareStandaloneApp(final Model model) throws MojoExecutionException {
        final Map<String, File> contentsMap = new HashMap<String, File>();
        this.project.setContextValue(BuildConstants.CONTEXT_STANDALONE, contentsMap);

        // unpack base artifact and create settings
        final File outputDir = getStandaloneOutputDirectory();
        unpackBaseArtifact(model, outputDir, ModelConstants.RUN_MODE_STANDALONE);
        this.buildSettings(model, ModelConstants.RUN_MODE_STANDALONE, outputDir);
        this.buildBootstrapFile(model, ModelConstants.RUN_MODE_STANDALONE, outputDir);
        this.embedModel(model, outputDir);

        this.buildContentsMap(model, ModelConstants.RUN_MODE_STANDALONE, contentsMap);
    }

    /** Embed our model in the created jar file */
    private void embedModel(Model model, File outputDir) throws MojoExecutionException {
        final File modelDir = new File(new File(outputDir, BASE_DESTINATION), PROVISIONING_DIRECTORY);
        modelDir.mkdirs();
        final File modelFile = new File(modelDir, EMBEDDED_MODEL_FILENAME);
        try {
            final FileWriter w = new FileWriter(modelFile);
            try {
                w.write("# Aggregated provisioning model embedded by " + getClass().getName() + "\n");
                ModelWriter.write(w, model);
            } finally {
                w.flush();
                w.close();
            }
        } catch(IOException ioe) {
            throw new MojoExecutionException("Failed to create model file " + modelFile.getAbsolutePath(), ioe);
        }
    }

    /**
     * Prepare the web application.
     */
    private void prepareWebapp(final Model model) throws MojoExecutionException {
        if ( this.createWebapp ) {
            final Map<String, File> contentsMap = new HashMap<String, File>();
            this.project.setContextValue(BuildConstants.CONTEXT_WEBAPP, contentsMap);

            // unpack base artifact and create settings
            final File outputDir = new File(this.project.getBuild().getDirectory(), BuildConstants.WEBAPP_OUTDIR);
            final File webappDir = new File(outputDir, "WEB-INF");
            unpackBaseArtifact(model, outputDir, ModelConstants.RUN_MODE_WEBAPP);

            // check for web.xml
            final Feature webappF = model.getFeature(ModelConstants.FEATURE_LAUNCHPAD);
            if ( webappF != null ) {
                final RunMode webappRM = webappF.getRunMode();
                if ( webappRM != null ) {
                    final Configuration webConfig = webappRM.getConfiguration(ModelConstants.CFG_LAUNCHPAD_WEB_XML);
                    if ( webConfig != null ) {
                        final File webXML = new File(webappDir, "web.xml");
                        try {
                            FileUtils.fileWrite(webXML, webConfig.getProperties().get(ModelConstants.CFG_LAUNCHPAD_WEB_XML).toString());
                        } catch (final IOException e) {
                            throw new MojoExecutionException("Unable to write configuration to " + webXML, e);
                        }
                    }
                }
            }
            this.buildSettings(model, ModelConstants.RUN_MODE_WEBAPP, webappDir);
            this.buildBootstrapFile(model, ModelConstants.RUN_MODE_WEBAPP, webappDir);
            this.embedModel(model, webappDir);

            this.buildContentsMap(model, ModelConstants.RUN_MODE_WEBAPP, contentsMap);
        }
    }

    /**
     * Build a list of all artifacts.
     */
    private void buildContentsMap(final Model model, final String packageRunMode, final Map<String, File> contentsMap)
    throws MojoExecutionException {
        if ( packageRunMode == null ) {
            // add base jar
            final Artifact artifact = getBaseArtifact(model, null, BuildConstants.TYPE_JAR);
            contentsMap.put(BASE_DESTINATION + "/"+ artifact.getArtifactId() + "." + artifact.getArtifactHandler().getExtension(), artifact.getFile());
        }
        for(final Feature feature : model.getFeatures()) {
            if ( feature.isSpecial() && !feature.getName().equals(ModelConstants.FEATURE_BOOT)) {
                continue;
            } else if (FeatureTypes.SUBSYSTEM_APPLICATION.equals(feature.getType()) ||
                    FeatureTypes.SUBSYSTEM_COMPOSITE.equals(feature.getType()) ||
                    FeatureTypes.SUBSYSTEM_FEATURE.equals(feature.getType())) {
                buildSubsystemBase(contentsMap, feature);
            } else {
                for(final RunMode runMode : feature.getRunModes()) {
                    if ( packageRunMode == null ) {
                        if ( runMode.isSpecial() ) {
                            continue;
                        }
                        this.buildContentsMap(model, runMode, contentsMap, feature.getName().equals(ModelConstants.FEATURE_BOOT));
                    } else {
                        if ( runMode.isRunMode(packageRunMode) ) {
                            this.buildContentsMap(model, runMode, contentsMap, feature.getName().equals(ModelConstants.FEATURE_BOOT));
                        }
                    }
                }
            }
        }
    }

    private void buildSubsystemBase(final Map<String, File> contentsMap, final Feature feature) throws MojoExecutionException {
        AtomicInteger startLevelHolder = new AtomicInteger(); // Used as output argument
        File subsystemFile = createSubsystemBaseFile(feature, startLevelHolder);
        if (subsystemFile != null)
            contentsMap.put(getPathForArtifact(startLevelHolder.get(), subsystemFile.getName()), subsystemFile);
    }

    /**
     * Build a list of all artifacts from this run mode
     */
    private void buildContentsMap(final Model model, final RunMode runMode, final Map<String, File> contentsMap, final boolean isBoot)
    throws MojoExecutionException{
        for(final ArtifactGroup group : runMode.getArtifactGroups()) {
            for(final org.apache.sling.provisioning.model.Artifact a : group) {
                Artifact artifact = null;
                if ( a.getGroupId().equals(this.project.getGroupId())
                        && a.getArtifactId().equals(this.project.getArtifactId())
                        && a.getVersion().equals(this.project.getVersion()) ) {
                    for(final Artifact projectArtifact : this.project.getAttachedArtifacts()) {
                        if ( projectArtifact.getClassifier().equals(a.getClassifier()) ) {
                            artifact = projectArtifact;
                            break;
                        }
                    }
                    if ( artifact == null ) {
                        throw new MojoExecutionException("Unable to find artifact from same project: " + a.toMvnUrl());
                    }
                } else {
                    artifact = ModelUtils.getArtifact(this.project, this.mavenSession, this.artifactHandlerManager, this.resolver,
                        a.getGroupId(), a.getArtifactId(), a.getVersion(), a.getType(), a.getClassifier());
                }
                File artifactFile = artifact.getFile();

                String newBSN = a.getMetadata().get("bundle:rename-bsn");
                if (newBSN != null) {
                    try {
                        getTmpDir().mkdirs();
                        artifactFile = new BSNRenamer(artifactFile, getTmpDir(), newBSN).process();
                    } catch (IOException e) {
                        throw new MojoExecutionException("Unable to rename bundle BSN to " + newBSN + " for " + artifactFile, e);
                    }
                }

                contentsMap.put(getPathForArtifact(group.getStartLevel(), artifactFile.getName(), runMode, isBoot), artifactFile);
            }
        }

        final File rootConfDir = new File(this.getTmpDir(), "global-config");
        boolean hasConfig = false;
        for(final Configuration config : runMode.getConfigurations()) {
            // skip special configurations
            if ( config.isSpecial() ) {
                continue;
            }
            final String configPath = getPathForConfiguration(config, runMode);
            final File configFile = new File(rootConfDir, configPath);
            getLog().debug(String.format("Creating configuration at %s", configFile.getPath()));
            configFile.getParentFile().mkdirs();
            try {
                final FileOutputStream os = new FileOutputStream(configFile);
                try {
                    ConfigurationHandler.write(os, config.getProperties());
                } finally {
                    os.close();
                }
            } catch (final IOException e) {
                throw new MojoExecutionException("Unable to write configuration to " + configFile, e);
            }
            hasConfig = true;
        }
        if ( hasConfig ) {
            contentsMap.put(BASE_DESTINATION, rootConfDir);
        }
    }

    private File createSubsystemBaseFile(Feature feature, AtomicInteger startLevelHolder) throws MojoExecutionException {
        File subsystemFile = new File(getTmpDir(), feature.getName() + ".subsystem-base");
        if (subsystemFile.exists()) {
            // This subsystem has already been created
            // TODO is there a better way to avoid calling this multiple times?
            return null;
        }

        startLevelHolder.set(-1);

        // The runmodes information has to be the first item in the archive so that we always have it available when the
        // archive is being processed. For this reason a Jar file is used here as it's guaranteed to store the manifest
        // first.
        Manifest runModesManifest = getRunModesManifest(feature);

        getLog().info("Creating subsystem base file: " + subsystemFile.getName());
        boolean created = subsystemFile.getParentFile().mkdirs();
        if ( !created ) {
            throw new MojoExecutionException("Failed creating " + subsystemFile.getParentFile().getAbsolutePath());
        }

        try (JarOutputStream os = new JarOutputStream(new FileOutputStream(subsystemFile), runModesManifest)) {
            Map<String, Integer> bsnStartOrderMap = new HashMap<>();

            for (RunMode rm : feature.getRunModes()) {
                for (ArtifactGroup ag : rm.getArtifactGroups()) {
                    int startOrder = ag.getStartLevel(); // For subsystems the start level on the artifact group is used as start order.

                    for (org.apache.sling.provisioning.model.Artifact a : ag) {
                        Artifact artifact = ModelUtils.getArtifact(this.project, this.mavenSession, this.artifactHandlerManager, this.resolver,
                                a.getGroupId(), a.getArtifactId(), a.getVersion(), a.getType(), a.getClassifier());
                        File artifactFile = artifact.getFile();
                        String entryName = getEntryName(artifactFile, startOrder);

                        ZipEntry ze = new ZipEntry(entryName);
                        try {
                            os.putNextEntry(ze);
                            Files.copy(artifactFile.toPath(), os);
                        } finally {
                            os.closeEntry();
                        }
                    }
                }
            }

            int sl = createSubsystemManifest(feature, bsnStartOrderMap, os);
            if (sl != -1)
                startLevelHolder.set(sl);
            addReadme(os);
        } catch (IOException ioe) {
            throw new MojoExecutionException("Problem creating subsystem .esa file " + subsystemFile, ioe);
        }
        return subsystemFile;
    }

    private Manifest getRunModesManifest(Feature feature) throws MojoExecutionException {
        Map<String, StringBuilder> runModes = new HashMap<>();

        for (RunMode rm : feature.getRunModes()) {
            for (ArtifactGroup ag : rm.getArtifactGroups()) {
                int startOrder = ag.getStartLevel(); // For subsystems the start level on the artifact group is used as start order.

                for (org.apache.sling.provisioning.model.Artifact a : ag) {
                    Artifact artifact = ModelUtils.getArtifact(this.project, this.mavenSession, this.artifactHandlerManager, this.resolver,
                            a.getGroupId(), a.getArtifactId(), a.getVersion(), a.getType(), a.getClassifier());
                    File artifactFile = artifact.getFile();
                    String entryName = getEntryName(artifactFile, startOrder);

                    String [] runModeNames = rm.getNames();
                    if (runModeNames == null)
                        runModeNames = new String[] {ALL_RUNMODES_KEY};

                    for (String runModeName : runModeNames) {
                        StringBuilder sb = runModes.get(runModeName);
                        if (sb == null) {
                            sb = new StringBuilder();
                            runModes.put(runModeName, sb);
                        } else {
                            sb.append('|');
                        }

                        sb.append(entryName);
                    }
                }
            }
        }

        Manifest mf = new Manifest();
        Attributes attrs = mf.getMainAttributes();
        attrs.putValue("Manifest-Version", "1.0"); // Manifest does not work without this value
        attrs.putValue("About-This-Manifest", "This is not a real manifest, it is used as information when this archive is transformed into a real subsystem .esa file");
        for (Map.Entry<String, StringBuilder> entry : runModes.entrySet()) {
            attrs.putValue(entry.getKey().replace(':', '_'), entry.getValue().toString());
        }
        return mf;
    }

    private String getEntryName(File artifactFile, int startOrder) {
        return "Potential_Bundles/" + startOrder + "/" + artifactFile.getName();
    }

    // This manifest will be used as the basis for the OSGI-INF/SUBSYSTEM.MF file when the real
    // .esa file is generated. However since some contents of that file depend on the actual
    // runmode that is being executed, additional information will be added to the SUBSYSTEM.MF
    // file at startup time before it's finalized (example: Subsystem-Content).
    private int createSubsystemManifest(Feature feature,
            Map<String, Integer> startOrderMap, ZipOutputStream os) throws IOException {
        int subsystemStartLevel = -1;
        ZipEntry ze = new ZipEntry("SUBSYSTEM-MANIFEST-BASE.MF");
        try {
            os.putNextEntry(ze);

            Manifest mf = new Manifest();
            Attributes attributes = mf.getMainAttributes();
            attributes.putValue("Manifest-Version", "1.0"); // Manifest does not work without this value
            attributes.putValue("Subsystem-SymbolicName", feature.getName());
            attributes.putValue("Subsystem-Version", "1"); // Version must be an integer (cannot be a long), TODO better idea?
            attributes.putValue("Subsystem-Type", feature.getType());
            for (Section section : feature.getAdditionalSections("subsystem-manifest")) {
                String sl = section.getAttributes().get("startLevel");
                try {
                    subsystemStartLevel = Integer.parseInt(sl);
                } catch (NumberFormatException nfe) {
                    // Not a valid start level
                }

                BufferedReader br = new BufferedReader(new StringReader(section.getContents()));
                String line = null;
                while ((line = br.readLine()) != null) {
                    int idx = line.indexOf(':');
                    if (idx > 0) {
                        String key = line.substring(0, idx);
                        String value;
                        idx++;
                        if (line.length() > idx)
                            value = line.substring(idx);
                        else
                            value = "";
                        attributes.putValue(key.trim(), value.trim());
                    }
                }
            }
            mf.write(os);
        } finally {
            os.closeEntry();
        }

        return subsystemStartLevel;
    }

    private void addReadme(ZipOutputStream os) throws IOException {
        ZipEntry ze = new ZipEntry("readme.txt");
        try (InputStream is = getClass().getResourceAsStream("/subsystem-base/readme.txt")) {
            os.putNextEntry(ze);
            IOUtils.copy(is, os);
        } finally {
            os.closeEntry();
        }
    }

    /**
     * Build the settings for the given packaging run mode
     */
    private void buildSettings(final Model model, final String packageRunMode, final File outputDir)
    throws MojoExecutionException {
        final Properties settings = new Properties();
        final Feature launchpadFeature = model.getFeature(ModelConstants.FEATURE_LAUNCHPAD);
        if ( launchpadFeature != null ) {
            final RunMode launchpadRunMode = launchpadFeature.getRunMode();
            if ( launchpadRunMode != null ) {
                for(final Map.Entry<String, String> entry : launchpadRunMode.getSettings()) {
                    settings.put(entry.getKey(), deescapeVariablePlaceholders(entry.getValue()));
                }
            }
        }
        final Feature bootFeature = model.getFeature(ModelConstants.FEATURE_BOOT);
        if ( bootFeature != null ) {
            final RunMode bootRunMode = bootFeature.getRunMode();
            if ( bootRunMode != null ) {
                for(final Map.Entry<String, String> entry : bootRunMode.getSettings()) {
                    settings.put(entry.getKey(), deescapeVariablePlaceholders(entry.getValue()));
                }
            }
        }
        for(final Feature f : model.getFeatures()) {
            final RunMode packageRM = f.getRunMode(new String[] {packageRunMode});
            if ( packageRM != null ) {
                for(final Map.Entry<String, String> entry : packageRM.getSettings()) {
                    settings.put(entry.getKey(), deescapeVariablePlaceholders(entry.getValue()));
                }
            }
        }

        if ( settings.size() > 0 ) {
            final File settingsFile = new File(outputDir, PROPERTIES_FILE);
            getLog().debug(String.format("Creating settings at %s", settingsFile.getPath()));
            FileWriter writer = null;
            try {
                writer = new FileWriter(settingsFile);
                settings.store(writer, null);
            } catch ( final IOException ioe ) {
                throw new MojoExecutionException("Unable to write properties file.", ioe);
            } finally {
                IOUtils.closeQuietly(writer);
            }
        }
    }

    /**
     * Build the bootstrap file for the given packaging run mode
     */
    private void buildBootstrapFile(final Model model, final String packageRunMode, final File outputDir)
    throws MojoExecutionException {
        final StringBuilder sb = new StringBuilder();

        final Feature launchpadFeature = model.getFeature(ModelConstants.FEATURE_LAUNCHPAD);
        if ( launchpadFeature != null ) {
            final RunMode launchpadRunMode = launchpadFeature.getRunMode();
            if ( launchpadRunMode != null ) {
                final Configuration c = launchpadRunMode.getConfiguration(ModelConstants.CFG_LAUNCHPAD_BOOTSTRAP);
                if ( c != null ) {
                    sb.append(c.getProperties().get(c.getPid()));
                    sb.append('\n');
                }
            }
            final RunMode packageRM = launchpadFeature.getRunMode(new String[] {packageRunMode});
            if ( packageRM != null ) {
                final Configuration c = packageRM.getConfiguration(ModelConstants.CFG_LAUNCHPAD_BOOTSTRAP);
                if ( c != null ) {
                    sb.append(c.getProperties().get(c.getPid()));
                    sb.append('\n');
                }
            }
        }

        if ( sb.length() > 0 ) {
            final File file = new File(outputDir, BOOTSTRAP_FILE);
            getLog().debug(String.format("Creating bootstrap file at %s", file.getPath()));
            try {
                FileUtils.fileWrite(file, sb.toString());
            } catch ( final IOException ioe ) {
                throw new MojoExecutionException("Unable to write bootstrap file.", ioe);
            }
        }
    }

    /**
     * Return the base artifact
     */
    private Artifact getBaseArtifact(final Model model, final String classifier, final String type) throws MojoExecutionException {
        try {
            final org.apache.sling.provisioning.model.Artifact baseArtifact = ModelUtils.findBaseArtifact(model);

            final Artifact a = ModelUtils.getArtifact(this.project,  this.mavenSession, this.artifactHandlerManager, this.resolver,
                    baseArtifact.getGroupId(),
                    baseArtifact.getArtifactId(),
                    baseArtifact.getVersion(),
                    type,
                    classifier);
            if (a == null) {
                throw new MojoExecutionException(
                        String.format("Project doesn't have a base dependency of groupId %s and artifactId %s",
                                baseArtifact.getGroupId(), baseArtifact.getArtifactId()));
            }
            return a;
        } catch ( final MavenExecutionException mee) {
            throw new MojoExecutionException(mee.getMessage(), mee.getCause());
        }
    }

    /**
     * Unpack the base artifact
     */
    private void unpackBaseArtifact(final Model model, final File outputDirectory, final String packageRunMode)
     throws MojoExecutionException {
        final String classifier;
        final String type;
        if ( ModelConstants.RUN_MODE_STANDALONE.equals(packageRunMode) ) {
            classifier = BuildConstants.CLASSIFIER_APP;
            type = BuildConstants.TYPE_JAR;
        } else {
            classifier = BuildConstants.CLASSIFIER_WEBAPP;
            type = BuildConstants.TYPE_WAR;
        }
        final Artifact artifact = this.getBaseArtifact(model, classifier, type);
        unpack(artifact.getFile(), outputDirectory);
    }

    /**
     * Unpack a file
     */
    private void unpack(final File source, final File destination)
    throws MojoExecutionException {
        getLog().debug("Unpacking " + source.getPath() + " to\n  " + destination.getPath());
        try {
            destination.mkdirs();

            final UnArchiver unArchiver = archiverManager.getUnArchiver(source);

            unArchiver.setSourceFile(source);
            unArchiver.setDestDirectory(destination);

            unArchiver.extract();
        } catch (final NoSuchArchiverException e) {
            throw new MojoExecutionException("Unable to find archiver for " + source.getPath(), e);
        } catch (final ArchiverException e) {
            throw new MojoExecutionException("Unable to unpack " + source.getPath(), e);
        }
    }

    private String getPathForArtifact(final int startLevel, final String artifactName) {
        return getPathForArtifact(startLevel, artifactName, null, false);
    }

    /**
     * Get the relative path for an artifact.
     */
    private String getPathForArtifact(final int startLevel, final String artifactName, final RunMode rm, final boolean isBoot) {
        final Set<String> runModesList = new TreeSet<String>();
        if ( rm != null && rm.getNames() != null ) {
            for(final String mode : rm.getNames()) {
                runModesList.add(mode);
            }
        }
        final String runModeExt;
        if ( runModesList.size() == 0 || rm.isSpecial() ) {
            runModeExt = "";
        } else {
            final StringBuilder sb = new StringBuilder();
            for(final String n : runModesList ) {
                sb.append('.');
                sb.append(n);
            }
            runModeExt = sb.toString();
        }

        if ( isBoot ) {
            return String.format("%s/%s/1/%s", BASE_DESTINATION, BOOT_DIRECTORY,
                    artifactName);
        }
        return String.format("%s/%s%s/%s/%s", BASE_DESTINATION, ARTIFACTS_DIRECTORY,
                runModeExt,
                (startLevel == -1 ? 1 : startLevel),
                artifactName);
    }

    /**
     * Get the relative path for a configuration
     */
    private String getPathForConfiguration(final Configuration config, final RunMode rm) {
        final Set<String> runModesList = new TreeSet<String>();
        if (rm.getNames() != null ) {
            for(final String mode : rm.getNames()) {
                runModesList.add(mode);
            }
        }
        final String runModeExt;
        if ( runModesList.size() == 0 || rm.isSpecial() ) {
            runModeExt = "";
        } else {
            final StringBuilder sb = new StringBuilder();
            boolean first = true;
            for(final String n : runModesList ) {
                if ( first ) {
                    sb.append('/');
                    first = false;
                } else {
                    sb.append('.');
                }
                sb.append(n);
            }
            runModeExt = sb.toString();
        }

        final String mainName = (config.getFactoryPid() != null ? config.getFactoryPid() : config.getPid());
        final String alias = (config.getFactoryPid() != null ? "-" + config.getPid() : "");
        return String.format("%s/%s%s/%s%s.config", BASE_DESTINATION, CONFIG_DIRECTORY,
                runModeExt,
                mainName,
                alias);
    }

    /**
     * Replace \${var} with ${var}
     * @param text String with escaped variables
     * @return String with deescaped variables
     */
    private String deescapeVariablePlaceholders(String text) {
        if (text == null) {
            return null;
        }
        return text.replaceAll("\\\\\\$", "\\$");
    }

}