You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/02/19 16:01:13 UTC
git commit: [KARAF-2763] Use a plugin for SCR support to work around
the fact that maven can't add build artifacts to plugin class path
Repository: karaf
Updated Branches:
refs/heads/master 92c85f25c -> 73205de0d
[KARAF-2763] Use a plugin for SCR support to work around the fact that maven can't add build artifacts to plugin class path
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/73205de0
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/73205de0
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/73205de0
Branch: refs/heads/master
Commit: 73205de0d50e91990c04674351e45797d6ee7e76
Parents: 92c85f2
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Feb 19 16:00:59 2014 +0100
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Wed Feb 19 16:00:59 2014 +0100
----------------------------------------------------------------------
pom.xml | 17 +-
scr/command/pom.xml | 23 +-
scr/pom.xml | 1 -
scr/support/pom.xml | 113 -------
.../karaf/scr/support/InjectAnnotations.java | 279 -----------------
.../karaf/scr/support/ScrCommandSupport.java | 112 -------
tooling/karaf-scr-maven-plugin/pom.xml | 243 +++++++++++++++
.../karaf/tooling/scr/ScrCommandMojo.java | 309 +++++++++++++++++++
.../karaf/tooling/scr/ScrCommandSupport.java | 112 +++++++
tooling/pom.xml | 1 +
10 files changed, 685 insertions(+), 525 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index da53fad..e1780ac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,9 +59,7 @@
<module>webconsole</module>
<module>exception</module>
<module>scheduler</module>
- <!--
<module>scr</module>
- -->
<module>diagnostic</module>
<module>obr</module>
<module>jndi</module>
@@ -1930,6 +1928,21 @@
</configuration>
</plugin>
<plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-scr-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>scr</goal>
+ </goals>
+ <configuration>
+ <ranking>${karaf.service.ranking}</ranking>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-idea-plugin</artifactId>
<version>2.2.1</version>
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/scr/command/pom.xml
----------------------------------------------------------------------
diff --git a/scr/command/pom.xml b/scr/command/pom.xml
index 4475bfc..1a8a981 100644
--- a/scr/command/pom.xml
+++ b/scr/command/pom.xml
@@ -35,6 +35,7 @@
<properties>
<appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+ <karaf.service.ranking>1</karaf.service.ranking>
</properties>
<dependencies>
@@ -69,11 +70,6 @@
<artifactId>bndlib</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.scr</groupId>
- <artifactId>org.apache.karaf.scr.support</artifactId>
- <scope>provided</scope>
- </dependency>
</dependencies>
<build>
@@ -94,21 +90,12 @@
</resources>
<plugins>
<plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-scr-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Service-Component>*</Service-Component>
- <_plugin>org.apache.karaf.scr.support.InjectAnnotations</_plugin>
- </instructions>
- </configuration>
- <dependencies>
- <dependency>
- <groupId>org.apache.karaf.scr</groupId>
- <artifactId>org.apache.karaf.scr.support</artifactId>
- <version>${project.version}</version>
- </dependency>
- </dependencies>
</plugin>
</plugins>
</build>
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/scr/pom.xml
----------------------------------------------------------------------
diff --git a/scr/pom.xml b/scr/pom.xml
index 4d7422c..162477a 100644
--- a/scr/pom.xml
+++ b/scr/pom.xml
@@ -34,7 +34,6 @@
<name>Apache Karaf :: Declarative Services (DS)</name>
<modules>
- <module>support</module>
<module>command</module>
<module>management</module>
<module>examples</module>
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/scr/support/pom.xml
----------------------------------------------------------------------
diff --git a/scr/support/pom.xml b/scr/support/pom.xml
deleted file mode 100644
index 3ee6706..0000000
--- a/scr/support/pom.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <!--
-
- 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.
- -->
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.apache.karaf.scr</groupId>
- <artifactId>scr</artifactId>
- <version>3.0.1-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
-
- <artifactId>org.apache.karaf.scr.support</artifactId>
- <packaging>jar</packaging>
- <name>Apache Karaf :: SCR :: Support</name>
- <description>This bundle provides support for commands.</description>
-
- <properties>
- <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.shell</groupId>
- <artifactId>org.apache.karaf.shell.console</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.scr</artifactId>
- </dependency>
- <dependency>
- <groupId>biz.aQute.bnd</groupId>
- <artifactId>bndlib</artifactId>
- <optional>true</optional>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.gogo.runtime</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <includes>
- <include>**/*</include>
- </includes>
- </resource>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <filtering>true</filtering>
- <includes>
- <include>**/*.info</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Import-Package>
- org.apache.felix.gogo.commands,
- org.apache.karaf.shell.commands.basic,
- org.apache.karaf.shell.console,
- org.apache.karaf.shell.inject,
- org.osgi.framework,
- org.osgi.service.component,
- org.slf4j
- </Import-Package>
- <Export-Package>
- org.apache.karaf.scr.support
- </Export-Package>
- <Private-Package>
- org.apache.karaf.scr.support.plugin
- </Private-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/scr/support/src/main/java/org/apache/karaf/scr/support/InjectAnnotations.java
----------------------------------------------------------------------
diff --git a/scr/support/src/main/java/org/apache/karaf/scr/support/InjectAnnotations.java b/scr/support/src/main/java/org/apache/karaf/scr/support/InjectAnnotations.java
deleted file mode 100644
index 92e56b1..0000000
--- a/scr/support/src/main/java/org/apache/karaf/scr/support/InjectAnnotations.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * 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.scr.support;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import aQute.bnd.component.HeaderReader;
-import aQute.bnd.component.TagResource;
-import aQute.bnd.header.Parameters;
-import aQute.bnd.osgi.Analyzer;
-import aQute.bnd.osgi.Annotation;
-import aQute.bnd.osgi.ClassDataCollector;
-import aQute.bnd.osgi.Clazz;
-import aQute.bnd.osgi.Constants;
-import aQute.bnd.osgi.Descriptors;
-import aQute.bnd.osgi.Instruction;
-import aQute.bnd.osgi.Processor;
-import aQute.bnd.osgi.URLResource;
-import aQute.bnd.service.AnalyzerPlugin;
-import aQute.lib.tag.Tag;
-import org.apache.felix.service.command.CommandProcessor;
-import org.apache.felix.service.command.Function;
-import org.apache.karaf.scr.support.ScrCommandSupport;
-import org.apache.karaf.shell.commands.Command;
-import org.apache.karaf.shell.commands.CommandWithAction;
-import org.apache.karaf.shell.commands.basic.AbstractCommand;
-import org.apache.karaf.shell.console.CompletableFunction;
-import org.apache.karaf.shell.inject.Destroy;
-import org.apache.karaf.shell.inject.Init;
-import org.apache.karaf.shell.inject.Reference;
-import org.apache.karaf.shell.inject.Service;
-
-import static aQute.bnd.osgi.Constants.COMPONENT_ACTIVATE;
-import static aQute.bnd.osgi.Constants.COMPONENT_DEACTIVATE;
-import static aQute.bnd.osgi.Constants.COMPONENT_PROPERTIES;
-import static aQute.bnd.osgi.Constants.COMPONENT_PROVIDE;
-
-/**
- *
- */
-public class InjectAnnotations implements AnalyzerPlugin {
-
- private Analyzer analyzer;
-
- @Override
- public boolean analyzeJar(Analyzer analyzer) throws Exception {
- try {
- return doAnalyzeJar(analyzer);
- } catch (Exception t) {
- t.printStackTrace(System.out);
- throw t;
- }
- }
-
- protected boolean doAnalyzeJar(Analyzer analyzer) throws Exception {
- this.analyzer = analyzer;
-
- System.out.println("\nLooking for @Service annotated classes\n");
-
- Collection<Clazz> annotatedComponents = analyzer.getClasses("", Clazz.QUERY.ANNOTATED.toString(), Service.class.getName());
-
- List<String> components = new ArrayList<String>();
-
-
- for (Clazz clazz : annotatedComponents) {
- System.out.println("\nFound @Service annotated class: " + clazz);
-
- if (clazz.is(Clazz.QUERY.ANNOTATED, new Instruction(Command.class.getName()), analyzer)) {
- System.out.println("\tCommand");
- Collector collector = new Collector();
- clazz.parseClassFileWithCollector(collector);
-
- Map<String, String> info = new LinkedHashMap<String, String>();
- info.put(COMPONENT_ACTIVATE, "activate");
- info.put(COMPONENT_DEACTIVATE, "deactivate");
- for (String key : collector.references.keySet()) {
- info.put(key, collector.references.get(key));
- }
- info.put(COMPONENT_PROVIDE, Processor.join(Arrays.asList(new String[] {
- Function.class.getName(),
- CompletableFunction.class.getName(),
- CommandWithAction.class.getName(),
-// AbstractCommand.class.getName()
- })));
-
- List<String> properties = new ArrayList<String>();
- properties.add(CommandProcessor.COMMAND_SCOPE + "=" + collector.command.get("scope"));
- properties.add(CommandProcessor.COMMAND_FUNCTION + "=" + collector.command.get("name"));
- properties.add("hidden.component=true");
- info.put(COMPONENT_PROPERTIES, Processor.join(properties));
-
- TagResource resource = createComponentResource(clazz.getFQN(), ScrCommandSupport.class.getName(), info);
- analyzer.getJar().putResource("OSGI-INF/" + clazz.getFQN() + ".xml", resource);
- components.add("OSGI-INF/" + clazz.getFQN() + ".xml");
- resource.write(System.out);
- System.out.println();
-
- } else {
- System.out.println("\tNot a command");
- Collector collector = new Collector();
- clazz.parseClassFileWithCollector(collector);
-
- Map<String, String> info = new LinkedHashMap<String, String>();
- if (collector.init != null) {
- info.put(COMPONENT_ACTIVATE, collector.init);
- }
- if (collector.destroy != null) {
- info.put(COMPONENT_DEACTIVATE, collector.destroy);
- }
- for (String key : collector.references.keySet()) {
- info.put(key, collector.references.get(key));
- }
- info.put(COMPONENT_PROVIDE, Processor.join(collector.allClasses));
- List<String> properties = new ArrayList<String>();
- properties.add("hidden.component=true");
- info.put(COMPONENT_PROPERTIES, Processor.join(properties));
-
- TagResource resource = createComponentResource(clazz.getFQN(), clazz.getFQN(), info);
- analyzer.getJar().putResource("OSGI-INF/" + clazz.getFQN() + ".xml", resource);
- components.add("OSGI-INF/" + clazz.getFQN() + ".xml");
- resource.write(System.out);
- System.out.println();
- }
-
- }
-
- String name = ScrCommandSupport.class.getName().replace('.', '/') + ".class";
- analyzer.getJar().putResource(name, new URLResource(ScrCommandSupport.class.getClassLoader().getResource(name)));
- String pkg = ScrCommandSupport.class.getName();
- pkg = pkg.substring( 0, pkg.lastIndexOf( '.' ) );
- Descriptors.PackageRef pkgRef = analyzer.getPackageRef( pkg );
- if ( !analyzer.getContained().containsKey( pkgRef ) ) {
- analyzer.getContained().put(pkgRef);
- }
- String[] imports = new String[] {
- "org.apache.felix.gogo.commands",
- "org.apache.karaf.shell.commands.basic",
- "org.apache.karaf.shell.console",
- "org.apache.karaf.shell.inject",
- "org.osgi.framework",
- "org.osgi.service.component",
- "org.slf4j"
- };
- for (String importPkg : imports) {
- pkgRef = analyzer.getPackageRef( importPkg );
- if ( !analyzer.getReferred().containsKey( pkgRef ) ) {
- analyzer.getReferred().put( pkgRef );
- }
- }
-
- String prop = analyzer.getProperty(Constants.SERVICE_COMPONENT);
- for (String comp : components) {
- if (prop == null || prop.length() == 0) {
- prop = comp;
- } else {
- prop = prop + "," + comp;
- }
- }
- analyzer.setProperty(Constants.SERVICE_COMPONENT, prop);
-
- return false;
- }
-
- TagResource createComponentResource(String name, String impl, Map<String, String> info)
- throws Exception {
- Tag tag = new HeaderReader(analyzer).createComponentTag(name, impl, info);
- return new TagResource(tag);
- }
-
- class Collector extends ClassDataCollector {
- Descriptors.TypeRef zuper;
- Clazz.MethodDef method;
- Clazz.FieldDef field;
-
- String init;
- String destroy;
- Annotation command;
- Map<String, String> references = new LinkedHashMap<String, String>();
- List<String> allClasses = new ArrayList<String>();
-
- @Override
- public void classBegin(int access, Descriptors.TypeRef name) {
- if (!name.getFQN().equals(Object.class.getName())) {
- allClasses.add(name.getFQN());
- }
- }
-
- public void implementsInterfaces(Descriptors.TypeRef[] interfaces) throws Exception {
- if (interfaces != null) {
- for (Descriptors.TypeRef ref : interfaces) {
- allClasses.add(ref.getFQN());
- }
- }
- }
-
- @Override
- public void extendsClass(Descriptors.TypeRef zuper) throws Exception {
- this.zuper = zuper;
- }
-
- @Override
- public void field(Clazz.FieldDef defined) {
- field = defined;
- }
-
- @Override
- public void method(Clazz.MethodDef defined) {
- method = defined;
- }
-
- @Override
- public void annotation(Annotation annotation) {
- String name = annotation.getName().getFQN();
- if (Command.class.getName().equals(name)) {
- System.out.println("\tCommand: " + annotation.get("scope") + ":" + annotation.get("name"));
- command = annotation;
- }
- if (Reference.class.getName().equals(name)) {
- System.out.println("\tReference: field=" + field.getName() + ", type=" + field.getType().getFQN());
- references.put(field.getName(), field.getType().getFQN());
- }
- if (Init.class.getName().equals(name)) {
- if (init == null) {
- System.out.println("\tInit method: " + method.getName());
- init = method.getName();
- }
- }
- if (Destroy.class.getName().equals(name)) {
- if (destroy == null) {
- System.out.println("\tDestroy method: " + method.getName());
- destroy = method.getName();
- }
- }
- }
-
- @Override
- public void classEnd() throws Exception {
- if (zuper != null) {
- Clazz clazz = analyzer.findClass(zuper);
- zuper = null;
- if (clazz != null) {
- clazz.parseClassFileWithCollector(this);
- }
- }
- }
- }
-
- static boolean isAnnotated(Clazz.Def def, Class annotation) {
- Collection<Descriptors.TypeRef> anns = def.getAnnotations();
- if (anns != null) {
- for (Descriptors.TypeRef ann : anns) {
- if (annotation.getName().equals(ann.getFQN())) {
- return true;
- }
- }
- }
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/scr/support/src/main/java/org/apache/karaf/scr/support/ScrCommandSupport.java
----------------------------------------------------------------------
diff --git a/scr/support/src/main/java/org/apache/karaf/scr/support/ScrCommandSupport.java b/scr/support/src/main/java/org/apache/karaf/scr/support/ScrCommandSupport.java
deleted file mode 100644
index 18eadb0..0000000
--- a/scr/support/src/main/java/org/apache/karaf/scr/support/ScrCommandSupport.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.scr.support;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.gogo.commands.Action;
-import org.apache.karaf.shell.commands.basic.AbstractCommand;
-import org.apache.karaf.shell.console.BundleContextAware;
-import org.apache.karaf.shell.console.CompletableFunction;
-import org.apache.karaf.shell.console.Completer;
-import org.apache.karaf.shell.inject.Init;
-import org.apache.karaf.shell.inject.Reference;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.component.ComponentContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- */
-public class ScrCommandSupport extends AbstractCommand implements CompletableFunction {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(ScrCommandSupport.class);
-
- private ComponentContext componentContext;
-
- public ScrCommandSupport() {
- }
-
- public void activate(ComponentContext componentContext) {
- LOGGER.info("Activating SCR command for " + componentContext.getProperties().get("component.name"));
- this.componentContext = componentContext;
- }
-
- public void deactivate(ComponentContext componentContext) {
- }
-
- public Class<? extends Action> getActionClass() {
- try {
- String className = (String) componentContext.getProperties().get("component.name");
- return (Class<? extends Action>) componentContext.getBundleContext().getBundle().loadClass(className);
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public Action createNewAction() {
- Class actionClass = getActionClass();
- try {
- Action action = (Action) actionClass.newInstance();
- // Inject services
- for (Class<?> cl = actionClass; cl != Object.class; cl = cl.getSuperclass()) {
- for (Field field : cl.getDeclaredFields()) {
- if (field.getAnnotation(Reference.class) != null) {
- Object value;
- if (field.getType() == BundleContext.class) {
- value = componentContext.getBundleContext();
- } else {
- value = componentContext.locateService(field.getName());
- }
- if (value == null) {
- throw new RuntimeException("No OSGi service matching " + field.getType().getName());
- }
- field.setAccessible(true);
- field.set(action, value);
- }
- }
- }
- if (action instanceof BundleContextAware) {
- ((BundleContextAware) action).setBundleContext(componentContext.getBundleContext());
- }
- for (Method method : actionClass.getDeclaredMethods()) {
- Init ann = method.getAnnotation(Init.class);
- if (ann != null && method.getParameterTypes().length == 0 && method.getReturnType() == void.class) {
- method.setAccessible(true);
- method.invoke(action);
- }
- }
- return action;
- } catch (Exception e) {
- throw new RuntimeException("Unable to creation command action " + actionClass.getName(), e);
- }
- }
-
- @Override
- public List<Completer> getCompleters() {
- return null;
- }
-
- @Override
- public Map<String, Completer> getOptionalCompleters() {
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/tooling/karaf-scr-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-scr-maven-plugin/pom.xml b/tooling/karaf-scr-maven-plugin/pom.xml
new file mode 100644
index 0000000..1f12340
--- /dev/null
+++ b/tooling/karaf-scr-maven-plugin/pom.xml
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>tooling</artifactId>
+ <version>3.0.1-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>karaf-scr-maven-plugin</artifactId>
+ <packaging>maven-plugin</packaging>
+ <name>Apache Karaf :: Tooling :: Maven Karaf SCR Plugin</name>
+
+ <properties>
+ <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>3.0.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.sonatype.aether</groupId>
+ <artifactId>aether-api</artifactId>
+ <version>1.11</version>
+ </dependency>
+ <dependency>
+ <groupId>org.sonatype.aether</groupId>
+ <artifactId>aether-util</artifactId>
+ <version>1.11</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>3.0.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>3.0.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-compat</artifactId>
+ <version>3.0.3</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-filtering</artifactId>
+ <version>1.0-beta-4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>3.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.bundlerepository</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.fileinstall</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>org.apache.karaf.features.core</artifactId>
+ <exclusions>
+ <exclusion>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <groupId>org.apache.karaf.shell</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.url</groupId>
+ <artifactId>pax-url-wrap</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.url</groupId>
+ <artifactId>pax-url-aether</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.deployer</groupId>
+ <artifactId>org.apache.karaf.deployer.spring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.deployer</groupId>
+ <artifactId>org.apache.karaf.deployer.blueprint</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.deployer</groupId>
+ <artifactId>org.apache.karaf.deployer.features</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.deployer</groupId>
+ <artifactId>org.apache.karaf.deployer.kar</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.kar</groupId>
+ <artifactId>org.apache.karaf.kar.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.ant</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.xbean</groupId>
+ <artifactId>xbean-finder-shaded</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.generator</artifactId>
+ <version>1.5.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.ds-annotations</artifactId>
+ <version>1.2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.sonatype.plexus</groupId>
+ <artifactId>plexus-build-api</artifactId>
+ <version>0.0.7</version>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>ci-build-profile</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-invoker-plugin</artifactId>
+ <version>1.6</version>
+ <configuration>
+ <debug>true</debug>
+ <projectsDirectory>src/it</projectsDirectory>
+ <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
+ <pomIncludes>
+ <pomInclude>*/pom.xml</pomInclude>
+ </pomIncludes>
+ <postBuildHookScript>verify</postBuildHookScript>
+ <localRepositoryPath>${project.build.directory}/system</localRepositoryPath>
+ <!--<settingsFile>src/it/settings.xml</settingsFile>-->
+ <mavenOpts>-Djava.io.tmpdir=${project.build.directory}</mavenOpts>
+ <goals>
+ <goal>install</goal>
+ </goals>
+ </configuration>
+ <executions>
+ <execution>
+ <id>integration-test</id>
+ <goals>
+ <goal>install</goal>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ <version>1.3</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+ <reporting>
+ <!--<outputDirectory>target/site</outputDirectory>-->
+ <plugins>
+ <plugin>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>2.9</version>
+ </plugin>
+ </plugins>
+ </reporting>
+
+</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/tooling/karaf-scr-maven-plugin/src/main/java/org/apache/karaf/tooling/scr/ScrCommandMojo.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-scr-maven-plugin/src/main/java/org/apache/karaf/tooling/scr/ScrCommandMojo.java b/tooling/karaf-scr-maven-plugin/src/main/java/org/apache/karaf/tooling/scr/ScrCommandMojo.java
new file mode 100644
index 0000000..377dd60
--- /dev/null
+++ b/tooling/karaf-scr-maven-plugin/src/main/java/org/apache/karaf/tooling/scr/ScrCommandMojo.java
@@ -0,0 +1,309 @@
+package org.apache.karaf.tooling.scr;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.Function;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.CommandWithAction;
+import org.apache.karaf.shell.console.CompletableFunction;
+import org.apache.karaf.shell.inject.Reference;
+import org.apache.karaf.shell.inject.Service;
+import org.apache.maven.artifact.DependencyResolutionRequiredException;
+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.project.MavenProject;
+import org.apache.xbean.finder.ClassFinder;
+
+/**
+ * The <code>ScrCommandMojo</code> generates a service descriptor file based
+ * on annotations found in the sources.
+ *
+ * @goal scr
+ * @phase process-classes
+ * @threadSafe
+ * @description Build Service Descriptors from Java Source
+ * @requiresDependencyResolution compile
+ */
+public class ScrCommandMojo extends AbstractMojo {
+
+ /**
+ * The Maven project.
+ *
+ * @parameter expression="project"
+ * @required
+ * @readonly
+ */
+ private MavenProject project;
+
+ /**
+ * @parameter expression="${project.build.directory}/generated-scr-commands"
+ */
+ private File outputDirectory;
+
+ /**
+ * @parameter
+ */
+ private int ranking;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ try {
+ ClassFinder finder = new ClassFinder(getClassLoader());
+ List<String> components = new ArrayList<String>();
+ boolean hasCommand = false;
+ for (Class<?> clazz : finder.findAnnotatedClasses(Service.class)) {
+
+ Command cmd = clazz.getAnnotation(Command.class);
+ if (cmd != null) {
+ System.out.println("\nFound command: " + clazz.getName() + "\n\t" + cmd.scope() + ":" + cmd.name() + "\n");
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("<?xml version='1.1'?>\n");
+ sb.append("<scr:component xmlns:scr=\"http://www.osgi.org/xmlns/scr/v1.1.0\" name=\"")
+ .append(clazz.getName())
+ .append("\" activate=\"activate\" deactivate=\"deactivate\">\n");
+ sb.append(" <implementation class=\"").append(ScrCommandSupport.class.getName()).append("\"/>\n");
+ sb.append(" <service>\n");
+ sb.append(" <provide interface=\"").append(Function.class.getName()).append("\"/>\n");
+ sb.append(" <provide interface=\"").append(CompletableFunction.class.getName()).append("\"/>\n");
+ sb.append(" <provide interface=\"").append(CommandWithAction.class.getName()).append("\"/>\n");
+ sb.append(" </service>\n");
+ Map<String, Class> refs = getReferences(clazz);
+ for (String key : refs.keySet()) {
+ sb.append(" <reference name=\"").append(key).append("\" cardinality=\"1..1\" interface=\"")
+ .append(refs.get(key).getName()).append("\"/>\n");
+ }
+ sb.append(" <property name=\"hidden.component\" value=\"true\"/>\n");
+ if (ranking != 0) {
+ sb.append(" <property name=\"service.ranking\" value=\"").append(ranking).append("\"/>\n");
+ }
+ sb.append(" <property name=\"").append(CommandProcessor.COMMAND_SCOPE).append("\" value=\"").append(cmd.scope()).append("\"/>\n");
+ sb.append(" <property name=\"").append(CommandProcessor.COMMAND_FUNCTION).append("\" value=\"").append(cmd.name()).append("\"/>\n");
+ sb.append("</scr:component>\n");
+ String component = "OSGI-INF/" + clazz.getName() + ".xml";
+ components.add(component);
+ File file = new File(outputDirectory, component);
+ file.getParentFile().mkdirs();
+ Writer w = new FileWriter(file);
+ w.write(sb.toString());
+ w.close();
+ hasCommand = true;
+ } else {
+ System.out.println("\nFound service: " + clazz.getName() + "\n");
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("<?xml version='1.1'?>\n");
+ sb.append("<scr:component xmlns:scr=\"http://www.osgi.org/xmlns/scr/v1.1.0\" name=\"")
+ .append(clazz.getName())
+ .append("\" activate=\"activate\" deactivate=\"deactivate\">\n");
+ sb.append(" <implementation class=\"").append(clazz.getName()).append("\"/>\n");
+ sb.append(" <service>\n");
+ List<Class> allClasses = new ArrayList<Class>();
+ addAllClasses(allClasses, clazz);
+ for (Class cl : allClasses) {
+ sb.append(" <provide interface=\"").append(cl.getName()).append("\"/>\n");
+ }
+ sb.append(" </service>\n");
+ Map<String, Class> refs = getReferences(clazz);
+ for (String key : refs.keySet()) {
+ sb.append(" <reference name=\"").append(key).append("\" cardinality=\"1..1\" interface=\"")
+ .append(refs.get(key).getName()).append("\"");
+ String[] bind = getBindMethods(clazz, key, refs.get(key));
+ if (bind[0] != null) {
+ sb.append(" bind=\"").append(bind[0]).append("\"");
+ }
+ if (bind[1] != null) {
+ sb.append(" unbind=\"").append(bind[1]).append("\"");
+ }
+ sb.append("/>\n");
+ }
+ sb.append(" <property name=\"hidden.component\" value=\"true\"/>\n");
+ if (ranking != 0) {
+ sb.append(" <property name=\"service.ranking\" value=\"").append(ranking).append("\"/>\n");
+ }
+ sb.append("</scr:component>\n");
+ String component = "OSGI-INF/" + clazz.getName() + ".xml";
+ components.add(component);
+ File file = new File(outputDirectory, component);
+ file.getParentFile().mkdirs();
+ Writer w = new FileWriter(file);
+ w.write(sb.toString());
+ w.close();
+ }
+ }
+ if (!components.isEmpty()) {
+ if (hasCommand) {
+ String name = ScrCommandSupport.class.getName().replace('.', '/') + ".class";
+ File file = new File(outputDirectory, name);
+ file.getParentFile().mkdirs();
+ URL url = getClass().getClassLoader().getResource(name);
+ InputStream is = url.openStream();
+ FileOutputStream fos = new FileOutputStream(file);
+ copy(is, fos);
+ is.close();
+ fos.close();
+ name = ScrCommandSupport.class.getName();
+ name = name.substring(0, name.lastIndexOf('.'));
+ setPrivatePackageHeader(name);
+ }
+ setServiceComponentHeader(components);
+ updateProjectResources();
+ }
+ } catch (Exception e) {
+ throw new MojoExecutionException("Error executing SCR command scanner", e);
+ }
+ }
+
+ private String[] getBindMethods(Class<?> clazz, String key, Class type) {
+ String cap = key.substring(0, 1).toUpperCase() + key.substring(1);
+ Method bind = null;
+ Method unbind = null;
+ try {
+ bind = clazz.getMethod("set" + cap, type);
+ } catch (NoSuchMethodException e0) {
+ try {
+ bind = clazz.getMethod("bind" + cap, type);
+ } catch (NoSuchMethodException e1) {
+ }
+ }
+ if (bind != null) {
+ try {
+ unbind = clazz.getMethod("un" + bind.getName(), type);
+ } catch (NoSuchMethodException e0) {
+ }
+ }
+ return new String[] {
+ bind != null ? bind.getName() : null,
+ unbind != null ? unbind.getName() : null
+ };
+ }
+
+ private void addAllClasses(List<Class> allClasses, Class<?> clazz) {
+ if (clazz != null && clazz != Object.class) {
+ if (allClasses.add(clazz)) {
+ addAllClasses(allClasses, clazz.getSuperclass());
+ for (Class cl : clazz.getInterfaces()) {
+ addAllClasses(allClasses, cl);
+ }
+ }
+ }
+ }
+
+ private Map<String, Class> getReferences(Class<?> clazz) {
+ Map<String, Class> refs = new HashMap<String, Class>();
+ while (clazz != null) {
+ for (Field field : clazz.getDeclaredFields()) {
+ if (field.getAnnotation(Reference.class) != null) {
+ refs.put(field.getName(), field.getType());
+ }
+ }
+ clazz = clazz.getSuperclass();
+ }
+ return refs;
+ }
+
+ private ClassLoader getClassLoader() throws MojoFailureException, DependencyResolutionRequiredException, MalformedURLException {
+ List<URL> urls = new ArrayList<URL>();
+ for (Object object : project.getCompileClasspathElements()) {
+ String path = (String) object;
+ urls.add(new File(path).toURL());
+ }
+ ClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[] {}), getClass().getClassLoader());
+ return classLoader;
+ }
+
+ private void setPrivatePackageHeader(String pkg) {
+ String header = project.getProperties().getProperty("Private-Package");
+ if (header != null && header.length() > 0) {
+ header += "," + pkg;
+ } else {
+ header = pkg;
+ }
+ project.getProperties().setProperty("Private-Package", header);
+ System.out.println("\nPrivate-Package: " + header + "\n");
+ }
+
+ /**
+ * Set the service component header based on the scr files.
+ */
+ private void setServiceComponentHeader(final List<String> files) {
+ if ( files != null && files.size() > 0 ) {
+ final String svcHeader = project.getProperties().getProperty("Service-Component");
+ final Set<String> xmlFiles = new HashSet<String>();
+ if ( svcHeader != null ) {
+ final StringTokenizer st = new StringTokenizer(svcHeader, ",");
+ while ( st.hasMoreTokens() ) {
+ final String token = st.nextToken();
+ xmlFiles.add(token.trim());
+ }
+ }
+
+ for(final String path : files) {
+ xmlFiles.add(path);
+ }
+ final StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for(final String entry : xmlFiles) {
+ if ( !first ) {
+ sb.append(", ");
+ } else {
+ first = false;
+ }
+ sb.append(entry);
+ }
+ project.getProperties().setProperty("Service-Component", sb.toString());
+ System.out.println("\nService-Component: " + sb.toString() + "\n");
+ }
+ }
+
+ /**
+ * Update the Maven project resources.
+ */
+ private void updateProjectResources() {
+ // now add the descriptor directory to the maven resources
+ final String ourRsrcPath = this.outputDirectory.getAbsolutePath();
+ boolean found = false;
+ @SuppressWarnings("unchecked")
+ final Iterator<Resource> rsrcIterator = this.project.getResources().iterator();
+ while (!found && rsrcIterator.hasNext()) {
+ final Resource rsrc = rsrcIterator.next();
+ found = rsrc.getDirectory().equals(ourRsrcPath);
+ }
+ if (!found) {
+ final Resource resource = new Resource();
+ resource.setDirectory(this.outputDirectory.getAbsolutePath());
+ this.project.addResource(resource);
+ }
+ }
+
+ static void copy(InputStream is, OutputStream os) throws IOException {
+ byte[] buffer = new byte[8192];
+ int l;
+ while ((l = is.read(buffer)) > 0) {
+ os.write(buffer, 0, l);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/tooling/karaf-scr-maven-plugin/src/main/java/org/apache/karaf/tooling/scr/ScrCommandSupport.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-scr-maven-plugin/src/main/java/org/apache/karaf/tooling/scr/ScrCommandSupport.java b/tooling/karaf-scr-maven-plugin/src/main/java/org/apache/karaf/tooling/scr/ScrCommandSupport.java
new file mode 100644
index 0000000..c6c52ef
--- /dev/null
+++ b/tooling/karaf-scr-maven-plugin/src/main/java/org/apache/karaf/tooling/scr/ScrCommandSupport.java
@@ -0,0 +1,112 @@
+/*
+ * 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.scr;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.gogo.commands.Action;
+import org.apache.karaf.shell.commands.basic.AbstractCommand;
+import org.apache.karaf.shell.console.BundleContextAware;
+import org.apache.karaf.shell.console.CompletableFunction;
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.inject.Init;
+import org.apache.karaf.shell.inject.Reference;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ */
+public class ScrCommandSupport extends AbstractCommand implements CompletableFunction {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ScrCommandSupport.class);
+
+ private ComponentContext componentContext;
+
+ public ScrCommandSupport() {
+ }
+
+ public void activate(ComponentContext componentContext) {
+ LOGGER.info("Activating SCR command for " + componentContext.getProperties().get("component.name"));
+ this.componentContext = componentContext;
+ }
+
+ public void deactivate(ComponentContext componentContext) {
+ }
+
+ public Class<? extends Action> getActionClass() {
+ try {
+ String className = (String) componentContext.getProperties().get("component.name");
+ return (Class<? extends Action>) componentContext.getBundleContext().getBundle().loadClass(className);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public Action createNewAction() {
+ Class actionClass = getActionClass();
+ try {
+ Action action = (Action) actionClass.newInstance();
+ // Inject services
+ for (Class<?> cl = actionClass; cl != Object.class; cl = cl.getSuperclass()) {
+ for (Field field : cl.getDeclaredFields()) {
+ if (field.getAnnotation(Reference.class) != null) {
+ Object value;
+ if (field.getType() == BundleContext.class) {
+ value = componentContext.getBundleContext();
+ } else {
+ value = componentContext.locateService(field.getName());
+ }
+ if (value == null) {
+ throw new RuntimeException("No OSGi service matching " + field.getType().getName());
+ }
+ field.setAccessible(true);
+ field.set(action, value);
+ }
+ }
+ }
+ if (action instanceof BundleContextAware) {
+ ((BundleContextAware) action).setBundleContext(componentContext.getBundleContext());
+ }
+ for (Method method : actionClass.getDeclaredMethods()) {
+ Init ann = method.getAnnotation(Init.class);
+ if (ann != null && method.getParameterTypes().length == 0 && method.getReturnType() == void.class) {
+ method.setAccessible(true);
+ method.invoke(action);
+ }
+ }
+ return action;
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to creation command action " + actionClass.getName(), e);
+ }
+ }
+
+ @Override
+ public List<Completer> getCompleters() {
+ return null;
+ }
+
+ @Override
+ public Map<String, Completer> getOptionalCompleters() {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/73205de0/tooling/pom.xml
----------------------------------------------------------------------
diff --git a/tooling/pom.xml b/tooling/pom.xml
index d3ee158..9abc2cd 100644
--- a/tooling/pom.xml
+++ b/tooling/pom.xml
@@ -34,6 +34,7 @@
<name>Apache Karaf :: Tooling</name>
<modules>
+ <module>karaf-scr-maven-plugin</module>
<module>karaf-maven-plugin</module>
</modules>