diff --git a/scm-core/src/main/java/sonia/scm/plugin/ExtensionPoint.java b/scm-core/src/main/java/sonia/scm/plugin/ExtensionPoint.java
index d85470ce19..26687f4fde 100644
--- a/scm-core/src/main/java/sonia/scm/plugin/ExtensionPoint.java
+++ b/scm-core/src/main/java/sonia/scm/plugin/ExtensionPoint.java
@@ -47,6 +47,7 @@ import java.lang.annotation.Target;
*/
@Documented
@Target({ ElementType.TYPE })
+@PluginAnnotation("extension-points")
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtensionPoint
{
diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginAnnotation.java b/scm-core/src/main/java/sonia/scm/plugin/PluginAnnotation.java
new file mode 100644
index 0000000000..a234702cd0
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/plugin/PluginAnnotation.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.plugin;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 2.0.0
+ */
+@Documented
+@Target(ElementType.ANNOTATION_TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PluginAnnotation
+{
+ String value();
+}
diff --git a/scm-core/src/main/java/sonia/scm/plugin/ext/Extension.java b/scm-core/src/main/java/sonia/scm/plugin/ext/Extension.java
index 437088cb1f..97813dfb27 100644
--- a/scm-core/src/main/java/sonia/scm/plugin/ext/Extension.java
+++ b/scm-core/src/main/java/sonia/scm/plugin/ext/Extension.java
@@ -33,6 +33,10 @@
package sonia.scm.plugin.ext;
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.plugin.PluginAnnotation;
+
//~--- JDK imports ------------------------------------------------------------
import java.lang.annotation.Documented;
@@ -47,5 +51,6 @@ import java.lang.annotation.Target;
*/
@Documented
@Target({ ElementType.TYPE })
+@PluginAnnotation("extensions")
@Retention(RetentionPolicy.RUNTIME)
public @interface Extension {}
diff --git a/scm-maven-plugins/pom.xml b/scm-maven-plugins/pom.xml
index 3e77b61cb0..8bf26056dc 100644
--- a/scm-maven-plugins/pom.xml
+++ b/scm-maven-plugins/pom.xml
@@ -18,6 +18,7 @@
scm-plugin-archetype
scm-maven-plugin
+ scm-annotation-processor
\ No newline at end of file
diff --git a/scm-maven-plugins/scm-annotation-processor/pom.xml b/scm-maven-plugins/scm-annotation-processor/pom.xml
new file mode 100644
index 0000000000..44f5ec50a1
--- /dev/null
+++ b/scm-maven-plugins/scm-annotation-processor/pom.xml
@@ -0,0 +1,40 @@
+
+
+
+ 4.0.0
+
+
+ sonia.scm.maven
+ scm-maven-plugins
+ 2.0.0-SNAPSHOT
+
+
+ sonia.scm.maven
+ scm-annotation-processor
+ 2.0.0-SNAPSHOT
+ scm-annotation-processor
+
+
+
+
+ sonia.scm
+ scm-core
+ 2.0.0-SNAPSHOT
+
+
+
+ org.jenkins-ci
+ annotation-indexer
+ 1.9
+
+
+
+ org.kohsuke.metainf-services
+ metainf-services
+ 1.5
+
+
+
+
+
diff --git a/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/ClassSetElement.java b/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/ClassSetElement.java
new file mode 100644
index 0000000000..22ec6db55b
--- /dev/null
+++ b/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/ClassSetElement.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.annotation;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class ClassSetElement implements DescriptorElement
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param elementName
+ * @param classes
+ */
+ public ClassSetElement(String elementName, Iterable classes)
+ {
+ this.elementName = elementName;
+ this.classes = classes;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param doc
+ * @param root
+ */
+ @Override
+ public void append(Document doc, Element root)
+ {
+ Element element = doc.createElement(elementName);
+
+ for (String c : classes)
+ {
+ Element classEl = doc.createElement("class");
+
+ classEl.setTextContent(c);
+ element.appendChild(classEl);
+ }
+
+ root.appendChild(element);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private final Iterable classes;
+
+ /** Field description */
+ private final String elementName;
+}
diff --git a/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/DescriptorElement.java b/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/DescriptorElement.java
new file mode 100644
index 0000000000..c10a625e2a
--- /dev/null
+++ b/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/DescriptorElement.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.annotation;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public interface DescriptorElement
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param doc
+ * @param root
+ */
+ public void append(Document doc, Element root);
+}
diff --git a/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/ScmAnnotationProcessor.java b/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/ScmAnnotationProcessor.java
new file mode 100644
index 0000000000..3a40d3dbd5
--- /dev/null
+++ b/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/ScmAnnotationProcessor.java
@@ -0,0 +1,413 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.annotation;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.github.legman.Subscribe;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import org.kohsuke.MetaInfServices;
+
+import org.w3c.dom.Document;
+
+import sonia.scm.plugin.PluginAnnotation;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+
+import java.lang.annotation.Annotation;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.ext.Provider;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@SuppressWarnings({ "Since16", "Since15" })
+@MetaInfServices(Processor.class)
+@SupportedSourceVersion(SourceVersion.RELEASE_6)
+@SupportedAnnotationTypes("*")
+public final class ScmAnnotationProcessor extends AbstractProcessor
+{
+
+ /** Field description */
+ private static final Set SUBSCRIBE_ANNOTATIONS =
+ ImmutableSet.of(Subscribe.class.getName());
+
+ /** Field description */
+ private static final Set CLASS_ANNOTATIONS =
+ ImmutableSet.of(new ClassAnnotation("jaxrs-resources", Path.class),
+ new ClassAnnotation("jaxrs-providers", Provider.class));
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param annotations
+ * @param roundEnv
+ *
+ * @return
+ */
+ @Override
+ public boolean process(Set extends TypeElement> annotations,
+ RoundEnvironment roundEnv)
+ {
+ if (!roundEnv.processingOver())
+ {
+ Set descriptorElements = Sets.newHashSet();
+ Set subscriberAnnotations = Sets.newHashSet();
+
+ for (TypeElement e : annotations)
+ {
+ PluginAnnotation pa = e.getAnnotation(PluginAnnotation.class);
+
+ if (pa != null)
+ {
+ scanForClassAnnotations(descriptorElements, pa.value(),
+ roundEnv.getElementsAnnotatedWith(e));
+ }
+
+ if (SUBSCRIBE_ANNOTATIONS.contains(e.getQualifiedName().toString()))
+ {
+ subscriberAnnotations.add(e);
+ }
+ }
+
+ for (ClassAnnotation ca : CLASS_ANNOTATIONS)
+ {
+ scanForClassAnnotations(descriptorElements, ca.elementName,
+ roundEnv.getElementsAnnotatedWith(ca.annotationClass));
+ }
+
+ for (TypeElement annotation : subscriberAnnotations)
+ {
+ scanForSubscriberAnnotations(descriptorElements, roundEnv, annotation);
+ }
+
+ write(descriptorElements);
+ }
+
+ return false;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param closeable
+ */
+ private void close(Closeable closeable)
+ {
+ if (closeable != null)
+ {
+ try
+ {
+ closeable.close();
+ }
+ catch (IOException ex)
+ {
+ processingEnv.getMessager().printMessage(Kind.WARNING,
+ "could not close closeable");
+ }
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param f
+ *
+ * @return
+ */
+ private Document parseDocument(FileObject f)
+ {
+ Document doc = null;
+ InputStream input = null;
+
+ try
+ {
+ File file = new File(f.toUri());
+
+ if (file.exists())
+ {
+ input = f.openInputStream();
+ doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
+ input);
+ }
+ else
+ {
+ processingEnv.getMessager().printMessage(Kind.WARNING,
+ "could not find plugin descriptor");
+ }
+ }
+ catch (Exception ex)
+ {
+ printException("could not parse document", ex);
+ }
+ finally
+ {
+ close(input);
+ }
+
+ return doc;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param msg
+ * @param throwable
+ */
+ private void printException(String msg, Throwable throwable)
+ {
+ processingEnv.getMessager().printMessage(Kind.ERROR, msg);
+
+ String stack = Throwables.getStackTraceAsString(throwable);
+
+ processingEnv.getMessager().printMessage(Kind.ERROR, stack);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ *
+ * @param classes
+ * @param elementName
+ * @param elements
+ *
+ * @param descriptorElements
+ * @param roundEnv
+ * @param annotationClass
+ * @param pa
+ * @param typeElement
+ * @param
+ *
+ * @return
+ */
+ private void scanForClassAnnotations(
+ Set descriptorElements, String elementName,
+ Set extends Element> elements)
+ {
+ Set classes = Sets.newHashSet();
+
+ for (Element e : elements)
+ {
+ if (e.getKind().isClass())
+ {
+ TypeElement type = (TypeElement) e;
+
+ classes.add(type.getQualifiedName().toString());
+ }
+ }
+
+ descriptorElements.add(new ClassSetElement(elementName, classes));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param descriptorElements
+ * @param roundEnv
+ * @param annotation
+ */
+ private void scanForSubscriberAnnotations(
+ Set descriptorElements, RoundEnvironment roundEnv,
+ TypeElement annotation)
+ {
+ for (Element el : roundEnv.getElementsAnnotatedWith(annotation))
+ {
+ if (el.getKind() == ElementKind.METHOD)
+ {
+ ExecutableElement ee = (ExecutableElement) el;
+ List extends VariableElement> params = ee.getParameters();
+
+ if ((params != null) && (params.size() == 1))
+ {
+ VariableElement param = params.get(0);
+
+ descriptorElements.add(
+ new SubscriberElement(
+ el.getEnclosingElement().toString(), param.asType().toString()));
+ }
+ }
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param roundEnv
+ * @param classes
+ *
+ * @param descriptorElements
+ */
+ private void write(Set descriptorElements)
+ {
+ Filer filer = processingEnv.getFiler();
+
+ try
+ {
+ FileObject f = filer.getResource(StandardLocation.CLASS_OUTPUT, "",
+ "META-INF/scm/plugin.xml");
+
+ Document doc = parseDocument(f);
+
+ if (doc != null)
+ {
+ org.w3c.dom.Element root = doc.getDocumentElement();
+
+ for (DescriptorElement el : descriptorElements)
+ {
+ el.append(doc, root);
+ }
+
+ writeDocument(doc, f);
+ }
+ }
+ catch (Exception ex)
+ {
+ printException("could not open plugin descriptor", ex);
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param doc
+ * @param f
+ */
+ private void writeDocument(Document doc, FileObject f)
+ {
+ Writer writer = null;
+
+ try
+ {
+ writer = new FileWriter(new File(f.toUri()));
+
+ Transformer transformer =
+ TransformerFactory.newInstance().newTransformer();
+
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.transform(new DOMSource(doc), new StreamResult(writer));
+ }
+ catch (Exception ex)
+ {
+ printException("could not write document", ex);
+ }
+ finally
+ {
+ close(writer);
+ }
+ }
+
+ //~--- inner classes --------------------------------------------------------
+
+ /**
+ * Class description
+ *
+ *
+ * @version Enter version here..., 14/03/18
+ * @author Enter your name here...
+ */
+ private static final class ClassAnnotation
+ {
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param elementName
+ * @param annotationClass
+ */
+ public ClassAnnotation(String elementName,
+ Class extends Annotation> annotationClass)
+ {
+ this.elementName = elementName;
+ this.annotationClass = annotationClass;
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private final Class extends Annotation> annotationClass;
+
+ /** Field description */
+ private final String elementName;
+ }
+}
diff --git a/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/SubscriberElement.java b/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/SubscriberElement.java
new file mode 100644
index 0000000000..eceb617393
--- /dev/null
+++ b/scm-maven-plugins/scm-annotation-processor/src/main/java/sonia/scm/annotation/SubscriberElement.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.annotation;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SubscriberElement implements DescriptorElement
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param subscriberType
+ * @param eventType
+ */
+ public SubscriberElement(String subscriberType, String eventType)
+ {
+ this.subscriberType = subscriberType;
+ this.eventType = eventType;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param doc
+ * @param root
+ */
+ @Override
+ public void append(Document doc, Element root)
+ {
+ Element subscriberEl = doc.createElement("subscriber");
+ Element classEl = doc.createElement("class");
+
+ classEl.setTextContent(subscriberType);
+ subscriberEl.appendChild(classEl);
+
+ Element eventEl = doc.createElement("event");
+
+ eventEl.setTextContent(eventType);
+ subscriberEl.appendChild(eventEl);
+ root.appendChild(subscriberEl);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private final String eventType;
+
+ /** Field description */
+ private final String subscriberType;
+}
diff --git a/scm-plugins/pom.xml b/scm-plugins/pom.xml
index 5cb3c3288c..7c0dcad4f8 100644
--- a/scm-plugins/pom.xml
+++ b/scm-plugins/pom.xml
@@ -28,6 +28,15 @@
scm-core
2.0.0-SNAPSHOT
+
+
+
+
+ sonia.scm.maven
+ scm-annotation-processor
+ 2.0.0-SNAPSHOT
+ provided
+