com.actility.maven.plugin.cocoon.GenerateKfCocoonMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.actility.maven.plugin.cocoon.GenerateKfCocoonMojo.java

Source

package com.actility.maven.plugin.cocoon;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * Licensed 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.
 */

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
import org.codehaus.plexus.archiver.util.DefaultFileSet;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;

/**
 * Goal which generate the init.xargs Knopflerfish init script.
 *
 * @goal generate-kf-cocoon
 *
 * @phase prepare-package
 */
public class GenerateKfCocoonMojo extends AbstractMojo {
    /**
     * POM
     *
     * @parameter expression="${project}"
     * @readonly
     * @required
     */
    private MavenProject project;

    /**
     * Firmware qualifier.
     *
     * @parameter alias="firmwareQualifier"
     */
    private String firmwareQualifier;

    /**
     * Firmware entries configuration.
     *
     * @parameter alias="firmwareEntriesConfiguration"
     */
    private String firmwareEntriesConfiguration;

    /**
     * Bundles configuration.
     *
     * @parameter alias="bundlesConfiguration"
     * @required
     */
    private String bundlesConfiguration;

    /**
     * Levels configuration.
     *
     * @parameter alias="levelsConfiguration"
     */
    private String levelsConfiguration;

    /**
     * Default location used for mojo unless overridden in ArtifactItem
     *
     * @parameter expression="${project.build.directory}"
     * @required
     */
    protected File buildDirectory;

    /**
     * Location of base KF directory.
     *
     * @parameter alias="kfBaseDirectory"
     * @required
     */
    private File kfBaseDirectory;

    /**
     * Location of Factory directory.
     *
     * @parameter alias="factoryDirectory"
     * @required
     */
    private File factoryDirectory;

    /**
     * Initial start level configuration.
     *
     * @parameter alias="initialStartLevel" default-value="7"
     */
    private int initialStartLevel;

    /**
     * Version prefix of the firmware file.
     *
     * @parameter alias="versionPrefix"
     * @required
     */
    private String versionPrefix;

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

    /**
     *
     * @parameter
     */
    private String classifier;

    private Map<String, Artifact> nameToDependency;
    private Map<String, Artifact> nameVersionToDependency;

    @Override
    public void execute() throws MojoExecutionException {
        try {
            if (!kfBaseDirectory.isDirectory()) {
                throw new MojoExecutionException("KF base directory does not exist: " + kfBaseDirectory);
            }
            if (!factoryDirectory.isDirectory()) {
                throw new MojoExecutionException("Factory directory does not eists: " + factoryDirectory);
            }
            getLog().debug("Read bundlesConfiguration: " + bundlesConfiguration);
            getLog().debug("Read kfBaseDirectory: " + kfBaseDirectory);
            getLog().debug("Read factoryDirectory: " + factoryDirectory);

            Set<Artifact> dependencies = project.getDependencyArtifacts();
            nameToDependency = new HashMap<String, Artifact>();
            for (Artifact artifact : dependencies) {
                nameToDependency.put(artifact.getGroupId() + "~" + artifact.getArtifactId(), artifact);
            }

            nameVersionToDependency = new HashMap<String, Artifact>();
            for (Artifact artifact : dependencies) {
                nameVersionToDependency.put(
                        artifact.getGroupId() + "~" + artifact.getArtifactId() + "~" + artifact.getVersion(),
                        artifact);
            }

            // Build levels configuration
            Map<Integer, LevelConfiguration> levelsConfigurations = buildLevelsConfiguration();
            // Build bundles configuration
            buildBundlesConfiguration(levelsConfigurations);
            // Build firmware entries configuration
            List<FirmwareEntryConfiguration> firmwareEntries = buildFirmwareEntriesConfiguration(
                    levelsConfigurations);
            // Build init.xargs
            buildInitXargs(levelsConfigurations);
            // Build firmware-manifest.properties
            buildFirmwareManifest(firmwareEntries, factoryDirectory, firmwareQualifier);
            // Copy cocoon bundles
            copyFirmwareEntries(firmwareEntries, factoryDirectory);
            // Build firmware file
            buildFirmwareFile(firmwareEntries, factoryDirectory, firmwareQualifier);
        } catch (RuntimeException e) {
            e.printStackTrace();
            throw e;
        }
    }

