Package io.fabric8.maven

Source Code of io.fabric8.maven.ZipMojo

/**
*  Copyright 2005-2014 Red Hat, Inc.
*
*  Red Hat 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 io.fabric8.maven;

import io.fabric8.utils.Files;
import io.fabric8.utils.Objects;
import io.fabric8.utils.Strings;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
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.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.Invoker;
import org.apache.maven.shared.invoker.MavenInvocationException;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Generates a ZIP file of the App for the current maven project.
*/
@Mojo(name = "zip", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE)
public class ZipMojo extends AbstractFabric8Mojo {

    /**
     * Name of the directory used to create the app configuration zip
     */
    @Parameter(property = "fabric8.zip.buildDir", defaultValue = "${project.build.directory}/generated-app")
    private File buildDir;

    /**
     * Name of the aggregated app zip file
     */
    @Parameter(property = "fabric8.aggregated.zip.outFile", defaultValue = "${project.build.directory}/${project.artifactId}-${project.version}-app.zip")
    private File aggregatedZipOutputFile;

    @Component
    private MavenProjectHelper projectHelper;

    @Parameter(defaultValue = "${project.distributionManagementArtifactRepository}", readonly = true, required = true)
    private ArtifactRepository deploymentRepository;

    /**
     * The artifact type for attaching the generated app zip file to the project
     */
    @Parameter(property = "fabric8.zip.artifactType", defaultValue = "zip")
    private String artifactType = "zip";

    /**
     * The artifact classifier for attaching the generated app zip file to the project
     */
    @Parameter(property = "fabric8.zip.artifactClassifier", defaultValue = "app")
    private String artifactClassifier = "app";

    /**
     * Files to be excluded
     */
    @Parameter(property = "fabric8.excludedFiles", defaultValue = "io.fabric8.agent.properties")
    private String[] filesToBeExcluded;

    /**
     * The projects in the reactor.
     */
    @Parameter(defaultValue = "${reactorProjects}")
    private List<MavenProject> reactorProjects;

    /**
     * Name of the directory used to create the app zip files in each reactor project when creating an aggregated zip
     * for all the {@link #reactorProjects}
     */
    @Parameter(property = "fabric8.fullzip.reactorProjectOutputPath", defaultValue = "target/generated-app")
    private String reactorProjectOutputPath;

    /**
     * The folder used for defining project specific files
     */
    @Parameter(property = "appConfigDir", defaultValue = "${basedir}/src/main/fabric8")
    protected File appConfigDir;

    /**
     * Whether or not we should upload the project readme file if no specific readme file exists in the {@link #appConfigDir}
     */
    @Parameter(property = "fabric8.includeReadMe", defaultValue = "true")
    protected boolean includeReadMe;

    /**
     * If provided then any links in the readme.md files will be replaced to include the given prefix
     */
    @Parameter(property = "fabric8.replaceReadmeLinksPrefix")
    protected String replaceReadmeLinksPrefix;

    /**
     * Provides the resource name of the icon to use; found using the current classpath (including the ones shippped inside the maven plugin).
     */
    @Parameter(property = "fabric8.iconRef")
    protected String iconRef;

    /**
     * Whether or not we should generate a <code>Summary.md</code> file from the pom.xml &lt;description&gt; element text value.
     */
    @Parameter(property = "fabric8.generateSummaryFile", defaultValue = "true")
    protected boolean generateSummaryFile;

    /**
     * Whether or not we should generate a <code>fabric8.properties</code> file from the pom.xml.
     */
    @Parameter(property = "fabric8.generateAppPropertiesFile", defaultValue = "true")
    protected boolean generateAppPropertiesFile;

    /**
     * The name of the path inside the zip where the app is generated.
     */
    @Parameter(property = "fabric8.pathInZip", defaultValue = "${project.artifactId}")
    protected String pathInZip;


