]> source.dussan.org Git - archiva.git/commitdiff
Refactoring event API
authorMartin Stockhammer <martin_s@apache.org>
Tue, 1 Oct 2019 21:11:54 +0000 (23:11 +0200)
committerMartin Stockhammer <martin_s@apache.org>
Tue, 1 Oct 2019 21:11:54 +0000 (23:11 +0200)
14 files changed:
archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/IndexCreationEvent.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventHandler.java [deleted file]
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventSource.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java

index b59091a4cb11bc417757ac29ae3be3d31382415a..4fb20b7afbfdb65e35aef43d3d0f1714ec417341 100644 (file)
@@ -19,15 +19,19 @@ package org.apache.archiva.proxy;
  * under the License.
  */
 
-import org.apache.archiva.configuration.*;
+import org.apache.archiva.configuration.ArchivaConfiguration;
+import org.apache.archiva.configuration.NetworkProxyConfiguration;
+import org.apache.archiva.configuration.ProxyConnectorConfiguration;
 import org.apache.archiva.policies.Policy;
 import org.apache.archiva.policies.PolicyOption;
 import org.apache.archiva.policies.PolicyUtil;
 import org.apache.archiva.proxy.model.NetworkProxy;
 import org.apache.archiva.proxy.model.ProxyConnector;
 import org.apache.archiva.proxy.model.RepositoryProxyHandler;
-import org.apache.archiva.repository.*;
-import org.apache.archiva.repository.events.Event;
+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.RepositoryRegistryEvent;
 import org.slf4j.Logger;
@@ -47,7 +51,7 @@ import java.util.stream.Collectors;
  */
 @SuppressWarnings( "SpringJavaInjectionPointsAutowiringInspection" )
 @Service("proxyRegistry#default")
