org.codehaus.mojo.nbm.CreateUpdateSiteMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.mojo.nbm.CreateUpdateSiteMojo.java

Source

/* ==========================================================================
 * Copyright 2003-2004 Mevenide Team
 *
 * 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.
 * =========================================================================
 */
package org.codehaus.mojo.nbm;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.DefaultArtifactRepository;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.artifact.resolver.ArtifactResolver;
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.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.archiver.gzip.GZipArchiver;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.netbeans.nbbuild.MakeUpdateDesc;

/**
 * Create the NetBeans auto update site definition.
 * @author <a href="mailto:mkleint@codehaus.org">Milos Kleint</a>
 *
 */
@Mojo(name = "autoupdate", defaultPhase = LifecyclePhase.PACKAGE, aggregator = true, requiresDependencyResolution = ResolutionScope.RUNTIME)
public class CreateUpdateSiteMojo extends AbstractNbmMojo implements Contextualizable {

    /**
     * output directory.
     */
    @Parameter(required = true, defaultValue = "${project.build.directory}")
    protected File outputDirectory;
    /**
     * autoupdate site xml file name.
     */
    @Parameter(defaultValue = "updates.xml", property = "maven.nbm.updatesitexml")
    protected String fileName;
    /**
     * A custom distribution base for the nbms in the update site.
     * If NOT defined, the update site will use a simple relative URL, which is generally what you want.
     * Defining it as "auto" will pick up the distribution URL from each NBM, which is generally wrong. 
     * See <code>distributionUrl</code> in nbm mojo for what url will be used in that case.
     * <p/>
     * The value is either a direct http protocol based URL that points to
     * the location under which all nbm files are located, or
     * <p/>
     * allows to create an update site based on maven repository content.
     * The resulting autoupdate site document can be uploaded as tar.gz to repository as well
     * as attached artifact to the 'nbm-application' project.
     * <br/>
     * Format: id::layout::url same as in maven-deploy-plugin
     * <br/>
     * with the 'default' and 'legacy' layouts. (maven2 vs maven1 layout)
     * <br/>
     * If the value doesn't contain :: characters,
     * it's assumed to be the flat structure and the value is just the URL.
     * 
     * @since 3.0 it's also possible to add remote repository as base
     */
    @Parameter(defaultValue = ".", property = "maven.nbm.customDistBase")
    private String distBase;

    /**
     * The Maven Project.
     *
     */
    @Parameter(required = true, readonly = true, property = "project")
    private MavenProject project;

    /**
     * If the executed project is a reactor project, this will contains the full list of projects in the reactor.
     */
    @Parameter(required = true, readonly = true, defaultValue = "${reactorProjects}")
    private List reactorProjects;

    /**
     * List of Ant style patterns on artifact GA (groupID:artifactID) that should be included in the update site.
     * Eg. org.netbeans.* matches all artifacts with any groupID starting with 'org.netbeans.',
     * org.*:api will match any artifact with artifactId of 'api' and groupId starting with 'org.'
     * @since 3.14
     */
    @Parameter
    private List<String> updateSiteIncludes;

    // <editor-fold defaultstate="collapsed" desc="Component parameters">

    @Component
    private ArtifactFactory artifactFactory;
    /**
     * Contextualized.
     */
    private PlexusContainer container;
    /**
     * Used for attaching the artifact in the project
     *
     */
    @Component
    private MavenProjectHelper projectHelper;

    @Component
    private ArtifactResolver artifactResolver;

    /**
     * Local maven repository.
     *
     */
    @Parameter(readonly = true, required = true, defaultValue = "${localRepository}")
    protected ArtifactRepository localRepository;

    // </editor-fold>

