org.apache.karaf.tooling.tracker.GenerateServiceMetadata Maven / Gradle / Ivy
The newest version!
/*
* 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.karaf.tooling.tracker;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.util.tracker.annotation.Managed;
import org.apache.karaf.util.tracker.annotation.ProvideService;
import org.apache.karaf.util.tracker.annotation.RequireService;
import org.apache.karaf.util.tracker.annotation.Services;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
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.xbean.finder.ClassFinder;
import org.osgi.framework.BundleActivator;
import org.sonatype.plexus.build.incremental.BuildContext;
/**
* Generates service requirement and capabilities for activators
*/
@Mojo(name = "service-metadata-generate", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, inheritByDefault = false)
public class GenerateServiceMetadata extends AbstractMojo {
/**
* The maven project.
*/
@Parameter(defaultValue = "${project}")
protected MavenProject project;
@Parameter(defaultValue="BNDExtension-Bundle-Activator")
protected String activatorProperty;
@Parameter(defaultValue="BNDExtension-Require-Capability")
protected String requirementsProperty;
@Parameter(defaultValue="BNDExtension-Provide-Capability")
protected String capabilitiesProperty;
@Parameter(defaultValue = "${project.build.directory}/generated/karaf-tracker")
protected String outputDirectory;
@Parameter(defaultValue=".*")
protected String artifactInclude;
/**
* The classloader to use for loading the commands.
* Can be "project" or "plugin"
*/
@Parameter(defaultValue = "project")
protected String classLoader;
@Component
private BuildContext buildContext;
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("START karaf-services-maven-plugin artifactInclude: " + artifactInclude);
try {
boolean addSourceDirectory = false;
StringBuilder requirements = new StringBuilder();
StringBuilder capabilities = new StringBuilder();
ClassFinder finder = createFinder(classLoader);
List> classes = finder.findAnnotatedClasses(Services.class);
List> activators = new ArrayList<>();
for (Class> clazz : classes) {
URL classUrl = clazz.getClassLoader().getResource(clazz.getName().replace('.', '/') + ".class");
URL outputDirectoryUrl = new File(project.getBuild().getOutputDirectory()).toURI().toURL();
if (classUrl == null || !classUrl.getPath().startsWith(outputDirectoryUrl.getPath())) {
getLog().info(" Ignoring " + classUrl);
continue;
} else {
getLog().info(" Found " + classUrl);
}
if (BundleActivator.class.isAssignableFrom(clazz)) {
activators.add(clazz);
}
Properties props = new Properties();
Services services = clazz.getAnnotation(Services.class);
if (services != null) {
for (RequireService req : services.requires()) {
String fltWithClass = combine(req.filter(), "(objectClass=" + req.value().getName() + ")");
addServiceReq(requirements, fltWithClass);
props.setProperty(req.value().getName(), req.filter());
}
for (ProvideService cap : services.provides()) {
addServiceCap(capabilities, cap);
}
}
Managed managed = clazz.getAnnotation(Managed.class);
if (managed != null) {
props.setProperty("pid", managed.value());
}
File file = new File(outputDirectory, "OSGI-INF/karaf-tracker/" + clazz.getName());
file.getParentFile().mkdirs();
try (OutputStream os = buildContext.newFileOutputStream(file)) {
props.store(os, null);
}
addSourceDirectory = true;
}
if (addSourceDirectory) {
Resource resource = new Resource();
resource.setDirectory(outputDirectory);
project.addResource(resource);
}
project.getProperties().setProperty(requirementsProperty, requirements.toString());
project.getProperties().setProperty(capabilitiesProperty, capabilities.toString());
if (activators.size() == 1) {
project.getProperties().setProperty(activatorProperty, activators.get(0).getName());
}
project.getProperties().setProperty("BNDExtension-Private-Package", "org.apache.karaf.util.tracker");
project.getProperties().setProperty("BNDPrependExtension-Import-Package", "!org.apache.karaf.util.tracker.annotation");
List> services = finder.findAnnotatedClasses(Service.class);
Set packages = new TreeSet<>();
for (Class> clazz : services) {
getLog().info(" Found Service " + clazz);
packages.add(clazz.getPackage().getName());
}
if (!packages.isEmpty()) {
project.getProperties().setProperty("BNDExtension-Karaf-Commands", join(packages, ","));
}
} catch (Exception e) {
throw new MojoExecutionException("Error building commands help", e);
}
getLog().info("STOP karaf-services-maven-plugin");
}
private String join(Set packages, String separator) {
StringBuilder sb = new StringBuilder();
for (String pkg : packages) {
if (sb.length() > 0) {
sb.append(separator);
}
sb.append(pkg);
}
return sb.toString();
}
private void addServiceCap(StringBuilder capabilities, ProvideService cap) {
if (capabilities.length() > 0) {
capabilities.append(",");
}
capabilities.append("osgi.service;effective:=active;objectClass=")
.append(cap.value().getName());
}
private void addServiceReq(StringBuilder requirements, String fltWithClass) {
if (requirements.length() > 0) {
requirements.append(",");
}
requirements.append("osgi.service;effective:=active;filter:=\"")
.append(fltWithClass)
.append("\"");
}
private String combine(String filter1, String filter2) {
if (filter1!=null && !filter1.isEmpty()) {
return "(&" + filter2 + filter1 + ")";
} else {
return filter2;
}
}
private ClassFinder createFinder(String classloaderType) throws Exception {
ClassFinder finder;
if ("project".equals(classloaderType)) {
List urls = new ArrayList<>();
urls.add( new File(project.getBuild().getOutputDirectory()).toURI().toURL() );
for ( Artifact artifact : project.getArtifacts() ) {
if (artifactInclude != null && artifactInclude.length() > 0 && artifact.getArtifactId().matches(artifactInclude)) {
getLog().info(" Artifact " + artifact.getGroupId() + "/" + artifact.getArtifactId() );
File file = artifact.getFile();
if ( file != null ) {
urls.add( file.toURI().toURL() );
getLog().debug(" classpath: " + file);
}
} else {
getLog().info(" Ignore Artifact " + artifact.getGroupId() + "/" + artifact.getArtifactId());
}
}
ClassLoader loader = new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader());
getLog().info("Load Classes; " + urls.size() + " jars");
finder = new ClassFinder(loader, urls);
} else if ("plugin".equals(classLoader)) {
finder = new ClassFinder(getClass().getClassLoader());
} else {
throw new MojoFailureException("classLoader attribute must be 'project' or 'plugin'");
}
return finder;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy