You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ma...@apache.org on 2019/10/03 12:21:33 UTC

[archiva] branch master updated: Finalizing event API

This is an automated email from the ASF dual-hosted git repository.

martin_s pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/archiva.git


The following commit(s) were added to refs/heads/master by this push:
     new 69a4057  Finalizing event API
69a4057 is described below

commit 69a4057630a50ff6597e02fcc3f2ccdfc9f61c0e
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Thu Oct 3 14:21:18 2019 +0200

    Finalizing event API
---
 .../src/test/java/RepositoryProviderMock.java      |   2 +-
 .../repository/mock/RepositoryProviderMock.java    |   2 +-
 .../apache/archiva/proxy/ArchivaProxyRegistry.java |   8 +-
 .../org/apache/archiva/repository/Repository.java  |   4 +-
 .../archiva/repository/RepositoryProvider.java     |   4 +-
 .../apache/archiva/repository/events/Event.java    |  74 ++++++++++----
 ...ositoryEventListener.java => EventHandler.java} |   8 +-
 .../archiva/repository/events/EventManager.java    |  79 +++++++++++++++
 ...RepositoryEventSource.java => EventSource.java} |  13 +--
 .../archiva/repository/events/EventType.java       | 108 ++++++++++++++++++++-
 .../repository/events/IndexCreationEvent.java      |  44 ---------
 .../archiva/repository/events/LifecycleEvent.java  |   9 ++
 .../archiva/repository/events/RepositoryEvent.java |   8 +-
 .../repository/events/RepositoryIndexEvent.java    |  49 ++++++++++
 .../repository/events/RepositoryRegistryEvent.java |  20 +++-
 .../repository/events/RepositoryValueEvent.java    |  18 +++-
 .../repository/features/AbstractFeature.java       |  16 +--
 .../repository/features/IndexCreationFeature.java  |  14 +--
 .../archiva/repository/AbstractRepository.java     |  57 +++--------
 .../archiva/repository/RepositoryRegistry.java     |  70 +++++--------
 .../repository/mock/RepositoryProviderMock.java    |   2 +-
 .../repository/mock/RepositoryProviderMock.java    |   2 +-
 .../repository/maven2/MavenRepositoryProvider.java |   2 +-
 23 files changed, 414 insertions(+), 199 deletions(-)

diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java b/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java
index 5302a74..1691b58 100644
--- a/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java
@@ -256,7 +256,7 @@ public class RepositoryProviderMock implements RepositoryProvider
     }
 
     @Override
-    public void raise(Event event) {
+    public void handle(Event event) {
 
     }
 
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
index c10a5a8..82959a0 100644
--- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
@@ -285,7 +285,7 @@ public class RepositoryProviderMock implements RepositoryProvider
     }
 
     @Override
-    public void raise(Event event) {
+    public void handle(Event event) {
 
     }
 }
diff --git a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java
index 4fb20b7..a42ab95 100644
--- a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java
+++ b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java
@@ -32,7 +32,7 @@ import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.RemoteRepository;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.events.RepositoryEventListener;
+import org.apache.archiva.repository.events.EventHandler;
 import org.apache.archiva.repository.events.RepositoryRegistryEvent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -51,7 +51,7 @@ import java.util.stream.Collectors;
  */
 @SuppressWarnings( "SpringJavaInjectionPointsAutowiringInspection" )
 @Service("proxyRegistry#default")
-public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListener<RepositoryRegistryEvent> {
+public class ArchivaProxyRegistry implements ProxyRegistry, EventHandler<RepositoryRegistryEvent> {
 
     private static final Logger log = LoggerFactory.getLogger(ArchivaProxyRegistry.class);
 
@@ -84,7 +84,7 @@ public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListe
         updateHandler();
         updateConnectors();
         updateNetworkProxies();
-        repositoryRegistry.register(RepositoryRegistryEvent.RELOADED, this);
+        repositoryRegistry.registerEventHandler(RepositoryRegistryEvent.RELOADED, this);
     }
 
     private ArchivaConfiguration getArchivaConfiguration() {
@@ -217,7 +217,7 @@ public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListe
     }
 
     @Override
-    public void raise(RepositoryRegistryEvent event) {
+    public void handle(RepositoryRegistryEvent event) {
         log.debug("Reload happened, updating proxy list");
         if (event.getType()== RepositoryRegistryEvent.RELOADED) {
             init();
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java
index 96cb597..c88dc63 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java
@@ -20,7 +20,7 @@ package org.apache.archiva.repository;
  */
 
 import org.apache.archiva.indexer.ArchivaIndexingContext;
-import org.apache.archiva.repository.events.RepositoryEventSource;
+import org.apache.archiva.repository.events.EventSource;
 import org.apache.archiva.repository.storage.RepositoryStorage;
 import org.apache.archiva.repository.features.RepositoryFeature;
 import org.apache.archiva.repository.storage.StorageAsset;
@@ -35,7 +35,7 @@ import java.util.Set;
  *
  * Created by Martin Stockhammer on 21.09.17.
  */
-public interface Repository extends RepositoryEventSource, RepositoryStorage {
+public interface Repository extends EventSource, RepositoryStorage {
 
     /**
      * Return the identifier of the repository. Repository identifier should be unique at least
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java
index 3a405fb..cba28e1 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java
@@ -22,7 +22,7 @@ package org.apache.archiva.repository;
 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
-import org.apache.archiva.repository.events.RepositoryEventListener;
+import org.apache.archiva.repository.events.EventHandler;
 
 import java.io.IOException;
 import java.util.Set;
@@ -40,7 +40,7 @@ import java.util.Set;
  *
  *
  */
-public interface RepositoryProvider extends RepositoryEventListener
+public interface RepositoryProvider extends EventHandler
 {
 
     /**
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
index 4b01207..dc91def 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
@@ -22,51 +22,91 @@ package org.apache.archiva.repository.events;
 import java.time.LocalDateTime;
 import java.util.EventObject;
 
-public class Event extends EventObject {
+/**
+ * Base class for events. Events have a type and a source.
+ * The source is the instance that raised the event.
+ *
+ * There are different event types for a given event. The types are represented in a hierarchical structure.
+ *
+ * Events can be chained, which means a event listener can catch events and rethrow them as its own event.
+ *
+ */
+public class Event extends EventObject implements Cloneable {
 
-    public static final EventType<Event> ANY = new EventType(null, "ANY");
+    private static final long serialVersionUID = -7171846575892044990L;
 
-    Event previous;
-    final Object originator;
-    final EventType<? extends Event> type;
-    final LocalDateTime instant;
+    public static final EventType<Event> ANY = EventType.ROOT;
+
+    private Event previous;
+    private final EventType<? extends Event> type;
+    private final LocalDateTime createTime;
 
     public Event(EventType<? extends Event> type, Object originator) {
         super(originator);
-        this.originator = originator;
         this.type = type;
-        this.instant = LocalDateTime.now();
+        this.createTime = LocalDateTime.now();
     }
 
     private Event(Event previous, Object originator) {
         super(originator);
         this.previous = previous;
-        this.originator = originator;
         this.type = previous.getType();
-        this.instant = previous.getInstant();
+        this.createTime = previous.getCreateTime();
     }
 
+    /**
+     * Returns the event type that is associated with this event instance.
+     * @return the event type
+     */
     public EventType<? extends Event> getType() {
         return type;
     };
 
-    public LocalDateTime getInstant() {
-        return instant;
+    /**
+     * Returns the time, when the event was created.
+     * @return
+     */
+    public LocalDateTime getCreateTime() {
+        return createTime;
     }
 
-    public Object getOriginator() {
-        return originator;
-    }
 
-    public Event recreate(Object newOrigin) {
-        return new Event(this, newOrigin);
+    /**
+     * Recreates the event with the given instance as the new source. The
+     * current source is stored in the previous event.
+     * @param newSource The new source
+     * @return a new event instance, where <code>this</code> is stored as previous event
+     */
+    public Event copyFor(Object newSource) {
+        Event newEvent = (Event) this.clone();
+        newEvent.previous = this;
+        newEvent.source = newSource;
+        return newEvent;
     }
 
+    /**
+     * Returns the previous event or <code>null</code>, if this is a root event.
+     * @return the previous event or <code>null</code>, if it does not exist
+     */
     public Event getPreviousEvent() {
         return previous;
     }
 
+    /**
+     * Returns <code>true</code>, if the event has a previous event.
+     * @return <code>true</code>, if this has a previous event, otherwise <code>false</code>
+     */
     public boolean hasPreviousEvent() {
         return previous!=null;
     }
+
+    @Override
+    protected Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            // this should not happen
+            throw new RuntimeException("Event is not clonable");
+        }
+    }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventHandler.java
similarity index 83%
rename from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java
rename to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventHandler.java
index ffedc42..9f2d441 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventHandler.java
@@ -19,10 +19,12 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
+import java.util.EventListener;
+
 /**
- * A listener that accepts repository events.
+ * A listener that accepts events.
  */
-public interface RepositoryEventListener<T extends Event> {
+public interface EventHandler<T extends Event> extends EventListener {
 
-    void raise(T event);
+    void handle(T event);
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventManager.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventManager.java
new file mode 100644
index 0000000..694cfd9
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventManager.java
@@ -0,0 +1,79 @@
+package org.apache.archiva.repository.events;
+
+/*
+ * 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.
+ */
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class EventManager implements EventSource {
+
+    private static final Logger log = LoggerFactory.getLogger(EventManager.class);
+
+    private final ConcurrentHashMap<EventType<? extends Event>, Set<EventHandler>> handlerMap = new ConcurrentHashMap<>();
+
+    private final Object source;
+
+    public EventManager(Object source) {
+        if (source==null) {
+            throw new IllegalArgumentException("The source may not be null");
+        }
+        this.source = source;
+    }
+
+    @Override
+    public <T extends Event> void registerEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
+        Set<EventHandler> handlers = handlerMap.computeIfAbsent(type, t -> new LinkedHashSet<>());
+        if (!handlers.contains(eventHandler)) {
+            handlers.add(eventHandler);
+        }
+    }
+
+    @Override
+    public <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
+        if (handlerMap.containsKey(type)) {
+            handlerMap.get(type).remove(eventHandler);
+        }
+    }
+
+    public void fireEvent(Event fireEvent) {
+        final EventType<? extends Event> type = fireEvent.getType();
+        Event event;
+        if (fireEvent.getSource()!=source) {
+            event = fireEvent.copyFor(source);
+        } else {
+            event = fireEvent;
+        }
+        for (EventType<? extends Event> handlerType : handlerMap.keySet()) {
+            if (EventType.isInstanceOf(type, handlerType)) {
+                    for (EventHandler handler : handlerMap.get(handlerType)) {
+                        try {
+                            handler.handle(event);
+                        } catch (Exception e) {
+                            // We catch all errors from handlers
+                            log.error("An error occured during event handling: {}", e.getMessage(), e);
+                        }
+                    }
+            }
+        }
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventSource.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventSource.java
similarity index 65%
rename from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventSource.java
rename to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventSource.java
index f26eb78..cffaeaf 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventSource.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventSource.java
@@ -19,18 +19,15 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
-import java.util.Set;
-
 /**
- * A repository event handler raises events to its registered listeners.
- * Listeners may register for all events that are raised or only to a subset of events.
+ * A repository event source raises events to its registered listeners.
+ * Listeners register to event types that are structured hierarchical.
  *
  */
-public interface RepositoryEventSource {
+public interface EventSource {
 
-    <T extends Event> void register(EventType<T> type, RepositoryEventListener<? super T> listener);
+    <T extends Event> void registerEventHandler(EventType<T> type, EventHandler<? super T> eventHandler);
 
-    <T extends Event> void unregister(EventType<T> type, RepositoryEventListener<? super T> listener);
+    <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler);
 
-    void clearListeners();
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java
index 4162f9a..ab9678a 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java
@@ -19,17 +19,59 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.List;
+import java.io.InvalidObjectException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Event types define a hierarchical structure of events. Each event is bound to a certain event type.
+ * All event types have a super type, only the root event type {@link EventType#ROOT} has no super type.
+ *
+ * Event types should be stored as static fields on the events itself.
+ *
+ * @param <T> The type class parameter allows to define the types in a type safe way and represents a event class,
+ *           where the type is associated to.
+ */
+public class EventType<T extends Event> implements Serializable  {
 
-public class EventType<T extends Event> {
+
+    public static final EventType<Event> ROOT = new EventType<>();
 
     private final String name;
     private final EventType<? super T> superType;
+    private WeakHashMap<EventType<? extends T>, Void> subTypes;
+
+    /**
+     * Creates a type with the given name and the root type as parent.
+     * @param name the name of the new type
+     */
+    public EventType(String name) {
+        this.superType = ROOT;
+        this.name = name;
+    }
 
+    /**
+     * Creates a event type instance with the given super type and name.
+     *
+     * @param superType The super type or <code>null</code>, if this is the root type.
+     * @param name
+     */
     public EventType(EventType<? super T> superType, String name) {
+        if (superType==null) {
+            throw new NullPointerException("Super Type may not be null");
+        }
         this.name = name;
         this.superType = superType;
+        superType.register(this);
+    }
+
+    /**
+     * Creates the root type
+     */
+    private EventType() {
+        this.name="ROOT";
+        this.superType=null;
     }
 
     public String name() {
@@ -40,6 +82,19 @@ public class EventType<T extends Event> {
         return superType;
     }
 
+    private void register(EventType<? extends T> subType) {
+        if (subTypes == null) {
+            subTypes = new WeakHashMap<>();
+        }
+        for (EventType<? extends T> t : subTypes.keySet()) {
+            if (((t.name == null && subType.name == null) || (t.name != null && t.name.equals(subType.name)))) {
+                throw new IllegalArgumentException("EventType \"" + subType + "\""
+                        + "with parent \"" + subType.getSuperType()+"\" already exists");
+            }
+        }
+        subTypes.put(subType, null);
+    }
+
 
     public static List<EventType<?>> fetchSuperTypes(EventType<?> type) {
         List<EventType<?>> typeList = new ArrayList<>();
@@ -61,4 +116,51 @@ public class EventType<T extends Event> {
         }
         return false;
     }
+
+
+    private Object writeReplace() throws ObjectStreamException {
+        Deque<String> path = new LinkedList<String>();
+        EventType<?> t = this;
+        while (t != ROOT) {
+            path.addFirst(t.name);
+            t = t.superType;
+        }
+        return new EventTypeSerialization(new ArrayList<>(path));
+    }
+
+    static class EventTypeSerialization implements Serializable {
+        private static final long serialVersionUID = 1841649460281865547L;
+        private List<String> path;
+
+        public EventTypeSerialization(List<String> path) {
+            this.path = path;
+        }
+
+        private Object readResolve() throws ObjectStreamException {
+            EventType t = ROOT;
+            for (int i = 0; i < path.size(); ++i) {
+                String p = path.get(i);
+                if (t.subTypes != null) {
+                    EventType<?> s = findSubType(t.subTypes.keySet(), p);
+                    if (s == null) {
+                        throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")");
+                    }
+                    t = s;
+                } else {
+                    throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")");
+                }
+            }
+            return t;
+        }
+
+        private EventType<?> findSubType(Set<EventType> subTypes, String name) {
+            for (EventType t : subTypes) {
+                if (((t.name == null && name == null) || (t.name != null && t.name.equals(name)))) {
+                    return t;
+                }
+            }
+            return null;
+        }
+
+    }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/IndexCreationEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/IndexCreationEvent.java
deleted file mode 100644
index 9a21834..0000000
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/IndexCreationEvent.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.apache.archiva.repository.events;
-
-/*
- * 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.
- */
-
-
-import org.apache.archiva.repository.Repository;
-
-import java.net.URI;
-
-public class IndexCreationEvent extends RepositoryValueEvent<URI> {
-
-    public static EventType<IndexCreationEvent> ANY = new EventType<>(RepositoryValueEvent.ANY, "REPOSITORY.VALUE.INDEX");
-    public static EventType<IndexCreationEvent> INDEX_URI_CHANGED = new EventType<>(ANY, "REPOSITORY.VALUE.INDEX.URI_CHANGED");
-    public static EventType<IndexCreationEvent> PACKED_INDEX_URI_CHANGED = new EventType<>(ANY, "REPOSITORY.VALUE.INDEX.PACKED_URI_CHANGED");
-
-    IndexCreationEvent(EventType<? extends IndexCreationEvent> type, Object origin, Repository repo, URI oldValue, URI value) {
-        super(type, origin, repo, oldValue, value);
-    }
-
-    public static final <O> IndexCreationEvent indexUriChange(O origin, Repository repo, URI oldValue, URI newValue) {
-        return new IndexCreationEvent(INDEX_URI_CHANGED, origin, repo, oldValue, newValue);
-    }
-
-    public static final <O> IndexCreationEvent packedIndexUriChange(O origin, Repository repo, URI oldValue, URI newValue) {
-        return new IndexCreationEvent(PACKED_INDEX_URI_CHANGED, origin, repo, oldValue, newValue);
-    }
-}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
index 9197b58..6408eb5 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
@@ -21,8 +21,17 @@ package org.apache.archiva.repository.events;
 
 import org.apache.archiva.repository.Repository;
 
+/**
+ * Raises events about the repository lifecycle. The following events are raised:
+ * <ul>
+ *     <li>REGISTERED: a repository has been registered by the repository registry</li>
+ *     <li>UNREGISTERED: a repository has been removed by the repository registry</li>
+ *     <li>UPDATED: A repository attribute was updated</li>
+ * </ul>
+ */
 public class LifecycleEvent extends RepositoryEvent {
 
+    private static final long serialVersionUID = -2520982087439428714L;
     public static EventType<LifecycleEvent> ANY = new EventType<>(RepositoryEvent.ANY, "REPOSITORY.LIFECYCLE");
     public static EventType<LifecycleEvent> REGISTERED = new EventType<>(ANY, "REPOSITORY.LIFECYCLE.REGISTERED");
     public static EventType<LifecycleEvent> UNREGISTERED = new EventType<>(ANY, "REPOSITORY.LIFECYCLE.UNREGISTERED");
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
index 24ea42c..28d4770 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
@@ -21,9 +21,15 @@ package org.apache.archiva.repository.events;
 
 import org.apache.archiva.repository.Repository;
 
+/**
+ * A repository event is specific to a repository and holds a reference to the repository that
+ * is related to this event.
+ */
 public class RepositoryEvent extends Event {
 
-    public static final EventType<RepositoryEvent> ANY = new EventType<>(Event.ANY, "REPOSITORY.UPDATED");
+    private static final long serialVersionUID = 4676673476606414834L;
+
+    public static final EventType<RepositoryEvent> ANY = new EventType<>(Event.ANY, "REPOSITORY");
 
     private final Repository repository;
 
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryIndexEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryIndexEvent.java
new file mode 100644
index 0000000..9f1b2a6
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryIndexEvent.java
@@ -0,0 +1,49 @@
+package org.apache.archiva.repository.events;
+
+/*
+ * 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.
+ */
+
+
+import org.apache.archiva.repository.Repository;
+
+import java.net.URI;
+
+/**
+ * These events are thrown, when index information has changed.
+ */
+public class RepositoryIndexEvent extends RepositoryValueEvent<URI> {
+
+    private static final long serialVersionUID = -7801989699524776524L;
+
+    public static EventType<RepositoryIndexEvent> ANY = new EventType<>(RepositoryValueEvent.ANY, "REPOSITORY.VALUE.INDEX");
+    public static EventType<RepositoryIndexEvent> INDEX_URI_CHANGED = new EventType<>(ANY, "REPOSITORY.VALUE.INDEX.URI_CHANGED");
+    public static EventType<RepositoryIndexEvent> PACKED_INDEX_URI_CHANGED = new EventType<>(ANY, "REPOSITORY.VALUE.INDEX.PACKED_URI_CHANGED");
+
+    RepositoryIndexEvent(EventType<? extends RepositoryIndexEvent> type, Object origin, Repository repo, URI oldValue, URI value) {
+        super(type, origin, repo, oldValue, value, "index.uri");
+    }
+
+    public static final <O> RepositoryIndexEvent indexUriChange(O origin, Repository repo, URI oldValue, URI newValue) {
+        return new RepositoryIndexEvent(INDEX_URI_CHANGED, origin, repo, oldValue, newValue);
+    }
+
+    public static final <O> RepositoryIndexEvent packedIndexUriChange(O origin, Repository repo, URI oldValue, URI newValue) {
+        return new RepositoryIndexEvent(PACKED_INDEX_URI_CHANGED, origin, repo, oldValue, newValue);
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
index 2b9ac76..fbaa971 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
@@ -19,11 +19,29 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
+/**
+ * Repository registry events are raised by the repository registry itself.
+ */
 public class RepositoryRegistryEvent extends Event {
 
-    public static EventType<RepositoryRegistryEvent> ANY = new EventType(Event.ANY, "REGISTRY");
+    private static final long serialVersionUID = -4740127827269612094L;
+
+    /**
+     * All repository registry events
+     */
+    public static EventType<RepositoryRegistryEvent> ANY = new EventType(EventType.ROOT, "REGISTRY");
+    /**
+     * When the registry has reloaded the registry data from the configuration
+     */
     public static EventType<RepositoryRegistryEvent> RELOADED = new EventType(ANY, "REGISTRY.RELOADED");
+    /**
+     * When the registry was destroyed. Repository instances may still be referenced, but are not updated.
+     */
     public static EventType<RepositoryRegistryEvent> DESTROYED = new EventType(ANY, "REGISTRY.DESTROYED");
+    /**
+     * When the registry was initialized
+     */
+    public static EventType<RepositoryRegistryEvent> INITIALIZED = new EventType(ANY, "REGISTRY.INITIALIZED");
 
     public RepositoryRegistryEvent(EventType<? extends RepositoryRegistryEvent> type, Object origin) {
         super(type, origin);
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java
index b5f8146..448d720 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java
@@ -22,21 +22,27 @@ package org.apache.archiva.repository.events;
 import org.apache.archiva.repository.Repository;
 
 /**
- * Repository event. Repository events are used for providing information about repository changes.
+ * Repository value events are used for providing information about repository attribute changes.
+ * The value event gives information of the attribute value before and after the change.
  *
- * @param <V>
+ * @param <V> The type of the changed attribute
  */
 public class RepositoryValueEvent<V> extends RepositoryEvent {
 
-    public static final EventType<RepositoryValueEvent<?>> ANY = new EventType(RepositoryEvent.ANY, "REPOSITORY.VALUE.UPDATED");
+    private static final long serialVersionUID = 4176597620699304794L;
+
+    public static final EventType<RepositoryValueEvent<?>> ANY = new EventType(RepositoryEvent.ANY, "REPOSITORY.VALUE");
 
     final V value;
     final V oldValue;
+    final String attributeName;
 
-    public RepositoryValueEvent(EventType<? extends RepositoryValueEvent<V>> type, Object origin, Repository repo, V oldValue, V value) {
+    public RepositoryValueEvent(EventType<? extends RepositoryValueEvent<V>> type, Object origin, Repository repo, V oldValue, V value,
+                                String attributeName) {
         super(type, origin, repo);
         this.value = value;
         this.oldValue = oldValue;
+        this.attributeName = attributeName;
     }
 
     public V getValue() {
@@ -47,4 +53,8 @@ public class RepositoryValueEvent<V> extends RepositoryEvent {
         return oldValue;
     }
 
+    public String getAttributeName() {
+        return attributeName;
+    }
+
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/AbstractFeature.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/AbstractFeature.java
index 6b64d93..60a1dce 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/AbstractFeature.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/AbstractFeature.java
@@ -20,35 +20,35 @@ package org.apache.archiva.repository.features;
  */
 
 import org.apache.archiva.repository.events.Event;
-import org.apache.archiva.repository.events.RepositoryEventListener;
+import org.apache.archiva.repository.events.EventHandler;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
 public class AbstractFeature {
-    private List<RepositoryEventListener> listener = new ArrayList<>();
+    private List<EventHandler> listener = new ArrayList<>();
 
     AbstractFeature() {
 
     }
 
-    AbstractFeature(RepositoryEventListener listener) {
+    AbstractFeature(EventHandler listener) {
         this.listener.add(listener);
     }
 
-    AbstractFeature(Collection<RepositoryEventListener> listeners) {
+    AbstractFeature(Collection<EventHandler> listeners) {
         this.listener.addAll(listeners);
     }
 
-    public void addListener(RepositoryEventListener listener) {
+    public void addListener(EventHandler listener) {
         if (!this.listener.contains(listener)) {
             this.listener.add(listener);
         }
         this.listener.add(listener);
     }
 
-    public void removeListener(RepositoryEventListener listener) {
+    public void removeListener(EventHandler listener) {
         this.listener.remove(listener);
     }
 
@@ -57,8 +57,8 @@ public class AbstractFeature {
     }
 
     public void pushEvent(Event event) {
-        for(RepositoryEventListener listr : listener) {
-            listr.raise(event);
+        for(EventHandler listr : listener) {
+            listr.handle(event);
         }
     }
 
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java
index f834be1..f9de498 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java
@@ -21,8 +21,8 @@ package org.apache.archiva.repository.features;
 
 
 import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.events.IndexCreationEvent;
-import org.apache.archiva.repository.events.RepositoryEventListener;
+import org.apache.archiva.repository.events.RepositoryIndexEvent;
+import org.apache.archiva.repository.events.EventHandler;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.commons.lang3.StringUtils;
 
@@ -44,7 +44,7 @@ import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_PACKED_INDE
  * A index may have a remote and a local representation. The remote representation is used for downloading and
  * updating the local representation.
  *
- * The feature is throwing a {@link IndexCreationEvent}, if the URI of the index has been changed.
+ * The feature is throwing a {@link RepositoryIndexEvent}, if the URI of the index has been changed.
  *
  */
 public class IndexCreationFeature extends AbstractFeature implements RepositoryFeature<IndexCreationFeature>{
@@ -62,7 +62,7 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
 
     private Repository repo;
 
-    public IndexCreationFeature(Repository repository, RepositoryEventListener listener) {
+    public IndexCreationFeature(Repository repository, EventHandler listener) {
         super(listener);
         this.repo = repository;
         try {
@@ -129,7 +129,7 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
         if ((this.indexPath==null && indexPath!=null) || !this.indexPath.equals(indexPath)) {
             URI oldVal = this.indexPath;
             this.indexPath = indexPath;
-            pushEvent(IndexCreationEvent.indexUriChange(this, repo, oldVal, this.indexPath));
+            pushEvent(RepositoryIndexEvent.indexUriChange(this, repo, oldVal, this.indexPath));
         }
 
     }
@@ -173,14 +173,14 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
     /**
      * Sets the path (relative or absolute) of the packed index.
      *
-     * Throws a {@link IndexCreationEvent.Index#PACKED_INDEX_URI_CHANGE}, if the value changes.
+     * Throws a {@link RepositoryIndexEvent.Index#PACKED_INDEX_URI_CHANGE}, if the value changes.
      *
      * @param packedIndexPath the new path uri for the packed index
      */
     public void setPackedIndexPath(URI packedIndexPath) {
         URI oldVal = this.packedIndexPath;
         this.packedIndexPath = packedIndexPath;
-        pushEvent(IndexCreationEvent.packedIndexUriChange(this, repo, oldVal, this.packedIndexPath));
+        pushEvent(RepositoryIndexEvent.packedIndexUriChange(this, repo, oldVal, this.packedIndexPath));
     }
 
     /**
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
index 5a5aa6c..3172c7e 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
@@ -56,7 +56,7 @@ import java.util.function.Consumer;
  * No features are provided. Capabilities and features must be implemented by concrete classes.
  *
  */
-public abstract class AbstractRepository implements EditableRepository, RepositoryEventListener<RepositoryEvent>
+public abstract class AbstractRepository implements EditableRepository, EventHandler<RepositoryEvent>
 {
 
 
@@ -80,8 +80,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     private String layout = "default";
     public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
 
-    private Map<EventType<? extends RepositoryEvent>, List<RepositoryEventListener<? extends RepositoryEvent>>> listenerTypeMap = new HashMap<>();
-
+    private final EventManager eventManager;
 
     Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>(  );
 
@@ -95,6 +94,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
         this.storage = repositoryStorage;
         this.location = repositoryStorage.getLocation();
         this.openStatus.compareAndSet(false, true);
+        this.eventManager = new EventManager(this);
     }
 
     public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
@@ -105,6 +105,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
         this.storage = repositoryStorage;
         this.location = repositoryStorage.getLocation();
         this.openStatus.compareAndSet(false, true);
+        this.eventManager = new EventManager(this);
     }
 
     protected void setPrimaryLocale(Locale locale) {
@@ -324,8 +325,8 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
                     sf.getStagingRepository().close();
                 }
             }
-            clearListeners();
         }
+
     }
 
     @Override
@@ -334,56 +335,22 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     }
 
     @Override
-    public void raise(RepositoryEvent event) {
-        final EventType<? extends Event> currentType = event.getType();
-        for (EventType<? extends RepositoryEvent> type : listenerTypeMap.keySet()) {
-            if (EventType.isInstanceOf(currentType, type)) {
-                callListeners(event, listenerTypeMap.get(type));
-            }
-        }
-    }
-
-    private void callListeners(RepositoryEvent event, List<RepositoryEventListener<? extends RepositoryEvent>> evtListeners) {
-        for(RepositoryEventListener listener : evtListeners) {
-            try {
-                listener.raise(event.recreate(this));
-            } catch (Throwable e) {
-                log.error("Could not raise event {} on listener {}: {}", event, listener, e.getMessage());
-            }
-        }
-
+    public void handle(RepositoryEvent event) {
+        // We just rethrow the events
+        eventManager.fireEvent(event);
     }
 
     @Override
-    public <T extends Event> void register(EventType<T> eventType, RepositoryEventListener<? super T> listener) {
+    public <T extends Event> void registerEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler) {
         if (!EventType.isInstanceOf(eventType, RepositoryEvent.ANY)) {
             throw new IllegalArgumentException("Can only register RepositoryEvent Handlers");
         }
-        final RepositoryEventListener<? extends RepositoryEvent> myListener = (RepositoryEventListener<? extends RepositoryEvent>) listener;
-        final EventType<? extends RepositoryEvent> type = (EventType<? extends RepositoryEvent>) eventType;
-
-        List<RepositoryEventListener<? extends RepositoryEvent>> listeners;
-        if (listenerTypeMap.containsKey(type)) {
-            listeners = listenerTypeMap.get(type);
-        } else {
-            listeners = new ArrayList<>();
-            listenerTypeMap.put(type, listeners);
-        }
-        if (!listeners.contains(listener)) {
-            listeners.add(myListener);
-        }
-    }
-
-    @Override
-    public <T extends Event> void unregister(EventType<T> type, RepositoryEventListener<? super T> listener) {
-        for (List<RepositoryEventListener<? extends RepositoryEvent>> listeners : listenerTypeMap.values()) {
-            listeners.remove(listener);
-        }
+        eventManager.registerEventHandler(eventType, eventHandler);
     }
 
     @Override
-    public void clearListeners() {
-        this.listenerTypeMap.clear();
+    public <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
+        eventManager.unregisterEventHandler(type, eventHandler);
     }
 
     @Override
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
index 07e7300..998b79b 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
@@ -23,6 +23,7 @@ import org.apache.archiva.configuration.*;
 import org.apache.archiva.indexer.*;
 import org.apache.archiva.redback.components.registry.RegistryException;
 import org.apache.archiva.repository.events.*;
+import org.apache.archiva.repository.events.EventHandler;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.StagingRepositoryFeature;
 import org.apache.commons.lang3.StringUtils;
@@ -53,7 +54,7 @@ import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
  * @since 3.0
  */
 @Service("repositoryRegistry")
-public class RepositoryRegistry implements ConfigurationListener, RepositoryEventSource, RepositoryEventListener<Event> {
+public class RepositoryRegistry implements ConfigurationListener, EventSource, EventHandler<Event> {
 
     private static final Logger log = LoggerFactory.getLogger(RepositoryRegistry.class);
 
@@ -73,7 +74,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     @Named("repositoryContentFactory#default")
     RepositoryContentFactory repositoryContentFactory;
 
-    private Map<EventType<? extends Event>, List<RepositoryEventListener<? extends Event>>> typeListenerMap = new HashMap<>();
+    private final EventManager eventManager;
 
 
     private Map<String, ManagedRepository> managedRepositories = new HashMap<>();
@@ -89,6 +90,10 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
 
     private volatile boolean ignoreConfigEvents = false;
 
+    public RepositoryRegistry() {
+        this.eventManager = new EventManager(this);
+    }
+
     public void setArchivaConfiguration(ArchivaConfiguration archivaConfiguration) {
         this.archivaConfiguration = archivaConfiguration;
     }
@@ -181,7 +186,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     private ManagedRepository createNewManagedRepository(RepositoryProvider provider, ManagedRepositoryConfiguration cfg) throws RepositoryException {
         log.debug("Creating repo {}", cfg.getId());
         ManagedRepository repo = provider.createManagedInstance(cfg);
-        repo.register(RepositoryEvent.ANY,  this);
+        repo.registerEventHandler(RepositoryEvent.ANY,  this);
         updateRepositoryReferences(provider, repo, cfg, null);
         return repo;
 
@@ -221,7 +226,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 createIndexingContext(editableRepo);
             }
         }
-        repo.register(RepositoryEvent.ANY, this);
+        repo.registerEventHandler(RepositoryEvent.ANY, this);
     }
 
     public ArchivaIndexManager getIndexManager(RepositoryType type) {
@@ -296,7 +301,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 createIndexingContext(editableRepo);
             }
         }
-        repo.register(RepositoryEvent.ANY, this);
+        repo.registerEventHandler(RepositoryEvent.ANY, this);
     }
 
     private Map<String, RepositoryGroup> getRepositorGroupsFromConfig() {
@@ -331,7 +336,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
 
     private RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException {
         RepositoryGroup repositoryGroup = provider.createRepositoryGroup(config);
-        repositoryGroup.register(RepositoryEvent.ANY, this);
+        repositoryGroup.registerEventHandler(RepositoryEvent.ANY, this);
         updateRepositoryReferences(provider, repositoryGroup, config);
         return repositoryGroup;
     }
@@ -1171,7 +1176,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration(repo);
         cfg.setId(newId);
         ManagedRepository cloned = provider.createManagedInstance(cfg);
-        cloned.register(RepositoryEvent.ANY, this);
+        cloned.registerEventHandler(RepositoryEvent.ANY, this);
         return cloned;
     }
 
@@ -1200,7 +1205,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration(repo);
         cfg.setId(newId);
         RemoteRepository cloned = provider.createRemoteInstance(cfg);
-        cloned.register(RepositoryEvent.ANY, this);
+        cloned.registerEventHandler(RepositoryEvent.ANY, this);
         return cloned;
     }
 
@@ -1215,47 +1220,32 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
 
 
     @Override
-    public <T extends Event> void register(EventType<T> type, RepositoryEventListener<? super T> listener) {
-        List<RepositoryEventListener<?>> listeners;
-        if (typeListenerMap.containsKey(type)) {
-            listeners = typeListenerMap.get(type);
-        } else {
-            listeners = new ArrayList<>();
-            typeListenerMap.put(type, listeners);
-        }
-        if (!listeners.contains(listener)) {
-            listeners.add(listener);
-        }
+    public <T extends Event> void registerEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
+        eventManager.registerEventHandler(type, eventHandler);
     }
 
 
     @Override
-    public <T extends Event> void unregister(EventType<T> type, RepositoryEventListener<? super T> listener) {
-        for (List<RepositoryEventListener<?>> listeners : typeListenerMap.values()) {
-            listeners.remove(listener);
-        }
+    public <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) {
+        eventManager.unregisterEventHandler(type, eventHandler);
     }
 
-    @Override
-    public void clearListeners() {
-        this.typeListenerMap.clear();
-    }
 
     @Override
-    public void raise(Event event) {
+    public void handle(Event event) {
         // To avoid event cycles:
         if (sameOriginator(event)) {
             return;
         }
-        if (event instanceof IndexCreationEvent) {
-            handleIndexCreationEvent((IndexCreationEvent) event);
+        if (event instanceof RepositoryIndexEvent) {
+            handleIndexCreationEvent((RepositoryIndexEvent) event);
         }
         // We propagate all events to our listeners, but with context of repository registry
-        pushEvent(event.recreate(this));
+        pushEvent(event);
     }
 
-    private void handleIndexCreationEvent(IndexCreationEvent event) {
-        IndexCreationEvent idxEvent = event;
+    private void handleIndexCreationEvent(RepositoryIndexEvent event) {
+        RepositoryIndexEvent idxEvent = event;
         if (managedRepositories.containsKey(idxEvent.getRepository().getId()) ||
                 remoteRepositories.containsKey(idxEvent.getRepository().getId())) {
             EditableRepository repo = (EditableRepository) idxEvent.getRepository();
@@ -1276,7 +1266,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     }
 
     private boolean sameOriginator(Event event) {
-        if (event.getOriginator() == this) {
+        if (event.getSource() == this) {
             return true;
         } else if (event.hasPreviousEvent()) {
             return sameOriginator(event.getPreviousEvent());
@@ -1286,19 +1276,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     }
 
     private void pushEvent(Event event) {
-        final EventType<? extends Event> currentType = event.getType();
-        for (EventType<? extends Event> type : typeListenerMap.keySet()) {
-            if (EventType.isInstanceOf(currentType, type)) {
-                callListeners(event, typeListenerMap.get(type));
-            }
-        }
+        eventManager.fireEvent(event);
     }
 
-    private void callListeners(Event event, List<RepositoryEventListener<? extends Event>> listeners) {
-        for (RepositoryEventListener listener : listeners) {
-            listener.raise(event);
-        }
-    }
 
 
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
index 0f75218..801f519 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
@@ -261,7 +261,7 @@ public class RepositoryProviderMock implements RepositoryProvider
     }
 
     @Override
-    public void raise(Event event) {
+    public void handle(Event event) {
 
     }
 }
diff --git a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
index 0a8c573..04ff8c0 100644
--- a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
+++ b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
@@ -281,7 +281,7 @@ public class RepositoryProviderMock implements RepositoryProvider
     }
 
     @Override
-    public void raise(Event event) {
+    public void handle(Event event) {
 
     }
 }
diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenRepositoryProvider.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenRepositoryProvider.java
index ec78a94..b477af2 100644
--- a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenRepositoryProvider.java
+++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenRepositoryProvider.java
@@ -509,7 +509,7 @@ public class MavenRepositoryProvider implements RepositoryProvider {
     }
 
     @Override
-    public void raise(Event event) {
+    public void handle(Event event) {
         //
     }