    public void execute() throws MojoExecutionException, MojoFailureException {
        Project antProject = registerNbmAntTasks();
        File nbmBuildDirFile = new File(outputDirectory, "netbeans_site");
        if (!nbmBuildDirFile.exists()) {
            nbmBuildDirFile.mkdirs();
        }

        boolean isRepository = false;
        if ("auto".equals(distBase)) {
            distBase = null;
        }
        ArtifactRepository distRepository = getDeploymentRepository(distBase, container, getLog());
        String oldDistBase = null;
        if (distRepository != null) {
            isRepository = true;
        } else {
            if (distBase != null && !distBase.contains("::")) {
                oldDistBase = distBase;
            }
        }

        if ("nbm-application".equals(project.getPackaging())) {
            @SuppressWarnings("unchecked")
            Set<Artifact> artifacts = project.getArtifacts();
            for (Artifact art : artifacts) {
                if (!matchesIncludes(art)) {
                    continue;
                }
                ArtifactResult res = turnJarToNbmFile(art, artifactFactory, artifactResolver, project,
                        localRepository);
                if (res.hasConvertedArtifact()) {
                    art = res.getConvertedArtifact();
                }

                if (art.getType().equals("nbm-file")) {
                    Copy copyTask = (Copy) antProject.createTask("copy");
                    copyTask.setOverwrite(true);
                    copyTask.setFile(art.getFile());
                    if (!isRepository) {
                        copyTask.setFlatten(true);
                        copyTask.setTodir(nbmBuildDirFile);
                    } else {
                        String path = distRepository.pathOf(art);
                        File f = new File(nbmBuildDirFile, path.replace('/', File.separatorChar));
                        copyTask.setTofile(f);
                    }
                    try {
                        copyTask.execute();
                    } catch (BuildException ex) {
                        throw new MojoExecutionException("Cannot merge nbm files into autoupdate site", ex);
                    }

                }
                if (res.isOSGiBundle()) {
                    // TODO check for bundles
                }
            }
            getLog().info("Created NetBeans module cluster(s) at " + nbmBuildDirFile.getAbsoluteFile());

        } else if (reactorProjects != null && reactorProjects.size() > 0) {

            Iterator it = reactorProjects.iterator();
            while (it.hasNext()) {
                MavenProject proj = (MavenProject) it.next();
                //TODO how to figure where the the buildDir/nbm directory is
                File moduleDir = proj.getFile().getParentFile();
                if (moduleDir != null && moduleDir.exists()) {
                    Copy copyTask = (Copy) antProject.createTask("copy");
                    if (!isRepository) {
                        FileSet fs = new FileSet();
                        File projOutputDirectory = new File(proj.getBuild().getDirectory());
                        fs.setDir(projOutputDirectory);
                        fs.createInclude().setName("*.nbm");
                        copyTask.addFileset(fs);
                        copyTask.setOverwrite(true);
                        copyTask.setFlatten(true);
                        copyTask.setTodir(nbmBuildDirFile);
                    } else {
                        File target = new File(proj.getBuild().getDirectory());
                        boolean has = false;
                        File[] fls = target.listFiles();
                        if (fls != null) {
                            for (File fl : fls) {
                                if (fl.getName().endsWith(".nbm")) {
                                    copyTask.setFile(fl);
                                    has = true;
                                    break;
                                }
                            }
                        }
                        if (!has) {
                            continue;
                        }
                        Artifact art = artifactFactory.createArtifact(proj.getGroupId(), proj.getArtifactId(),
                                proj.getVersion(), null, "nbm-file");
                        String path = distRepository.pathOf(art);
                        File f = new File(nbmBuildDirFile, path.replace('/', File.separatorChar));
                        copyTask.setTofile(f);
                    }
                    try {
                        copyTask.execute();
                    } catch (BuildException ex) {
                        throw new MojoExecutionException("Cannot merge nbm files into autoupdate site", ex);
                    }
                }
            }
        } else {
            throw new MojoExecutionException(
                    "This goal only makes sense on reactor projects or project with 'nbm-application' packaging.");

        }
        MakeUpdateDesc descTask = (MakeUpdateDesc) antProject.createTask("updatedist");
        File xmlFile = new File(nbmBuildDirFile, fileName);
        descTask.setDesc(xmlFile);
        if (oldDistBase != null) {
            descTask.setDistBase(oldDistBase);
        }
        if (distRepository != null) {
            descTask.setDistBase(distRepository.getUrl());
        }
        FileSet fs = new FileSet();
        fs.setDir(nbmBuildDirFile);
        fs.createInclude().setName("**/*.nbm");
        descTask.addFileset(fs);
        try {
            descTask.execute();
        } catch (BuildException ex) {
            throw new MojoExecutionException("Cannot create autoupdate site xml file", ex);
        }
        getLog().info("Generated autoupdate site content at " + nbmBuildDirFile.getAbsolutePath());

        try {
            GZipArchiver gz = new GZipArchiver();
            gz.addFile(xmlFile, fileName);
            File gzipped = new File(nbmBuildDirFile, fileName + ".gz");
            gz.setDestFile(gzipped);
            gz.createArchive();
            if ("nbm-application".equals(project.getPackaging())) {
                projectHelper.attachArtifact(project, "xml.gz", "updatesite", gzipped);
            }
        } catch (Exception ex) {
            throw new MojoExecutionException("Cannot create gzipped version of the update site xml file.", ex);
        }

    }

    private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile("(.+)::(.+)::(.+)");

    static ArtifactRepository getDeploymentRepository(String distBase, PlexusContainer container, Log log)
            throws MojoExecutionException, MojoFailureException {

        ArtifactRepository repo = null;

        if (distBase != null) {

            Matcher matcher = ALT_REPO_SYNTAX_PATTERN.matcher(distBase);

            if (!matcher.matches()) {
                if (!distBase.contains("::")) {
                    //backward compatibility gag.
                    return null;
                }
                throw new MojoFailureException(distBase, "Invalid syntax for repository.",
                        "Invalid syntax for alternative repository. Use \"id::layout::url\".");
            } else {
                String id = matcher.group(1).trim();
                String layout = matcher.group(2).trim();
                String url = matcher.group(3).trim();

                ArtifactRepositoryLayout repoLayout;
                try {
                    repoLayout = (ArtifactRepositoryLayout) container.lookup(ArtifactRepositoryLayout.ROLE, layout);
                } catch (ComponentLookupException e) {
                    throw new MojoExecutionException("Cannot find repository layout: " + layout, e);
                }

                repo = new DefaultArtifactRepository(id, url, repoLayout);
            }
        }
        return repo;
    }

    public void contextualize(Context context) throws ContextException {
        this.container = (PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY);
    }

    private boolean matchesIncludes(Artifact art) {
        if (updateSiteIncludes != null) {
            String s = art.getGroupId() + ":" + art.getArtifactId();
            for (String p : updateSiteIncludes) {
                //TODO optimize and only do once per execution.
                p = p.replace(".", "\\.").replace("*", ".*");
                Pattern patt = Pattern.compile(p);
                if (patt.matcher(s).matches()) {
                    return true;
                }
            }
            return false;
        }
        return true;
    }
}