-public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListener {
+public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListener<RepositoryRegistryEvent> {
 
     private static final Logger log = LoggerFactory.getLogger(ArchivaProxyRegistry.class);
 
@@ -80,7 +84,7 @@ public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListe
         updateHandler();
         updateConnectors();
         updateNetworkProxies();
-        repositoryRegistry.register(this, RepositoryRegistryEvent.RegistryEventType.RELOADED);
+        repositoryRegistry.register(RepositoryRegistryEvent.RELOADED, this);
     }
 
     private ArchivaConfiguration getArchivaConfiguration() {
@@ -213,9 +217,9 @@ public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListe
     }
 
     @Override
-    public void raise(Event event) {
+    public void raise(RepositoryRegistryEvent event) {
         log.debug("Reload happened, updating proxy list");
-        if (event.getType()== RepositoryRegistryEvent.RegistryEventType.RELOADED) {
+        if (event.getType()== RepositoryRegistryEvent.RELOADED) {
             init();
         }
     }
index b26627f108b6cbfcef7d6764a7b5e28867a2e5c3..96cb597e3d85e4f9cb58f7569b549f328c518818 100644 (file)
@@ -20,7 +20,7 @@ package org.apache.archiva.repository;
  */
 
 import org.apache.archiva.indexer.ArchivaIndexingContext;
-import org.apache.archiva.repository.events.RepositoryEventHandler;
+import org.apache.archiva.repository.events.RepositoryEventSource;
 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 RepositoryEventHandler, RepositoryStorage {
+public interface Repository extends RepositoryEventSource, RepositoryStorage {
 
     /**
      * Return the identifier of the repository. Repository identifier should be unique at least
index 7ba7f34b02cf28143bdce2f9f6683167b2ba2224..4b01207760629e8fa3b2131aae9d0b2cf9d76540 100644 (file)
@@ -20,28 +20,33 @@ package org.apache.archiva.repository.events;
  */
 
 import java.time.LocalDateTime;
+import java.util.EventObject;
 
-public class Event<O> {
+public class Event extends EventObject {
+
+    public static final EventType<Event> ANY = new EventType(null, "ANY");
 
     Event previous;
-    final O originator;
-    final EventType type;
+    final Object originator;
+    final EventType<? extends Event> type;
     final LocalDateTime instant;
 
-    public <OO extends O> Event(EventType type, OO originator) {
+    public Event(EventType<? extends Event> type, Object originator) {
+        super(originator);
         this.originator = originator;
         this.type = type;
         this.instant = LocalDateTime.now();
     }
 
-    private <OO> Event(Event<OO> previous, O originator) {
+    private Event(Event previous, Object originator) {
+        super(originator);
         this.previous = previous;
         this.originator = originator;
         this.type = previous.getType();
         this.instant = previous.getInstant();
     }
 
-    public EventType getType() {
+    public EventType<? extends Event> getType() {
         return type;
     };
 
@@ -49,11 +54,11 @@ public class Event<O> {
         return instant;
     }
 
-    public O getOriginator() {
+    public Object getOriginator() {
         return originator;
     }
 
-    public <NO> Event<NO> recreate(NO newOrigin) {
+    public Event recreate(Object newOrigin) {
         return new Event(this, newOrigin);
     }
 
index 5004a15266665acc11fb2c2e6c5aa169895151f9..4162f9ac1733da37148516436256cf46c3b04ab2 100644 (file)
@@ -19,7 +19,46 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
-public interface EventType {
+import java.util.ArrayList;
+import java.util.List;
 
-    String name();
+public class EventType<T extends Event> {
+
+    private final String name;
+    private final EventType<? super T> superType;
+
+    public EventType(EventType<? super T> superType, String name) {
+        this.name = name;
+        this.superType = superType;
+    }
+
+    public String name() {
+        return name;
+    }
+
+    public EventType<? super T> getSuperType() {
+        return superType;
+    }
+
+
+    public static List<EventType<?>> fetchSuperTypes(EventType<?> type) {
+        List<EventType<?>> typeList = new ArrayList<>();
+        EventType<?> cType = type;
+        while (cType!=null) {
+            typeList.add(cType);
+            cType = cType.getSuperType();
+        }
+        return typeList;
+    }
+
+    public static boolean isInstanceOf(EventType<?> type, EventType<?> baseType) {
+        EventType<?> cType = type;
+        while(cType!=null) {
+            if (cType == baseType) {
+                return true;
+            }
+            cType = cType.getSuperType();
+        }
+        return false;
+    }
 }
index 847b679a93dda3cae6dda07121030ac3f2ea0cf2..9a21834703f42df49335a52820ada9d525ff0012 100644 (file)
@@ -19,29 +19,26 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
+
 import org.apache.archiva.repository.Repository;
 
 import java.net.URI;
 
-public class IndexCreationEvent<O> extends RepositoryValueEvent<O, URI> {
-
-    public enum Index implements EventType {
-        INDEX_URI_CHANGE, PACKED_INDEX_URI_CHANGE
-    }
+public class IndexCreationEvent extends RepositoryValueEvent<URI> {
 
-    IndexCreationEvent(Repository repo, O origin, URI oldValue, URI value) {
-        super(Index.INDEX_URI_CHANGE, origin, repo, oldValue, value);
-    }
+    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(Index type, O origin, Repository repo, URI oldValue, URI value) {
+    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.INDEX_URI_CHANGE, origin, repo, oldValue, 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(Index.PACKED_INDEX_URI_CHANGE, origin, repo, oldValue, newValue);
+        return new IndexCreationEvent(PACKED_INDEX_URI_CHANGED, origin, repo, oldValue, newValue);
     }
 }
index 2c55dd8421aa033d392f3e597f2d48f7c308048d..9197b580a46718a661dbbf53f444b0395b5aed44 100644 (file)
@@ -21,13 +21,14 @@ package org.apache.archiva.repository.events;
 
 import org.apache.archiva.repository.Repository;
 
-public class LifecycleEvent<O> extends RepositoryEvent<O> {
+public class LifecycleEvent extends RepositoryEvent {
 
-    public enum LifecycleEventType implements EventType {
-        REGISTERED,UNREGISTERED,UPDATED
-    }
+    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");
+    public static EventType<LifecycleEvent> UPDATED = new EventType<>(ANY, "REPOSITORY.LIFECYCLE.UPDATED");
 
-    public <OO extends O> LifecycleEvent(LifecycleEventType type, OO origin, Repository repository) {
+    public LifecycleEvent(EventType<? extends LifecycleEvent> type, Object origin, Repository repository) {
         super(type, origin, repository);
     }
 }
index 7c97b8762433336b346927563475a8941f287d89..24ea42c31c74550f2478506ffc493a265dd9017f 100644 (file)
@@ -21,11 +21,13 @@ package org.apache.archiva.repository.events;
 
 import org.apache.archiva.repository.Repository;
 
-public class RepositoryEvent<O> extends Event<O> {
+public class RepositoryEvent extends Event {
+
+    public static final EventType<RepositoryEvent> ANY = new EventType<>(Event.ANY, "REPOSITORY.UPDATED");
 
     private final Repository repository;
 
-    public <OO extends O> RepositoryEvent(EventType type, OO origin, Repository repository) {
+    public RepositoryEvent(EventType<? extends RepositoryEvent> type, Object origin, Repository repository) {
         super(type, origin);
         this.repository = repository;
     }
@@ -33,4 +35,9 @@ public class RepositoryEvent<O> extends Event<O> {
     public Repository getRepository() {
         return repository;
     }
+
+    @Override
+    public EventType<? extends RepositoryEvent> getType() {
+        return (EventType<? extends RepositoryEvent>) super.getType();
+    }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventHandler.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventHandler.java
deleted file mode 100644 (file)
index 123ffb2..0000000
+++ /dev/null
@@ -1,40 +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 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.
- *
- */
-public interface RepositoryEventHandler {
-
-    void register(RepositoryEventListener listener);
-
-    void register(RepositoryEventListener listener, EventType type);
-
-    void register(RepositoryEventListener listener, Set<? extends EventType> types);
-
-    void unregister(RepositoryEventListener listener);
-
-    void clearListeners();
-}
index 1f0b2039da9e930241b4c154bcdf4a5d02580ca5..ffedc4207190c96a284bd1e687318a4955bbb545 100644 (file)
@@ -19,12 +19,10 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
-import org.apache.archiva.repository.events.RepositoryValueEvent;
-
 /**
- * Listener that accepts repository events.
+ * A listener that accepts repository events.
  */
-public interface RepositoryEventListener {
+public interface RepositoryEventListener<T extends Event> {
 
-    void raise(Event event);
+    void raise(T event);
 }
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/RepositoryEventSource.java
new file mode 100644 (file)
index 0000000..f26eb78
--- /dev/null
@@ -0,0 +1,36 @@
+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 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.
+ *
+ */
+public interface RepositoryEventSource {
+
+    <T extends Event> void register(EventType<T> type, RepositoryEventListener<? super T> listener);
+
+    <T extends Event> void unregister(EventType<T> type, RepositoryEventListener<? super T> listener);
+
+    void clearListeners();
+}
index 1a138cf4d3cb52e6df58b8e7fcef81361398d9a9..2b9ac7668d145d3ecc821abeb686034feda247ba 100644 (file)
@@ -19,13 +19,13 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
-public class RepositoryRegistryEvent<O> extends Event<O> {
+public class RepositoryRegistryEvent extends Event {
 
-    public enum RegistryEventType implements EventType {
-        RELOADED,DESTROYED
-    }
+    public static EventType<RepositoryRegistryEvent> ANY = new EventType(Event.ANY, "REGISTRY");
+    public static EventType<RepositoryRegistryEvent> RELOADED = new EventType(ANY, "REGISTRY.RELOADED");
+    public static EventType<RepositoryRegistryEvent> DESTROYED = new EventType(ANY, "REGISTRY.DESTROYED");
 
-    public <OO extends O> RepositoryRegistryEvent(RegistryEventType type, OO origin) {
+    public RepositoryRegistryEvent(EventType<? extends RepositoryRegistryEvent> type, Object origin) {
         super(type, origin);
     }
 }
index 6081717e63a7522fdcfe5c1c8f047299311f2d3a..b5f8146a72599cf3386bb78566a14441a619c1d2 100644 (file)
@@ -26,12 +26,14 @@ import org.apache.archiva.repository.Repository;
  *
  * @param <V>
  */
-public class RepositoryValueEvent<O, V> extends RepositoryEvent<O> {
+public class RepositoryValueEvent<V> extends RepositoryEvent {
+
+    public static final EventType<RepositoryValueEvent<?>> ANY = new EventType(RepositoryEvent.ANY, "REPOSITORY.VALUE.UPDATED");
 
     final V value;
     final V oldValue;
 
-    public RepositoryValueEvent(EventType type, O origin, Repository repo, V oldValue, V value) {
+    public RepositoryValueEvent(EventType<? extends RepositoryValueEvent<V>> type, Object origin, Repository repo, V oldValue, V value) {
         super(type, origin, repo);
         this.value = value;
         this.oldValue = oldValue;
index 0f71880c8fa6ba26174448219e8b7f4a4d158288..5a5aa6c4c9828e3db8c5cb864a35c03096df5052 100644 (file)
@@ -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
+public abstract class AbstractRepository implements EditableRepository, RepositoryEventListener<RepositoryEvent>
 {
 
 
@@ -79,8 +79,8 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     String schedulingDefinition = "0 0 02 * * ?";
     private String layout = "default";
     public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
-    private List<RepositoryEventListener> listeners = new ArrayList<>();
-    private Map<EventType, List<RepositoryEventListener>> listenerTypeMap = new HashMap<>();
+
+    private Map<EventType<? extends RepositoryEvent>, List<RepositoryEventListener<? extends RepositoryEvent>>> listenerTypeMap = new HashMap<>();
 
 
     Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>(  );
@@ -334,14 +334,16 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     }
 
     @Override
-    public void raise(Event event) {
-        callListeners(event, listeners);
-        if (listenerTypeMap.containsKey(event.getType())) {
-            callListeners(event, listenerTypeMap.get(event.getType()));
+    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(Event event, List<RepositoryEventListener> evtListeners) {
+    private void callListeners(RepositoryEvent event, List<RepositoryEventListener<? extends RepositoryEvent>> evtListeners) {
         for(RepositoryEventListener listener : evtListeners) {
             try {
                 listener.raise(event.recreate(this));
@@ -353,15 +355,14 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     }
 
     @Override
-    public void register(RepositoryEventListener listener) {
-        if (!this.listeners.contains(listener)) {
-            this.listeners.add(listener);
+    public <T extends Event> void register(EventType<T> eventType, RepositoryEventListener<? super T> listener) {
+        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;
 
-    @Override
-    public void register(RepositoryEventListener listener, EventType type) {
-        List<RepositoryEventListener> listeners;
+        List<RepositoryEventListener<? extends RepositoryEvent>> listeners;
         if (listenerTypeMap.containsKey(type)) {
             listeners = listenerTypeMap.get(type);
         } else {
@@ -369,29 +370,19 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
             listenerTypeMap.put(type, listeners);
         }
         if (!listeners.contains(listener)) {
-            listeners.add(listener);
-        }
-
-    }
-
-    @Override
-    public void register(RepositoryEventListener listener, Set<? extends EventType> types) {
-        for (EventType type : types) {
-            register(listener, type);
+            listeners.add(myListener);
         }
     }
 
     @Override
-    public void unregister(RepositoryEventListener listener) {
-        listeners.remove(listener);
-        for (List<RepositoryEventListener> listeners : listenerTypeMap.values()) {
+    public <T extends Event> void unregister(EventType<T> type, RepositoryEventListener<? super T> listener) {
+        for (List<RepositoryEventListener<? extends RepositoryEvent>> listeners : listenerTypeMap.values()) {
             listeners.remove(listener);
         }
     }
 
     @Override
     public void clearListeners() {
-        this.listeners.clear();
         this.listenerTypeMap.clear();
     }
 
index 28ffc5a0176111936f92e8128dde2792faf2ce42..07e7300e526cbda50dfdd7bc2d2aa7f13994cb73 100644 (file)
@@ -53,7 +53,7 @@ import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
  * @since 3.0
  */
 @Service("repositoryRegistry")
-public class RepositoryRegistry implements ConfigurationListener, RepositoryEventHandler, RepositoryEventListener {
+public class RepositoryRegistry implements ConfigurationListener, RepositoryEventSource, RepositoryEventListener<Event> {
 
     private static final Logger log = LoggerFactory.getLogger(RepositoryRegistry.class);
 
@@ -73,8 +73,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     @Named("repositoryContentFactory#default")
     RepositoryContentFactory repositoryContentFactory;
 
-    private List<RepositoryEventListener> listeners = new ArrayList<>();
-    private Map<EventType, List<RepositoryEventListener>> typeListenerMap = new HashMap<>();
+    private Map<EventType<? extends Event>, List<RepositoryEventListener<? extends Event>>> typeListenerMap = new HashMap<>();
 
 
     private Map<String, ManagedRepository> managedRepositories = new HashMap<>();
@@ -111,7 +110,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         } finally {
             rwLock.writeLock().unlock();
         }
-        pushEvent(new RepositoryRegistryEvent<>(RepositoryRegistryEvent.RegistryEventType.RELOADED, this));
+        pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.RELOADED, this));
     }
 
     @PreDestroy
@@ -124,7 +123,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             repo.close();
         }
         remoteRepositories.clear();
-        pushEvent(new RepositoryRegistryEvent<>(RepositoryRegistryEvent.RegistryEventType.DESTROYED, this));
+        pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.DESTROYED, this));
     }
 
 
@@ -182,7 +181,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(this);
+        repo.register(RepositoryEvent.ANY,  this);
         updateRepositoryReferences(provider, repo, cfg, null);
         return repo;
 
@@ -205,7 +204,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                     if (configuration != null) {
                         replaceOrAddRepositoryConfig(provider.getManagedConfiguration(stageRepo), configuration);
                     }
-                    pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, stageRepo));
+                    pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, stageRepo));
                 }
                 feature.setStagingRepository(stageRepo);
             }
@@ -222,7 +221,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 createIndexingContext(editableRepo);
             }
         }
-        repo.register(this);
+        repo.register(RepositoryEvent.ANY, this);
     }
 
     public ArchivaIndexManager getIndexManager(RepositoryType type) {
@@ -297,7 +296,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 createIndexingContext(editableRepo);
             }
         }
-        repo.register(this);
+        repo.register(RepositoryEvent.ANY, this);
     }
 
     private Map<String, RepositoryGroup> getRepositorGroupsFromConfig() {
@@ -332,7 +331,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
 
     private RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException {
         RepositoryGroup repositoryGroup = provider.createRepositoryGroup(config);
-        repositoryGroup.register(this);
+        repositoryGroup.register(RepositoryEvent.ANY, this);
         updateRepositoryReferences(provider, repositoryGroup, config);
         return repositoryGroup;
     }
@@ -511,9 +510,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 configuration.addManagedRepository(newCfg);
                 saveConfiguration(configuration);
                 if (originRepo != managedRepository) {
-                    pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.REGISTERED, this, managedRepository));
+                    pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, managedRepository));
                 } else {
-                    pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UPDATED, this, managedRepository));
+                    pushEvent(new LifecycleEvent(LifecycleEvent.UPDATED, this, managedRepository));
                 }
                 return managedRepository;
             } catch (Exception e) {
@@ -595,9 +594,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             updateRepositoryReferences(getProvider(repoType), repo, managedRepositoryConfiguration, configuration);
             replaceOrAddRepositoryConfig(managedRepositoryConfiguration, configuration);
             if (registeredNew) {
-                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
+                pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, repo));
             } else {
-                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UPDATED, this, repo));
+                pushEvent(new LifecycleEvent(LifecycleEvent.UPDATED, this, repo));
             }
             return repo;
         } finally {
@@ -780,9 +779,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 }
                 configuration.addRemoteRepository(newCfg);
                 if (remoteRepository != originRepo) {
-                    pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.REGISTERED, this, remoteRepository));
+                    pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, remoteRepository));
                 } else {
-                    pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UPDATED, this, remoteRepository));
+                    pushEvent(new LifecycleEvent(LifecycleEvent.UPDATED, this, remoteRepository));
                 }
                 return remoteRepository;
             } catch (Exception e) {
@@ -896,9 +895,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             updateRepositoryReferences(getProvider(repoType), repo, remoteRepositoryConfiguration, configuration);
             replaceOrAddRepositoryConfig(remoteRepositoryConfiguration, configuration);
             if (registeredNew) {
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
+                pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, repo));
             } else {
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UPDATED, this, repo));
+                pushEvent(new LifecycleEvent(LifecycleEvent.UPDATED, this, repo));
             }
             return repo;
         } finally {
@@ -958,7 +957,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                     }
                     saveConfiguration(configuration);
                 }