    private Map<Integer, LevelConfiguration> buildLevelsConfiguration() throws MojoExecutionException {
        Map<Integer, LevelConfiguration> levelsConfiguration = new TreeMap<Integer, LevelConfiguration>();
        String[] configs = StringUtils.split(this.levelsConfiguration, ",");
        for (String config : configs) {
            String realConfig = config.trim();
            LevelConfiguration levelConfig = new LevelConfiguration(StringUtils.split(realConfig, ":"));
            levelsConfiguration.put(levelConfig.getLevel(), levelConfig);
            getLog().debug("Read level configuration OK: " + realConfig);
        }

        return levelsConfiguration;
    }

    private void buildBundlesConfiguration(Map<Integer, LevelConfiguration> levelsConfiguration)
            throws MojoExecutionException {
        String[] configs = StringUtils.split(this.bundlesConfiguration, ",");
        for (String config : configs) {
            String realConfig = config.trim();
            BundleConfiguration bundleConfig = new BundleConfiguration(getLog(), nameToDependency, classifier,
                    StringUtils.split(realConfig, ":"));
            LevelConfiguration levelConfig = levelsConfiguration.get(bundleConfig.getStartLevel());
            if (levelConfig == null) {
                levelConfig = new LevelConfiguration(bundleConfig.getStartLevel());
                levelsConfiguration.put(bundleConfig.getStartLevel(), levelConfig);
            }
            levelConfig.addBundleConfiguration(bundleConfig);
            getLog().debug("Read bundle configuration OK: " + realConfig);
        }
    }

    private List<FirmwareEntryConfiguration> buildFirmwareEntriesConfiguration(
            Map<Integer, LevelConfiguration> levelsConfiguration) throws MojoExecutionException {
        List<FirmwareEntryConfiguration> firmwareEntriesConfiguration = new ArrayList<FirmwareEntryConfiguration>();
        for (LevelConfiguration levelConfig : levelsConfiguration.values()) {
            for (BundleConfiguration bundleConfig : levelConfig.getBundlesConfiguration()) {
                firmwareEntriesConfiguration.add(bundleConfig);
            }
        }

        if (this.firmwareEntriesConfiguration != null) {
            String[] configs = StringUtils.split(this.firmwareEntriesConfiguration, ",");
            for (String config : configs) {
                String realConfig = config.trim();
                firmwareEntriesConfiguration.add(new FirmwareEntryConfiguration(getLog(), nameVersionToDependency,
                        StringUtils.split(realConfig, ":")));
                getLog().debug("Read firmware entry configuration OK: " + realConfig);
            }
        }

        return firmwareEntriesConfiguration;
    }

