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