-                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+                pushEvent(new LifecycleEvent(LifecycleEvent.UNREGISTERED, this, repo));
             } catch (RegistryException | IndeterminateConfigurationException e) {
                 // Rollback
                 log.error("Could not save config after repository removal: {}", e.getMessage(), e);
@@ -995,7 +994,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                         configuration.removeManagedRepository(cfg);
                     }
                 }
-                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+                pushEvent(new LifecycleEvent(LifecycleEvent.UNREGISTERED, this, repo));
             } finally {
                 rwLock.writeLock().unlock();
             }
@@ -1102,7 +1101,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                     doRemoveRepo(repo, configuration);
                     saveConfiguration(configuration);
                 }
-                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+                pushEvent(new LifecycleEvent(LifecycleEvent.UNREGISTERED, this, repo));
             } catch (RegistryException | IndeterminateConfigurationException e) {
                 // Rollback
                 log.error("Could not save config after repository removal: {}", e.getMessage(), e);
@@ -1127,7 +1126,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 if (repo != null) {
                     doRemoveRepo(repo, configuration);
                 }
-                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+                pushEvent(new LifecycleEvent(LifecycleEvent.UNREGISTERED, this, repo));
             } finally {
                 rwLock.writeLock().unlock();
             }
@@ -1172,7 +1171,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration(repo);
         cfg.setId(newId);
         ManagedRepository cloned = provider.createManagedInstance(cfg);
