Java tutorial
/* ========================================================================== * 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; } }