/*
 * 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);
    }

    protected File getStandaloneOutputDirectory() {
        return new File(this.project.getBuild().getOutputDirectory());
    }

    /**
     * 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(null);
                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) {
                final 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 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());
        subsystemFile.getParentFile().mkdirs();

        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(null);
            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(null);
            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(null);
            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("\\\\\\$", "\\$");
    }

}