-        cloned.register(this);
+        cloned.register(RepositoryEvent.ANY, this);
         return cloned;
     }
 
@@ -1201,7 +1200,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration(repo);
         cfg.setId(newId);
         RemoteRepository cloned = provider.createRemoteInstance(cfg);
-        cloned.register(this);
+        cloned.register(RepositoryEvent.ANY, this);
         return cloned;
     }
 
@@ -1216,15 +1215,8 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
 
 
     @Override
-    public void register(RepositoryEventListener listener) {
-        if (!this.listeners.contains(listener)) {
-            this.listeners.add(listener);
-        }
-    }
-
-    @Override
-    public void register(RepositoryEventListener listener, EventType type) {
-        List<RepositoryEventListener> listeners;
+    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 {
@@ -1236,28 +1228,19 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         }
     }
 
-    @Override
-    public void register(RepositoryEventListener listener, Set<? extends EventType> types) {
-        for (EventType type : types) {
-            register(listener, type);
-        }
-    }
 
     @Override
-    public void unregister(RepositoryEventListener listener) {
-        this.listeners.remove(listener);
-        for (List<RepositoryEventListener> listeners : typeListenerMap.values()) {
+    public <T extends Event> void unregister(EventType<T> type, RepositoryEventListener<? super T> listener) {
+        for (List<RepositoryEventListener<?>> listeners : typeListenerMap.values()) {
             listeners.remove(listener);
         }
     }
 
     @Override
     public void clearListeners() {
-        this.listeners.clear();
         this.typeListenerMap.clear();
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public void raise(Event event) {
         // To avoid event cycles:
@@ -1302,20 +1285,18 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         }
     }
 
-    private void pushEvent(Event<RepositoryRegistry> event) {
-        callListeners(event, listeners);
-        if (typeListenerMap.containsKey(event.getType())) {
-            callListeners(event, typeListenerMap.get(event.getType()));
+    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));
+            }
         }
     }
 
-    private void callListeners(final Event<RepositoryRegistry> event, final List<RepositoryEventListener> evtListeners) {
-        for (RepositoryEventListener listener : evtListeners) {
-            try {
-                listener.raise(event);
-            } catch (Throwable e) {
-                log.error("Could not raise event {} on listener {}: {}", event, listener, e.getMessage());
-            }
+    private void callListeners(Event event, List<RepositoryEventListener<? extends Event>> listeners) {
+        for (RepositoryEventListener listener : listeners) {
+            listener.raise(event);
         }
     }