    private void buildInitXargs(Map<Integer, LevelConfiguration> levelsConfiguration)
            throws MojoExecutionException {
        File initXargsFile = new File(kfBaseDirectory, "init.xargs");
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(initXargsFile), "ASCII"));

            // Headers
            out.write("#\n");
            out.write("# Generated cocoon init file\n");
            out.write("#\n");
            out.write("\n");
            out.write("# load common properties\n");
            out.write("-xargs props.xargs\n");
            out.write("\n");
            out.write("# Semicolon seprated list of base URLs for searching (completing)\n");
            out.write("# bundle URLs in \"-install URL\" command line options and in the console.\n");
            out.write("-Dorg.knopflerfish.gosg.jars=file:");
            out.write(getRelativePath(factoryDirectory, kfBaseDirectory));
            out.write("\n");
            out.write("\n");
            out.write("-init\n");
            out.write("\n");

            // Body
            for (LevelConfiguration levelConfig : levelsConfiguration.values()) {
                if (levelConfig.getDescription() != null) {
                    out.write("# ");
                    out.write(levelConfig.getDescription());
                    out.write("\n");
                }
                out.write("-initlevel ");
                out.write(String.valueOf(levelConfig.getLevel()));
                out.write("\n");

                for (BundleConfiguration bundleConfig : levelConfig.getBundlesConfiguration()) {
                    if (bundleConfig.isComment()) {
                        out.write("#");
                    }
                    out.write("-install ");
                    out.write(bundleConfig.getDestFile());
                    out.write("\n");
                }
                out.write("\n");
            }
            out.write("\n");

            out.write("-startlevel ");
            out.write(String.valueOf(initialStartLevel));
            out.write("\n");
            out.write("\n");
            out.write("\n");

            out.write("# Start of these bundles are delayed since this makes start\n");
            out.write("# order dependencies much easier\n");
            out.write("\n");

            for (LevelConfiguration levelConfig : levelsConfiguration.values()) {
                for (BundleConfiguration bundleConfig : levelConfig.getBundlesConfiguration()) {
                    if (bundleConfig.isComment()) {
                        out.write("#");
                    }
                    out.write("-start ");
                    out.write(bundleConfig.getDestFile());
                    out.write("\n");
                }
                out.write("\n");
            }
        } catch (IOException e) {
            throw new MojoExecutionException("IO problem while generating init.xargs file", e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                throw new MojoExecutionException("IO problem while closing init.xargs file", e);
            }
        }
    }

    private void buildFirmwareManifest(List<FirmwareEntryConfiguration> firmwareEntries, File destDir,
            String firmwareQualifier) throws MojoExecutionException {
        File firmwareManifestFile = new File(destDir, "firmware-manifest.properties");
        BufferedWriter out = null;
        int index = 0;
        try {

            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(firmwareManifestFile), "ASCII"));

            out.write("firmware.versionPrefix=");
            out.write(versionPrefix);
            out.write("\n");
            out.write("firmware.versionNumber=");
            Artifact artifact = project.getArtifact();
            out.write(MavenUtils.getOSGiVersion(artifact));
            // Add firmware extra qualifier to firmware.versionNumber
            if (firmwareQualifier != null) {
                if (StringUtils.isNotEmpty(artifact.getSelectedVersion().getQualifier())) {
                    out.write("_");
                } else {
                    out.write(".");
                }
                out.write(firmwareQualifier);
            }

            out.write("\n");
            out.write("\n");

            // part.{index}.id=
            // part.{index}.namespace=
            // part.{index}.name=
            // part.{index}.version=
            // part.{index}.fullname=
            // part.{index}.installationType=
            for (FirmwareEntryConfiguration firmwareEntry : firmwareEntries) {
                if (!firmwareEntry.isOneTime()) {
                    ++index;
                    String prefix = "";
                    if (firmwareEntry.isComment()) {
                        prefix += "#";
                    }
                    prefix += "part." + String.valueOf(index) + ".";

                    out.write(prefix + "id=");
                    out.write(firmwareEntry.getId());
                    out.write("\n");
                    out.write(prefix + "namespace=");
                    out.write(firmwareEntry.getNamespace());
                    out.write("\n");
                    out.write(prefix + "name=");
                    out.write(firmwareEntry.getName());
                    out.write("\n");
                    out.write(prefix + "version=");
                    out.write(firmwareEntry.getVersion());
                    out.write("\n");
                    out.write(prefix + "fullname=");
                    out.write(firmwareEntry.getDestFile());
                    out.write("\n");
                    out.write(prefix + "installationType=");
                    out.write(firmwareEntry.getInstallationType());
                    out.write("\n");
                    out.write("\n");
                }
            }
            out.write("\n");
        } catch (IOException e) {
            throw new MojoExecutionException("IO problem while generating firmware-manifest.properties file", e);
        } catch (OverConstrainedVersionException e) {
            throw new MojoExecutionException("Failed to retrieve project artifact version", e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                throw new MojoExecutionException("IO problem while closing firmware-manifest.properties file", e);
            }
        }
    }

    private void copyFirmwareEntries(List<FirmwareEntryConfiguration> firmwareEntries, File destDir)
            throws MojoExecutionException {
        for (FirmwareEntryConfiguration firmwareEntry : firmwareEntries) {
            copyFile(firmwareEntry.getArtifact().getFile(), new File(destDir, firmwareEntry.getDestFile()));
        }
    }

    private void copyFile(File artifact, File destFile) throws MojoExecutionException {
        try {
            getLog().info("Copying " + artifact.getAbsolutePath() + " to " + destFile);
            FileUtils.copyFile(artifact, destFile);
        } catch (Exception e) {
            throw new MojoExecutionException("Error copying artifact from " + artifact + " to " + destFile, e);
        }
    }

    private void buildFirmwareFile(List<FirmwareEntryConfiguration> firmwareEntries, File destDir,
            String firmwareQualifier) throws MojoExecutionException {
        StringBuffer destFileName = new StringBuffer();

        try {
            destFileName.append(project.getArtifactId()).append("-").append(project.getVersion());
            if (firmwareQualifier != null) {
                if (StringUtils.isNotEmpty(project.getArtifact().getSelectedVersion().getQualifier())) {
                    destFileName.append("_").append(firmwareQualifier);
                } else {
                    destFileName.append("-").append(firmwareQualifier);
                }
            }
            destFileName.append("-firmware.zip");
            File destFile = new File(buildDirectory, destFileName.toString());
            Archiver archiver = archiverManager.getArchiver(destFile);
            archiver.setDestFile(destFile);

            List<String> excludes = new ArrayList<String>();
            excludes.add("cfg/");
            for (FirmwareEntryConfiguration firmwareEntry : firmwareEntries) {
                if (firmwareEntry.isOneTime()) {
                    excludes.add(firmwareEntry.getDestFile());
                }
            }

            DefaultFileSet fileSet = new DefaultFileSet();
            fileSet.setDirectory(destDir);
            fileSet.setPrefix("");
            fileSet.setIncludes(null);
            fileSet.setExcludes(excludes.toArray(new String[excludes.size()]));
            fileSet.setIncludingEmptyDirectories(true);
            archiver.addFileSet(fileSet);

            archiver.createArchive();
        } catch (OverConstrainedVersionException e) {
            throw new MojoExecutionException("Cannot build firmware file", e);
        } catch (NoSuchArchiverException e) {
            throw new MojoExecutionException("Cannot build firmware file", e);
        } catch (ArchiverException e) {
            throw new MojoExecutionException("Cannot build firmware file", e);
        } catch (IOException e) {
            throw new MojoExecutionException("Cannot build firmware file", e);
        }
    }

    private String getRelativePath(File targetPath, File basePath) {
        String target = targetPath.toURI().normalize().getPath();
        String base = basePath.toURI().normalize().getPath();
        if (!target.endsWith("/")) {
            target = target + "/";
        }
        if (!base.endsWith("/")) {
            base = base + "/";
        }

        int maxIndex = target.length();
        if (base.length() < maxIndex) {
            maxIndex = base.length();
        }

        // Detect common parts
        int index = 0;
        while (index < maxIndex && base.charAt(index) == target.charAt(index)) {
            ++index;
        }

        if (index == target.length()) {
            StringBuffer result = new StringBuffer();
            index = base.indexOf('/');
            while (index != -1) {
                index = base.indexOf('/', index + 1);
                result.append("../");
            }
            return result.toString();
        } else if (index == base.length()) {
            return target.substring(index);
        } else if (index > 0) {
            target = target.substring(index);
            base = base.substring(index);
        }

        StringBuffer result = new StringBuffer();
        index = base.indexOf('/');
        while (index != -1) {
            index = base.indexOf('/', index + 1);
            result.append("../");
        }
        result.append(target);

        return result.toString();
    }
}