    /**
     * Whether or not we should ignoreProject this maven project from this goal
     */
    @Parameter(property = "fabric8.ignoreProject", defaultValue = "false")
    private boolean ignoreProject;

    /**
     * The Maven Session.
     *
     * @parameter expression="${session}"
     * @required
     * @readonly
     */
    protected MavenSession session;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            if (isIgnoreProject()) return;

            boolean generatingAggregatedZip = false;
            if (reactorProjects != null) {
                List<MavenProject> pomZipProjects = new ArrayList<>();
                List<MavenProject> fabricZipGoalProjects = new ArrayList<>();
                for (MavenProject reactorProject : reactorProjects) {
                    if (isPom(reactorProject)) {
                        pomZipProjects.add(reactorProject);
                    }

                    List<Plugin> buildPlugins = reactorProject.getBuildPlugins();
                    for (Plugin buildPlugin : buildPlugins) {
                        String artifactId = buildPlugin.getArtifactId();
                        // TODO I guess we could try find if the "zip" goal is being invoked?
                        if ("fabric8-maven-plugin".equals(artifactId)) {
                            // TODO should we only consider reactorProjects which have a fabric8:zip goal?
                            Object goals = buildPlugin.getGoals();
                            boolean hasZipGoal = goals != null && goals.toString().contains("zip");
                            List<PluginExecution> executions = buildPlugin.getExecutions();
                            for (PluginExecution execution : executions) {
                                List<String> execGoals = execution.getGoals();
                                if (execGoals.contains("zip")) {
                                    hasZipGoal = true;
                                }
                            }
                            getLog().debug("project " + reactorProject.getArtifactId() + " has zip goal: " + hasZipGoal);

                            fabricZipGoalProjects.add(reactorProject);
                        }
                    }
                }

                // we want a list of projects which has a parent that has a zip goal too
                // as that helps us detect the 'last' project when we do a full build from the entire project
                MavenProject project = getProject();
                MavenProject parentProject = project.getParent();
                List<MavenProject> projectsWithSameParent = new ArrayList<>();

                for (MavenProject zipGoalProject : fabricZipGoalProjects) {
                    MavenProject zipGoalProjectParent = zipGoalProject.getParent();
                    if (parentProject != null && Objects.equal(parentProject, zipGoalProjectParent)) {
                        projectsWithSameParent.add(zipGoalProject);
                    }
                }
                MavenProject rootProject = null;
                int projectsWithSameParentSize = projectsWithSameParent.size();
                if (projectsWithSameParentSize > 1) {
                    MavenProject lastProject = projectsWithSameParent.get(projectsWithSameParentSize - 1);
                    if (Objects.equal(lastProject, project)) {
                        rootProject = parentProject;
                    }
                }

                if (rootProject != null) {
                    getLog().info("");
                    getLog().info("Creating aggregated app zip");
                    getLog().info("built the last fabric8:zip project so generating a combined zip for all " + projectsWithSameParentSize + " projects with a fabric8:zip goal: " + projectsWithSameParent);

                    getLog().info("Choosing root project " + rootProject.getArtifactId() + " for generation of aggregated zip");
                    generateAggregatedZip(rootProject, fabricZipGoalProjects, projectsWithSameParent);
                    generatingAggregatedZip = true;
                }
            }
            if (!generatingAggregatedZip && !isPom(getProject())) {
                generateZip();
            } else {
                getLog().info("Not generating a zip right now - waiting until we generate the aggregated zip for all sub projects");
            }
        } catch (MojoFailureException e) {
            throw e;
        } catch (MojoExecutionException e) {
            throw e;
        } catch (Exception e) {
            throw new MojoExecutionException("Error executing", e);
        }
    }

    protected void generateAggregatedZip(MavenProject rootProject, List<MavenProject> reactorProjects, List<MavenProject> pomZipProjects) throws IOException, MojoExecutionException {
        File projectBaseDir = rootProject.getBasedir();
        String rootProjectGroupId = rootProject.getGroupId();
        String rootProjectArtifactId = rootProject.getArtifactId();
        String rootProjectVersion = rootProject.getVersion();

        String aggregatedZipFileName = "target/" + rootProjectArtifactId + "-" + rootProjectVersion + "-app.zip";
        File projectOutputFile = new File(projectBaseDir, aggregatedZipFileName);
        getLog().info("Generating " + projectOutputFile.getAbsolutePath() + " from root project " + rootProjectArtifactId);
        File projectBuildDir = new File(projectBaseDir, reactorProjectOutputPath);

        if (projectOutputFile.exists()) {
            projectOutputFile.delete();
        }
        createAggregatedZip(projectBaseDir, projectBuildDir, reactorProjectOutputPath, projectOutputFile,
                includeReadMe, pomZipProjects);
        if (rootProject.getAttachedArtifacts() != null) {
            // need to remove existing as otherwise we get a WARN
            Artifact found = null;
            for (Artifact artifact : rootProject.getAttachedArtifacts()) {
                if (artifactClassifier != null && artifact.hasClassifier() && artifact.getClassifier().equals(artifactClassifier)) {
                    found = artifact;
                    break;
                }
            }
            if (found != null) {
                rootProject.getAttachedArtifacts().remove(found);
            }
        }

        getLog().info("Attaching aggregated zip " + projectOutputFile + " to root project " + rootProject.getArtifactId());
        projectHelper.attachArtifact(rootProject, artifactType, artifactClassifier, projectOutputFile);

        // if we are doing an install goal, then also install the aggregated zip manually
        // as maven will install the root project first, and then build the reactor projects, and at this point
        // it does not help to attach artifact to root project, as those artifacts will not be installed
        // so we need to install manually
        if (rootProject.hasLifecyclePhase("install")) {
            getLog().info("Installing aggregated zip " + projectOutputFile);
            InvocationRequest request = new DefaultInvocationRequest();
            request.setBaseDirectory(rootProject.getBasedir());
            request.setPomFile(new File("./pom.xml"));
            request.setGoals(Collections.singletonList("install:install-file"));
            request.setRecursive(false);
            request.setInteractive(false);

            Properties props = new Properties();
            props.setProperty("file", aggregatedZipFileName);
            props.setProperty("groupId", rootProjectGroupId);
            props.setProperty("artifactId", rootProjectArtifactId);
            props.setProperty("version", rootProjectVersion);
            props.setProperty("classifier", "app");
            props.setProperty("packaging", "zip");
            request.setProperties(props);

            getLog().info("Installing aggregated zip using: mvn install:install-file" + serializeMvnProperties(props));
            Invoker invoker = new DefaultInvoker();
            try {
                InvocationResult result = invoker.execute(request);
                if (result.getExitCode() != 0) {
                    throw new IllegalStateException("Error invoking Maven goal install:install-file");
                }
            } catch (MavenInvocationException e) {
                throw new MojoExecutionException("Error invoking Maven goal install:install-file", e);
            }
        }

        if (rootProject.hasLifecyclePhase("deploy")) {
            getLog().info("Deploying aggregated zip " + projectOutputFile + " to root project " + rootProject.getArtifactId());

            InvocationRequest request = new DefaultInvocationRequest();
            request.setBaseDirectory(rootProject.getBasedir());
            request.setPomFile(new File("./pom.xml"));
            request.setGoals(Collections.singletonList("deploy:deploy-file"));
            request.setRecursive(false);
            request.setInteractive(false);

            Properties props = new Properties();
            props.setProperty("file", aggregatedZipFileName);
            props.setProperty("groupId", rootProjectGroupId);
            props.setProperty("artifactId", rootProjectArtifactId);
            props.setProperty("version", rootProjectVersion);
            props.setProperty("classifier", "app");
            props.setProperty("packaging", "zip");
            props.setProperty("url", deploymentRepository.getUrl());
            props.setProperty("repositoryId", deploymentRepository.getId());
            request.setProperties(props);

            getLog().info("Deploying aggregated zip using: mvn deploy:deploy-file" + serializeMvnProperties(props));
            Invoker invoker = new DefaultInvoker();
            try {
                InvocationResult result = invoker.execute(request);
                if (result.getExitCode() != 0) {
                    throw new IllegalStateException("Error invoking Maven goal deploy:deploy-file");
                }
            } catch (MavenInvocationException e) {
                throw new MojoExecutionException("Error invoking Maven goal deploy:deploy-file", e);
            }
        }
    }

    protected void generateZip() throws DependencyTreeBuilderException, MojoExecutionException, IOException,
            MojoFailureException {

        File appBuildDir = buildDir;
        if (Strings.isNotBlank(pathInZip)) {
            appBuildDir = new File(buildDir, pathInZip);
        }
        appBuildDir.mkdirs();

        boolean hasConfigDir = appConfigDir.isDirectory();
        if (hasConfigDir) {
            copyAppConfigFiles(appBuildDir, appConfigDir);

        } else {
            getLog().info("The app configuration files directory " + appConfigDir + " doesn't exist, so not copying any additional project documentation or configuration files");
        }
        MavenProject project = getProject();

        if (!ignoreProject) {
            File kubernetesJson = getKubernetesJson();
            if (kubernetesJson != null && kubernetesJson.isFile() && kubernetesJson.exists()) {
                    File jsonFile = new File(appBuildDir, "kubernetes.json");
                    jsonFile.getParentFile().mkdirs();
                    Files.copy(kubernetesJson, jsonFile);
                }

            // TODO if no iconRef is specified we could try guess based on the project?

            // lets check if we can use an icon reference
            if (Strings.isNotBlank(iconRef)) {
                File[] icons = appBuildDir.listFiles(new FilenameFilter() {
                    @Override
                    public boolean accept(File dir, String name) {
                        if (name == null) {
                            return false;
                        }
                        String lower = name.toLowerCase();
                        return lower.startsWith("icon.") &&
                                (lower.endsWith(".svg") || lower.endsWith(".png") || lower.endsWith(".gif") || lower.endsWith(".jpg") || lower.endsWith(".jpeg"));
                    }
                });
                if (icons == null || icons.length == 0) {
                    // lets copy the iconRef
                    InputStream in = loadPluginResource(iconRef);
                    if (in == null) {
                        getLog().warn("Could not find icon: " + iconRef + " on the ClassPath!");
                    } else {
                        String fileName = "icon." + Files.getFileExtension(iconRef);
                        File outFile = new File(appBuildDir, fileName);
                        Files.copy(in, new FileOutputStream(outFile));
                        getLog().info("Generated icon file " + outFile + " from icon reference: " + iconRef);
                    }
                }
            }

        }

        // lets only generate a app zip if we have a requirement (e.g. we're not a parent pom packaging project) and
        // we have defined some configuration files or dependencies
        // to avoid generating dummy apps for parent poms
        if (hasConfigDir || !ignoreProject) {

            if (includeReadMe) {
                copyReadMe(project.getFile().getParentFile(), appBuildDir);
            }

            if (generateSummaryFile) {
                String description = project.getDescription();
                if (Strings.isNotBlank(description)) {
                    File summaryMd = new File(appBuildDir, "Summary.md");
                    summaryMd.getParentFile().mkdirs();
                    if (!summaryMd.exists()) {
                        byte[] bytes = description.getBytes();
                        Files.copy(new ByteArrayInputStream(bytes), new FileOutputStream(summaryMd));
                    }
                }
            }

            if (generateAppPropertiesFile) {
                String name = project.getName();
                if (Strings.isNullOrBlank(name)) {
                    name = project.getArtifactId();
                }
                String description = project.getDescription();
                Properties appProperties = new Properties();
                appProperties.put("name", name);
                if (Strings.isNotBlank(description)) {
                    appProperties.put("description", description);
                }
                appProperties.put("groupId", project.getGroupId());
                appProperties.put("artifactId", project.getArtifactId());
                appProperties.put("version", project.getVersion());
                File appPropertiesFile = new File(appBuildDir, "fabric8.properties");
                appPropertiesFile.getParentFile().mkdirs();
                if (!appPropertiesFile.exists()) {
                    appProperties.store(new FileWriter(appPropertiesFile), "Fabric8 Properties");
                }
            }

            File outputZipFile = getZipFile();
            Zips.createZipFile(getLog(), buildDir, outputZipFile);

            projectHelper.attachArtifact(project, artifactType, artifactClassifier, outputZipFile);
            getLog().info("Created app zip file: " + outputZipFile);
        }
    }


    protected static File copyReadMe(File src, File appBuildDir) throws IOException {
        File[] files = src.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.toLowerCase(Locale.ENGLISH).startsWith("readme.");
            }
        });
        if (files != null && files.length == 1) {
            File readme = files[0];
            File outFile = new File(appBuildDir, readme.getName());
            Files.copy(readme, outFile);
            return outFile;
        }

        return null;
    }

    private String getReadMeFileKey(String relativePath) {
        String answer = relativePath;

        if (Strings.isNullOrBlank(answer)) {
            return "<root>";
        }

        // remove leading path which can be either unix or windows style
        int pos = relativePath.indexOf('/');
        int pos2 = relativePath.indexOf('\\');
        if (pos > 0 && pos2 > 0) {
            pos = Math.max(pos, pos2);
        } else if (pos2 > 0) {
            pos = pos2;
        }
        if (pos > -1) {
            answer = relativePath.substring(pos);
        }

        // and remove any leading path separators
        answer = Files.stripLeadingSeparator(answer);

        if (Strings.isNullOrBlank(answer)) {
            answer = "<root>";
        }
        return answer;
    }

    /**
     * Replacing github links with fabric apps links for our quickstarts
     */
    protected String replaceGithubLinks(Set<String> names, String relativePath, String line) {
        boolean changed = false;
        Pattern pattern = Pattern.compile("\\[(.*?)\\]\\((.*?)\\)");
        Matcher matcher = pattern.matcher(line);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String s2 = matcher.group(2);
            if (s2.startsWith("http:") || s2.startsWith("https:")) {
                // leave it as-is
                matcher.appendReplacement(sb, "[$1]($2)");
            } else {
                if (names.contains(s2) || names.contains(relativePath + s2) || names.contains(relativePath + "/" + s2)) {
                    // need to ensure path is app friendly
                    s2 = s2;
                    if (relativePath != null && !"<root>".equals(relativePath)) {
                        s2 = addToPath(relativePath, s2);
                    }
                    // its a directory
                    matcher.appendReplacement(sb, "[$1](" + replaceReadmeLinksPrefix + s2 + ")");
                } else {
                    // need to ensure path is app friendly
                    s2 = s2;
                    if (relativePath != null && !"<root>".equals(relativePath)) {
                        s2 = addToPath(relativePath, s2);
                    }
                    // its a app
                    matcher.appendReplacement(sb, "[$1](" + replaceReadmeLinksPrefix + s2 + ".app)");
                }
                changed = true;
            }
        }
        matcher.appendTail(sb);
        if (changed) {
            return sb.toString();
        } else {
            return null;
        }
    }

    private static String addToPath(String path, String add) {
        if (add.startsWith("/") || path.endsWith("/")) {
            return path + add;
        } else {
            return path + "/" + add;
        }
    }

    protected void createAggregatedZip(File projectBaseDir, File projectBuildDir,
                                       String reactorProjectOutputPath, File projectOutputFile,
                                       boolean includeReadMe, List<MavenProject> pomZipProjects) throws IOException {
        projectBuildDir.mkdirs();

        for (MavenProject reactorProject : pomZipProjects) {
            // ignoreProject the execution root which just aggregates stuff
            if (!reactorProject.isExecutionRoot()) {
                Log log = getLog();

                // TODO allow the project nesting to be defined via a property?
                String relativePath = getChildProjectRelativePath(projectBaseDir, reactorProject);
                File outDir = new File(projectBuildDir, relativePath);
                combineAppFilesToFolder(reactorProject, outDir, log, reactorProjectOutputPath);
            }
        }

        // we may want to include readme files for pom projects
        if (includeReadMe) {

            Map<String, File> pomNames = new HashMap<String, File>();

            for (MavenProject pomProject : pomZipProjects) {
                File src = pomProject.getFile().getParentFile();
                String relativePath = getChildProjectRelativePath(projectBaseDir, pomProject);
                File outDir = new File(projectBuildDir, relativePath);
                File copiedFile = copyReadMe(src, outDir);

                if (copiedFile != null) {
                    String key = getReadMeFileKey(relativePath);
                    pomNames.put(key, copiedFile);
                }
            }

            if (replaceReadmeLinksPrefix != null) {

                // now parse each readme file and replace github links
                for (Map.Entry<String, File> entry : pomNames.entrySet()) {
                    File file = entry.getValue();
                    String key = entry.getKey();

                    boolean changed = false;
                    List<String> lines = Files.readLines(file);
                    for (int i = 0; i < lines.size(); i++) {
                        String line = lines.get(i);
                        String newLine = replaceGithubLinks(pomNames.keySet(), key, line);
                        if (newLine != null) {
                            lines.set(i, newLine);
                            changed = true;
                        }
                    }
                    if (changed) {
                        Files.writeLines(file, lines);
                        getLog().info("Replaced github links to fabric apps in reaadme file: " + file);
                    }
                }
            }
        }

        Zips.createZipFile(getLog(), projectBuildDir, projectOutputFile);
        String relativePath = Files.getRelativePath(projectBaseDir, projectOutputFile);
        while (relativePath.startsWith("/")) {
            relativePath = relativePath.substring(1);
        }
        getLog().info("Created app zip file: " + relativePath);
    }

    protected String getChildProjectRelativePath(File projectBaseDir, MavenProject pomProject) throws IOException {
        // must include first dir as prefix
        String root = projectBaseDir.getName();
        String relativePath = Files.getRelativePath(projectBaseDir, pomProject.getBasedir());
        relativePath = root + File.separator + relativePath;
        return relativePath;
    }


    /**
     * Combines any files from the appSourceDir into the output directory
     */
    public static void appendAppConfigFiles(File appSourceDir, File outputDir) throws IOException {
        if (appSourceDir.exists() && appSourceDir.isDirectory()) {
            File[] files = appSourceDir.listFiles();
            if (files != null) {
                outputDir.mkdirs();
                for (File file : files) {
                    File outFile = new File(outputDir, file.getName());
                    if (file.isDirectory()) {
                        appendAppConfigFiles(file, outFile);
                    } else {
                        if (outFile.exists() && file.getName().endsWith(".properties")) {
                            System.out.println("Combining properties: file " + file.getAbsolutePath());
                            combinePropertiesFiles(file, outFile);
                        } else {
                            System.out.println("Copying file " + file.getAbsolutePath());
                            Files.copy(file, outFile);
                        }
                    }
                }
            }
        }
    }


    protected static boolean isFile(File file) {
        return file != null && file.exists() && file.isFile();
    }

    public static void combineAppFilesToFolder(MavenProject reactorProject, File buildDir, Log log, String reactorProjectOutputPath) throws IOException {
        File basedir = reactorProject.getBasedir();
        if (!basedir.exists()) {
            log.warn("No basedir " + basedir.getAbsolutePath() + " for project + " + reactorProject);
            return;
        }
        File outDir = new File(basedir, reactorProjectOutputPath);
        if (!outDir.exists()) {
            log.warn("No app output dir at: " + outDir.getAbsolutePath() + " for project + " + reactorProject + " so ignoring this project.");
            return;
        }
        log.info("Copying apps from " + outDir.getAbsolutePath() + " into the output directory: " + buildDir);
        appendAppConfigFiles(outDir, buildDir);
    }

    /**
     * For 2 properties files the source and dest file, lets combine the values so that all the values of the sourceFile are in the dest file
     */
    public static void combinePropertiesFiles(File sourceFile, File destFile) throws IOException {
        Properties source = loadProperties(sourceFile);
        Properties dest = loadProperties(destFile);
        Set<Map.Entry<Object, Object>> entries = source.entrySet();
        for (Map.Entry<Object, Object> entry : entries) {
            Object key = entry.getKey();
            Object value = entry.getValue();
            if (key != null && value != null) {
                String keyText = key.toString();
                String valueText = value.toString();
                String oldValue = dest.getProperty(keyText);
                if (oldValue == null || oldValue.trim().length() == 0) {
                    dest.setProperty(keyText, valueText);
                } else {
                    if (oldValue.contains(valueText)) {
                        // we've already added it so ignoreProject!
                    } else {
                        String newValue = oldValue + " " + valueText;
                        dest.setProperty(keyText, newValue);
                    }
                }
            }
        }
        dest.store(new FileWriter(destFile), "Generated by fabric8:full-zip plugin at " + new Date());
    }

    private static Properties loadProperties(File file) throws IOException {
        Properties answer = new Properties();
        answer.load(new FileReader(file));
        return answer;
    }

    public static boolean notEmpty(List<?> list) {
        return list != null && !list.isEmpty();
    }

    /**
     * Copies any local configuration files into the app directory
     */
    protected void copyAppConfigFiles(File appBuildDir, File appConfigDir) throws IOException {

        File[] files = appConfigDir.listFiles();

        if (files != null) {
            appBuildDir.mkdirs();
            for (File file : files) {
                if (!toBeExclude(file.getName())) {
                    File outFile = new File(appBuildDir, file.getName());
                    if (file.isDirectory()) {
                        copyAppConfigFiles(outFile, file);
                    } else {
                        Files.copy(file, outFile);
                    }
                }
            }
        }

    }

    protected ArrayList<String> removePath(List<String> filesToBeExcluded) {
        ArrayList<String> fileName = new ArrayList<String>();
        for (String name : filesToBeExcluded) {
            int pos = name.lastIndexOf("/");
            if (pos > 0) {
                String fname = name.substring(0, pos);
                fileName.add(fname);
            }
        }
        return fileName;
    }

    protected boolean toBeExclude(String fileName) {
        List excludedFilesList = Arrays.asList(filesToBeExcluded);
        Boolean result = excludedFilesList.contains(fileName);
        return result;
    }


    protected String escapeAgentPropertiesKey(String text) {
        return text.replaceAll("\\:", "\\\\:");
    }

    protected String escapeAgentPropertiesValue(String text) {
        return escapeAgentPropertiesKey(text);
    }

    protected static String leadingSlash(String path) {
        if (path.startsWith("/")) {
            return path;
        } else {
            return "/" + path;
        }
    }

    private String serializeMvnProperties(Properties properties) {
        StringBuilder sb = new StringBuilder();
        if (properties != null) {
            for (Iterator it = properties.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry entry = (Map.Entry) it.next();

                String key = (String) entry.getKey();
                String value = (String) entry.getValue();

                sb.append(" -D").append(key).append('=').append(value);
            }
        }
        return sb.toString();
    }

}
TOP

Related Classes of io.fabric8.maven.ZipMojo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.