blob: 4e28260dd27938d15eb10aa20a7bb2e0d6c5715a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.felix.tools.maven2.bundleplugin;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.regex.*;
import java.util.zip.ZipException;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.*;
import org.apache.maven.plugin.*;
import org.apache.maven.project.MavenProject;
import aQute.lib.osgi.*;
/**
*
* @goal bundle
* @phase package
* @requiresDependencyResolution runtime
* @description build an OSGi bundle jar
*/
public class BundlePlugin extends AbstractMojo {
/**
* @parameter expression="${project.build.outputDirectory}"
* @required
* @readonly
*/
File outputDirectory;
/**
* The directory for the pom
*
* @parameter expression="${basedir}"
* @required
*/
private File baseDir;
/**
* The directory for the generated JAR.
*
* @parameter expression="${project.build.directory}"
* @required
*/
private String buildDirectory;
/**
* The Maven project.
*
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* The name of the generated JAR file.
*
* @parameter
*/
private Map instructions = new HashMap();
public void execute() throws MojoExecutionException {
try {
File jarFile = new File(buildDirectory, project.getBuild()
.getFinalName()
+ ".jar");
// Setup defaults
String bsn = project.getGroupId() + "." + project.getArtifactId();
Properties properties = new Properties();
properties.put(Analyzer.BUNDLE_SYMBOLICNAME, bsn);
properties.put(Analyzer.IMPORT_PACKAGE, "*");
if (!instructions.containsKey(Analyzer.PRIVATE_PACKAGE)) {
properties.put(Analyzer.EXPORT_PACKAGE, bsn + ".*");
}
String version = project.getVersion();
Pattern P_VERSION = Pattern.compile("([0-9]+(\\.[0-9])*)-(.*)");
Matcher m = P_VERSION.matcher(version);
if (m.matches()) {
version = m.group(1) + "." + m.group(3);
}
properties.put(Analyzer.BUNDLE_VERSION, version);
header(properties, Analyzer.BUNDLE_DESCRIPTION, project
.getDescription());
header(properties, Analyzer.BUNDLE_LICENSE, printLicenses(project
.getLicenses()));
header(properties, Analyzer.BUNDLE_NAME, project.getName());
if (project.getOrganization() != null) {
header(properties, Analyzer.BUNDLE_VENDOR, project
.getOrganization().getName());
if (project.getOrganization().getUrl() != null) {
header(properties, Analyzer.BUNDLE_DOCURL, project
.getOrganization().getUrl());
}
}
if (new File(baseDir, "src/main/resources").exists()) {
header(properties, Analyzer.INCLUDE_RESOURCE, "src/main/resources/");
}
properties.putAll(project.getProperties());
properties.putAll(project.getModel().getProperties());
properties.putAll( getProperies("project.build.", project.getBuild()));
properties.putAll( getProperies("pom.", project.getModel()));
properties.putAll( getProperies("project.", project));
properties.put("project.baseDir", baseDir );
properties.put("project.build.directory", buildDirectory );
properties.put("project.build.outputdirectory", outputDirectory );
properties.putAll(instructions);
Builder builder = new Builder();
builder.setBase(baseDir);
Jar[] cp = getClasspath();
builder.setProperties(properties);
builder.setClasspath(cp);
builder.build();
Jar jar = builder.getJar();
doMavenMetadata(jar);
builder.setJar(jar);
List errors = builder.getErrors();
List warnings = builder.getWarnings();
if (errors.size() > 0) {
jarFile.delete();
for (Iterator e = errors.iterator(); e.hasNext();) {
String msg = (String) e.next();
getLog().error(msg);
}
throw new MojoFailureException("Found errors, see log");
}
else {
jarFile.getParentFile().mkdirs();
builder.getJar().write(jarFile);
project.getArtifact().setFile(jarFile);
}
for (Iterator w = warnings.iterator(); w.hasNext();) {
String msg = (String) w.next();
getLog().warn(msg);
}
}
catch (Exception e) {
e.printStackTrace();
throw new MojoExecutionException("Unknown error occurred", e);
}
}
private Map getProperies(String prefix, Object model) {
Map properties = new HashMap();
Method methods[] = Model.class.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
String name = methods[i].getName();
if ( name.startsWith("get") ) {
try {
Object v = methods[i].invoke(project.getModel(), null );
if ( v != null ) {
name = prefix + Character.toLowerCase(name.charAt(3)) + name.substring(4);
if ( v.getClass().isArray() )
properties.put( name, Arrays.asList((Object[])v).toString() );
else
properties.put( name, v );
}
}
catch (Exception e) {
// too bad
}
}
}
return properties;
}
private StringBuffer printLicenses(List licenses) {
if (licenses == null || licenses.size() == 0)
return null;
StringBuffer sb = new StringBuffer();
String del = "";
for (Iterator i = licenses.iterator(); i.hasNext();) {
License l = (License) i.next();
String url = l.getUrl();
sb.append(del);
sb.append(url);
del = ", ";
}
return sb;
}
/**
* @param jar
* @throws IOException
*/
private void doMavenMetadata(Jar jar) throws IOException {
String path = "META-INF/maven/" + project.getGroupId() + "/"
+ project.getArtifactId();
File pomFile = new File(baseDir, "pom.xml");
jar.putResource(path + "/pom.xml", new FileResource(pomFile));
Properties p = new Properties();
p.put("version", project.getVersion());
p.put("groupId", project.getGroupId());
p.put("artifactId", project.getArtifactId());
ByteArrayOutputStream out = new ByteArrayOutputStream();
p.store(out, "Generated by org.apache.felix.plugin.bundle");
jar.putResource(path + "/pom.properties", new EmbeddedResource(out
.toByteArray()));
}
/**
* @return
* @throws ZipException
* @throws IOException
*/
private Jar[] getClasspath() throws ZipException, IOException {
List list = new ArrayList();
if (outputDirectory != null && outputDirectory.exists()) {
list.add(new Jar(".", outputDirectory));
}
Set artifacts = project.getArtifacts();
for (Iterator it = artifacts.iterator(); it.hasNext();) {
Artifact artifact = (Artifact) it.next();
if (Artifact.SCOPE_COMPILE.equals(artifact.getScope())
|| Artifact.SCOPE_SYSTEM.equals(artifact.getScope())
|| Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) {
Jar jar = new Jar(artifact.getArtifactId(), artifact.getFile());
list.add(jar);
}
}
Jar[] cp = new Jar[list.size()];
list.toArray(cp);
return cp;
}
private void header(Properties properties, String key, Object value) {
if (value == null)
return;
if (value instanceof Collection && ((Collection) value).isEmpty())
return;
properties.put(key, value.toString());
}
}