package org.ops4j.pax.construct.bundle; /* * Copyright 2007 Stuart McCulloch * * 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.File; import java.io.IOException; import java.util.List; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.ops4j.pax.construct.util.BndUtils; import org.ops4j.pax.construct.util.BndUtils.Bnd; import org.ops4j.pax.construct.util.PomUtils; import org.ops4j.pax.construct.util.PomUtils.Pom; /** * Embed a jarfile inside a bundle project * * <code><pre> * mvn pax:embed-jar [-DgroupId=...] -DartifactId=... [-Dversion=...] * </pre></code> * * @goal embed-jar * @aggregator true * * @requiresProject false */ public class EmbedJarMojo extends AbstractMojo { /** * Component factory for Maven artifacts * * @component */ private ArtifactFactory m_factory; /** * Component for resolving Maven metadata * * @component */ private ArtifactMetadataSource m_source; /** * List of remote Maven repositories for the containing project. * * @parameter expression="${project.remoteArtifactRepositories}" * @required * @readonly */ private List m_remoteRepos; /** * The local Maven repository for the containing project. * * @parameter expression="${localRepository}" * @required * @readonly */ private ArtifactRepository m_localRepo; /** * The groupId of the jar to be embedded. * * @parameter expression="${groupId}" */ private String groupId; /** * The artifactId of the jar to be embedded. * * @parameter expression="${artifactId}" * @required */ private String artifactId; /** * The version of the jar to be embedded. * * @parameter expression="${version}" */ private String version; /** * When true, unpack the jar inside the bundle. * * @parameter expression="${unpack}" */ private boolean unpack; /** * The -exportcontents directive for this bundle, see <a href="http://aqute.biz/Code/Bnd#directives">Bnd docs</a>. * * @parameter expression="${exportContents}" */ private String exportContents; /** * The directory containing the POM to be updated. * * @parameter expression="${targetDirectory}" default-value="${project.basedir}" */ private File targetDirectory; /** * When true, overwrite matching directives in the 'osgi.bnd' file. * * @parameter expression="${overwrite}" */ private boolean overwrite; /** * {@inheritDoc} */ public void execute() throws MojoExecutionException { populateMissingFields(); updatePomDependencies(); updateBndInstructions(); } /** * Populate missing fields with information from the Maven repository * * @throws MojoExecutionException */ private void populateMissingFields() throws MojoExecutionException { if( PomUtils.isEmpty( groupId ) ) { // this is a common assumption groupId = artifactId; } if( PomUtils.needReleaseVersion( version ) ) { Artifact artifact = m_factory.createBuildArtifact( groupId, artifactId, "RELEASE", "jar" ); version = PomUtils.getReleaseVersion( artifact, m_source, m_remoteRepos, m_localRepo, null ); } } /** * Add compile-time dependency to get the jarfile, mark it optional so it's not included in transitive dependencies * * @throws MojoExecutionException */ private void updatePomDependencies() throws MojoExecutionException { Pom pom; try { pom = PomUtils.readPom( targetDirectory ); } catch( IOException e ) { throw new MojoExecutionException( "Cannot execute command." + " It requires a project with an existing pom.xml, but the build is not using one." ); } if( !pom.isBundleProject() ) { throw new MojoExecutionException( "Cannot embed jar inside non-bundle project" ); } // new dependency to fetch the jarfile Dependency dependency = new Dependency(); dependency.setGroupId( groupId ); dependency.setArtifactId( artifactId ); dependency.setVersion( version ); dependency.setScope( Artifact.SCOPE_COMPILE ); // limit transitive nature dependency.setOptional( true ); String id = groupId + ':' + artifactId + ':' + version; getLog().info( "Embedding " + id + " in " + pom ); pom.addDependency( dependency, overwrite ); try { pom.write(); } catch( IOException e1 ) { throw new MojoExecutionException( "Problem writing Maven POM: " + pom.getFile() ); } } /** * Add Bnd instructions to embed jarfile, and update -exportcontents directive if necessary * * @throws MojoExecutionException */ private void updateBndInstructions() throws MojoExecutionException { Bnd bnd; try { bnd = BndUtils.readBnd( targetDirectory ); } catch( IOException e ) { throw new MojoExecutionException( "Problem reading Bnd file: " + targetDirectory + "/osgi.bnd" ); } final String embedKey = artifactId + ";groupId=" + groupId; String embedDependency = bnd.getInstruction( "Embed-Dependency" ); embedDependency = addEmbedClause( embedKey, embedDependency ); bnd.setInstruction( "Embed-Dependency", embedDependency, true ); if( exportContents != null ) { bnd.setInstruction( "-exportcontents", exportContents, overwrite ); } try { bnd.write(); } catch( IOException e ) { throw new MojoExecutionException( "Problem writing Bnd file: " + bnd.getFile() ); } } /** * @param embedKey partial clause identifying jarfile to embed * @param embedDependency comma separated list of clauses * @return updated Embed-Dependency instruction */ private String addEmbedClause( String embedKey, String embedDependency ) { final String embedClause = embedKey + ";inline=" + unpack; if( null == embedDependency ) { return embedClause; } StringBuffer buf = new StringBuffer(); String[] clauses = embedDependency.split( "," ); for( int i = 0; i < clauses.length; i++ ) { final String c = clauses[i].trim(); // remove any clauses matching the one we're adding if( c.length() > 0 && !c.startsWith( embedKey ) ) { buf.append( c ); buf.append( ',' ); } } // add the new clause buf.append( embedClause ); return buf.toString(); } }