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/09/12 11:10:44 UTC

[archiva] branch feature/storage_refactoring updated (e8eb470 -> 1c37992)

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

martin_s pushed a change to branch feature/storage_refactoring
in repository https://gitbox.apache.org/repos/asf/archiva.git.


    from e8eb470  Proxy changes
     new f39d677  Enhancing repository events
     new 1c37992  Fixing proxy connector handling

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../src/test/java/RepositoryProviderMock.java      |    3 +-
 .../repository/mock/RepositoryProviderMock.java    |    5 +-
 .../apache/archiva/proxy/ArchivaProxyRegistry.java |   34 +-
 .../managed/ManagedRepositoryAdminTest.java        |    1 -
 .../org/apache/archiva/repository/Repository.java  |    2 +-
 .../archiva/repository/RepositoryProvider.java     |    1 +
 .../{RepositoryEvent.java => events/Event.java}    |   50 +-
 .../archiva/repository/events/EventType.java}      |   10 +-
 .../archiva/repository/events/LifecycleEvent.java} |   24 +-
 .../repository/events/RepositoryEvent.java}        |   27 +-
 .../{ => events}/RepositoryEventHandler.java       |   16 +-
 .../{ => events}/RepositoryEventListener.java      |    6 +-
 .../events/RepositoryRegistryEvent.java}           |   22 +-
 .../repository/events/RepositoryValueEvent.java}   |   33 +-
 .../repository/features/AbstractFeature.java       |    6 +-
 .../repository/features/IndexCreationEvent.java    |   21 +-
 .../repository/features/IndexCreationFeature.java  |    6 +-
 .../repository/features/RemoteIndexFeature.java    |   10 +
 .../archiva/repository/AbstractRepository.java     |   56 +-
 .../archiva/repository/RepositoryRegistry.java     | 1181 +++++++++-----------
 .../repository/mock/RepositoryProviderMock.java    |    4 +-
 .../archiva/proxy/HttpProxyTransferTest.java       |    2 +
 .../repository/mock/RepositoryProviderMock.java    |    5 +-
 .../maven2/ArchivaRepositoryConnectorFactory.java  |    2 +
 .../repository/maven2/MavenRepositoryProvider.java |    8 +-
 .../maven2/DependencyTreeBuilderTestMaven3.java    |    2 +
 26 files changed, 774 insertions(+), 763 deletions(-)
 rename archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/{RepositoryEvent.java => events/Event.java} (61%)
 copy archiva-modules/{archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/RepositoryLocator.java => archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java} (88%)
 copy archiva-modules/{metadata/metadata-repository-api/src/main/java/org/apache/archiva/repository/events/AuditListener.java => archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java} (71%)
 copy archiva-modules/{metadata/metadata-repository-api/src/main/java/org/apache/archiva/repository/events/AuditListener.java => archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java} (69%)
 rename archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/{ => events}/RepositoryEventHandler.java (64%)
 rename archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/{ => events}/RepositoryEventListener.java (86%)
 copy archiva-modules/{metadata/metadata-repository-api/src/main/java/org/apache/archiva/repository/events/AuditListener.java => archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java} (75%)
 copy archiva-modules/{metadata/metadata-repository-api/src/main/java/org/apache/archiva/repository/events/AuditListener.java => archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java} (59%)


[archiva] 01/02: Enhancing repository events

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f39d6773bddbf33c2a90d6da6daada940ff6f011
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Thu Sep 12 13:09:40 2019 +0200

    Enhancing repository events
---
 .../src/test/java/RepositoryProviderMock.java      |    3 +-
 .../repository/mock/RepositoryProviderMock.java    |    5 +-
 .../org/apache/archiva/repository/Repository.java  |    2 +-
 .../archiva/repository/RepositoryProvider.java     |    1 +
 .../{RepositoryEvent.java => events/Event.java}    |   50 +-
 .../EventType.java}                                |    9 +-
 .../LifecycleEvent.java}                           |   17 +-
 .../RepositoryEvent.java}                          |   20 +-
 .../{ => events}/RepositoryEventHandler.java       |   16 +-
 .../{ => events}/RepositoryEventListener.java      |    6 +-
 .../RepositoryRegistryEvent.java}                  |   17 +-
 .../RepositoryValueEvent.java}                     |   41 +-
 .../repository/features/AbstractFeature.java       |    6 +-
 .../repository/features/IndexCreationEvent.java    |   21 +-
 .../repository/features/IndexCreationFeature.java  |    6 +-
 .../repository/features/RemoteIndexFeature.java    |   10 +
 .../archiva/repository/AbstractRepository.java     |   56 +-
 .../archiva/repository/RepositoryRegistry.java     | 1181 +++++++++-----------
 .../repository/mock/RepositoryProviderMock.java    |    4 +-
 .../repository/mock/RepositoryProviderMock.java    |    5 +-
 20 files changed, 723 insertions(+), 753 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 15cf17e..5302a74 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
@@ -36,6 +36,7 @@ import org.apache.archiva.repository.RepositoryCredentials;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryProvider;
 import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.events.Event;
 import org.apache.archiva.repository.features.ArtifactCleanupFeature;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.RemoteIndexFeature;
@@ -255,7 +256,7 @@ public class RepositoryProviderMock implements RepositoryProvider
     }
 
     @Override
-    public <T> void raise(org.apache.archiva.repository.RepositoryEvent<T> event) {
+    public void raise(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 a23ae0f..c10a5a8 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
@@ -32,7 +32,8 @@ import org.apache.archiva.repository.PasswordCredentials;
 import org.apache.archiva.repository.ReleaseScheme;
 import org.apache.archiva.repository.RemoteRepository;
 import org.apache.archiva.repository.RepositoryCredentials;
-import org.apache.archiva.repository.RepositoryEvent;
+import org.apache.archiva.repository.events.Event;
+import org.apache.archiva.repository.events.RepositoryValueEvent;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryGroup;
 import org.apache.archiva.repository.RepositoryProvider;
@@ -284,7 +285,7 @@ public class RepositoryProviderMock implements RepositoryProvider
     }
 
     @Override
-    public <T> void raise(RepositoryEvent<T> event) {
+    public void raise(Event event) {
 
     }
 }
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 cc43ab2..9b26143 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,12 +20,12 @@ package org.apache.archiva.repository;
  */
 
 import org.apache.archiva.indexer.ArchivaIndexingContext;
+import org.apache.archiva.repository.events.RepositoryEventHandler;
 import org.apache.archiva.repository.storage.RepositoryStorage;
 import org.apache.archiva.repository.features.RepositoryFeature;
 import org.apache.archiva.repository.storage.StorageAsset;
 
 import java.net.URI;
-import java.nio.file.Path;
 import java.util.Locale;
 import java.util.Set;
 
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 1f26a5d..3a405fb 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,6 +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 java.io.IOException;
 import java.util.Set;
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
similarity index 61%
copy from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEvent.java
copy to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
index 8a9db88..afac04c 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -21,49 +21,47 @@ package org.apache.archiva.repository;
 
 import java.time.LocalDateTime;
 
-/**
- * Repository event. Repository events are used for providing information about repository changes.
- *
- * @param <T>
- */
-public class RepositoryEvent<T> {
+public class Event<O> {
 
+    Event previous;
+    final O originator;
     final EventType type;
-    final Repository repo;
-    final T value;
-    final T oldValue;
     final LocalDateTime instant;
 
-    public RepositoryEvent(EventType type, Repository repo, T oldValue, T value) {
+    public Event(EventType type, O originator) {
+        this.originator = originator;
         this.type = type;
-        this.repo = repo;
-        this.value = value;
-        this.oldValue = oldValue;
         this.instant = LocalDateTime.now();
     }
 
-    public interface EventType {
-        String name();
+    private <OO> Event(Event<OO> previous, O originator) {
+        this.previous = previous;
+        this.originator = originator;
+        this.type = previous.getType();
+        this.instant = previous.getInstant();
     }
 
-
     public EventType getType() {
         return type;
     };
 
-    public Repository getRepository() {
-        return repo;
-    };
+    public LocalDateTime getInstant() {
+        return instant;
+    }
 
-    public T getValue() {
-        return value;
+    public O getOriginator() {
+        return originator;
     }
 
-    public T getOldValue() {
-        return oldValue;
+    public <NO> Event<NO> recreate(NO newOrigin) {
+        return new Event(this, newOrigin);
     }
 
-    public LocalDateTime getInstant() {
-        return instant;
+    public Event getPreviousEvent() {
+        return previous;
+    }
+
+    public boolean hasPreviousEvent() {
+        return previous!=null;
     }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventListener.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java
similarity index 81%
copy from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventListener.java
copy to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java
index 0234f34..5004a15 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventListener.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,10 +19,7 @@ package org.apache.archiva.repository;
  * under the License.
  */
 
-/**
- * Listener that accepts repository events.
- */
-public interface RepositoryEventListener {
+public interface EventType {
 
-    <T> void raise(RepositoryEvent<T> event);
+    String name();
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
similarity index 67%
copy from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
copy to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
index 7432627..5f69d1e 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,14 +19,15 @@ package org.apache.archiva.repository;
  * under the License.
  */
 
-/**
- * Implementations of this interface are able to handle repository event listeners
- */
-public interface RepositoryEventHandler {
+import org.apache.archiva.repository.Repository;
 
-    void addListener(RepositoryEventListener listener);
+public class LifecycleEvent<O> extends RepositoryEvent<O> {
 
-    void removeListener(RepositoryEventListener listener);
+    public enum LifecycleEventType implements EventType {
+        REGISTERED,UNREGISTERED,UPDATED
+    }
 
-    void clearListeners();
+    public LifecycleEvent(LifecycleEventType type, O origin, Repository repository) {
+        super(type, origin, repository);
+    }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
similarity index 66%
copy from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
copy to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
index 7432627..dd5550b 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,14 +19,18 @@ package org.apache.archiva.repository;
  * under the License.
  */
 
-/**
- * Implementations of this interface are able to handle repository event listeners
- */
-public interface RepositoryEventHandler {
+import org.apache.archiva.repository.Repository;
+
+public class RepositoryEvent<O> extends Event<O> {
 
-    void addListener(RepositoryEventListener listener);
+    private final Repository repository;
 
-    void removeListener(RepositoryEventListener listener);
+    public RepositoryEvent(EventType type, O origin, Repository repository) {
+        super(type, origin);
+        this.repository = repository;
+    }
 
-    void clearListeners();
+    public Repository getRepository() {
+        return repository;
+    }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventHandler.java
similarity index 64%
copy from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
copy to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventHandler.java
index 7432627..123ffb2 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventHandler.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,14 +19,22 @@ package org.apache.archiva.repository;
  * under the License.
  */
 
+import java.util.Set;
+
 /**
- * Implementations of this interface are able to handle repository event listeners
+ * 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 addListener(RepositoryEventListener listener);
+    void register(RepositoryEventListener listener);
+
+    void register(RepositoryEventListener listener, EventType type);
+
+    void register(RepositoryEventListener listener, Set<? extends EventType> types);
 
-    void removeListener(RepositoryEventListener listener);
+    void unregister(RepositoryEventListener listener);
 
     void clearListeners();
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventListener.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java
similarity index 86%
rename from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventListener.java
rename to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java
index 0234f34..1f0b203 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventListener.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,10 +19,12 @@ package org.apache.archiva.repository;
  * under the License.
  */
 
+import org.apache.archiva.repository.events.RepositoryValueEvent;
+
 /**
  * Listener that accepts repository events.
  */
 public interface RepositoryEventListener {
 
-    <T> void raise(RepositoryEvent<T> event);
+    void raise(Event event);
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
similarity index 72%
rename from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
rename to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
index 7432627..d9b891c 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,14 +19,13 @@ package org.apache.archiva.repository;
  * under the License.
  */
 
-/**
- * Implementations of this interface are able to handle repository event listeners
- */
-public interface RepositoryEventHandler {
-
-    void addListener(RepositoryEventListener listener);
+public class RepositoryRegistryEvent<O> extends Event {
 
-    void removeListener(RepositoryEventListener listener);
+    public enum RegistryEventType implements EventType {
+        RELOADED,DESTROYED
+    }
 
-    void clearListeners();
+    public RepositoryRegistryEvent(RegistryEventType type, O origin) {
+        super(type, origin);
+    }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java
similarity index 58%
rename from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEvent.java
rename to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java
index 8a9db88..6081717 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,51 +19,30 @@ package org.apache.archiva.repository;
  * under the License.
  */
 
-import java.time.LocalDateTime;
+import org.apache.archiva.repository.Repository;
 
 /**
  * Repository event. Repository events are used for providing information about repository changes.
  *
- * @param <T>
+ * @param <V>
  */
-public class RepositoryEvent<T> {
+public class RepositoryValueEvent<O, V> extends RepositoryEvent<O> {
 
-    final EventType type;
-    final Repository repo;
-    final T value;
-    final T oldValue;
-    final LocalDateTime instant;
+    final V value;
+    final V oldValue;
 
-    public RepositoryEvent(EventType type, Repository repo, T oldValue, T value) {
-        this.type = type;
-        this.repo = repo;
+    public RepositoryValueEvent(EventType type, O origin, Repository repo, V oldValue, V value) {
+        super(type, origin, repo);
         this.value = value;
         this.oldValue = oldValue;
-        this.instant = LocalDateTime.now();
     }
 
-    public interface EventType {
-        String name();
-    }
-
-
-    public EventType getType() {
-        return type;
-    };
-
-    public Repository getRepository() {
-        return repo;
-    };
-
-    public T getValue() {
+    public V getValue() {
         return value;
     }
 
-    public T getOldValue() {
+    public V getOldValue() {
         return oldValue;
     }
 
-    public LocalDateTime getInstant() {
-        return instant;
-    }
 }
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 08d0bba..6b64d93 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
@@ -19,8 +19,8 @@ package org.apache.archiva.repository.features;
  * under the License.
  */
 
-import org.apache.archiva.repository.RepositoryEvent;
-import org.apache.archiva.repository.RepositoryEventListener;
+import org.apache.archiva.repository.events.Event;
+import org.apache.archiva.repository.events.RepositoryEventListener;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -56,7 +56,7 @@ public class AbstractFeature {
         this.listener.clear();
     }
 
-    protected <T> void raiseEvent(RepositoryEvent<T> event) {
+    public void pushEvent(Event event) {
         for(RepositoryEventListener listr : listener) {
             listr.raise(event);
         }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationEvent.java
index 49a3d44..037ba47 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationEvent.java
@@ -20,29 +20,30 @@ package org.apache.archiva.repository.features;
  */
 
 import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.RepositoryEvent;
+import org.apache.archiva.repository.events.EventType;
+import org.apache.archiva.repository.events.RepositoryValueEvent;
 
 import java.net.URI;
 
-public class IndexCreationEvent extends RepositoryEvent<URI> {
+public class IndexCreationEvent<O> extends RepositoryValueEvent<O, URI> {
 
     public enum Index implements EventType {
         INDEX_URI_CHANGE, PACKED_INDEX_URI_CHANGE
     }
 
-    IndexCreationEvent(Repository repo, URI oldValue, URI value) {
-        super(Index.INDEX_URI_CHANGE, repo, oldValue, value);
+    IndexCreationEvent(Repository repo, O origin, URI oldValue, URI value) {
+        super(Index.INDEX_URI_CHANGE, origin, repo, oldValue, value);
     }
 
-    IndexCreationEvent(Index type, Repository repo, URI oldValue, URI value) {
-        super(type, repo, oldValue, value);
+    IndexCreationEvent(Index type, O origin, Repository repo, URI oldValue, URI value) {
+        super(type, origin, repo, oldValue, value);
     }
 
-    public static final IndexCreationEvent indexUriChange(Repository repo, URI oldValue, URI newValue) {
-        return new IndexCreationEvent(Index.INDEX_URI_CHANGE, repo, oldValue, newValue);
+    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);
     }
 
-    public static final IndexCreationEvent packedIndexUriChange(Repository repo, URI oldValue, URI newValue) {
-        return new IndexCreationEvent(Index.PACKED_INDEX_URI_CHANGE, 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);
     }
 }
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 94812fc..cf7432c 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,7 +21,7 @@ package org.apache.archiva.repository.features;
 
 
 import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.RepositoryEventListener;
+import org.apache.archiva.repository.events.RepositoryEventListener;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.commons.lang3.StringUtils;
 
@@ -113,7 +113,7 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
     {
         URI oldVal = this.indexPath;
         this.indexPath = indexPath;
-        raiseEvent(IndexCreationEvent.indexUriChange(repo, oldVal, this.indexPath));
+        pushEvent(IndexCreationEvent.indexUriChange(this, repo, oldVal, this.indexPath));
 
     }
 
@@ -157,7 +157,7 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
     public void setPackedIndexPath(URI packedIndexPath) {
         URI oldVal = this.packedIndexPath;
         this.packedIndexPath = packedIndexPath;
-        raiseEvent(IndexCreationEvent.packedIndexUriChange(repo, oldVal, this.packedIndexPath));
+        pushEvent(IndexCreationEvent.packedIndexUriChange(this, repo, oldVal, this.packedIndexPath));
     }
 
     /**
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/RemoteIndexFeature.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/RemoteIndexFeature.java
index 3e15487..245b8b0 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/RemoteIndexFeature.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/RemoteIndexFeature.java
@@ -23,6 +23,7 @@ package org.apache.archiva.repository.features;
 import org.apache.commons.lang3.StringUtils;
 
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.time.Duration;
 
 /**
@@ -32,6 +33,15 @@ public class RemoteIndexFeature implements RepositoryFeature<RemoteIndexFeature>
 
     private boolean downloadRemoteIndex = false;
     private URI indexUri;
+
+    {
+        try {
+            indexUri = new URI(".index");
+        } catch (URISyntaxException e) {
+            // Ignore
+        }
+    }
+
     private boolean downloadRemoteIndexOnStartup = false;
     private Duration downloadTimeout = Duration.ofSeconds( 600 );
     private String proxyId = "";
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 99c3dd0..d8c9e3b 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
@@ -24,6 +24,7 @@ import com.cronutils.model.definition.CronDefinition;
 import com.cronutils.model.definition.CronDefinitionBuilder;
 import com.cronutils.parser.CronParser;
 import org.apache.archiva.indexer.ArchivaIndexingContext;
+import org.apache.archiva.repository.events.*;
 import org.apache.archiva.repository.storage.RepositoryStorage;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.archiva.repository.features.RepositoryFeature;
@@ -39,7 +40,6 @@ import java.net.URI;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
 import java.nio.file.CopyOption;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -76,6 +76,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     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<>();
 
 
     Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> featureMap = new HashMap<>(  );
@@ -315,24 +316,65 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     }
 
     @Override
-    public <T> void raise(RepositoryEvent<T> event) {
-        for(RepositoryEventListener listener : listeners) {
-            listener.raise(event);
+    public void raise(Event event) {
+        callListeners(event, listeners);
+        if (listenerTypeMap.containsKey(event.getType())) {
+            callListeners(event, listenerTypeMap.get(event.getType()));
         }
     }
 
-    public void addListener(RepositoryEventListener listener) {
+    private void callListeners(Event event, 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());
+            }
+        }
+
+    }
+
+    @Override
+    public void register(RepositoryEventListener listener) {
         if (!this.listeners.contains(listener)) {
             this.listeners.add(listener);
         }
     }
 
-    public void removeListener(RepositoryEventListener listener) {
-        this.removeListener(listener);
+    @Override
+    public void register(RepositoryEventListener listener, EventType type) {
+        List<RepositoryEventListener> listeners;
+        if (listenerTypeMap.containsKey(type)) {
+            listeners = listenerTypeMap.get(type);
+        } else {
+            listeners = new ArrayList<>();
+            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);
+        }
+    }
+
+    @Override
+    public void unregister(RepositoryEventListener listener) {
+        listeners.remove(listener);
+        for (List<RepositoryEventListener> listeners : listenerTypeMap.values()) {
+            listeners.remove(listener);
+        }
     }
 
+    @Override
     public void clearListeners() {
         this.listeners.clear();
+        this.listenerTypeMap.clear();
     }
 
     @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 316b1cf..a58f960 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
@@ -20,12 +20,9 @@ package org.apache.archiva.repository;
  */
 
 import org.apache.archiva.configuration.*;
-import org.apache.archiva.indexer.ArchivaIndexManager;
-import org.apache.archiva.indexer.ArchivaIndexingContext;
-import org.apache.archiva.indexer.IndexCreationFailedException;
-import org.apache.archiva.indexer.IndexManagerFactory;
-import org.apache.archiva.indexer.IndexUpdateFailedException;
+import org.apache.archiva.indexer.*;
 import org.apache.archiva.redback.components.registry.RegistryException;
+import org.apache.archiva.repository.events.*;
 import org.apache.archiva.repository.features.IndexCreationEvent;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.StagingRepositoryFeature;
@@ -38,13 +35,7 @@ import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Named;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -54,16 +45,16 @@ import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
 /**
  * Registry for repositories. This is the central entry point for repositories. It provides methods for
  * retrieving, adding and removing repositories.
- *
+ * <p>
  * The modification methods addXX and removeXX persist the changes immediately to the configuration. If the
  * configuration save fails the changes are rolled back.
- *
+ * <p>
  * TODO: Audit events
  */
-@Service( "repositoryRegistry" )
+@Service("repositoryRegistry")
 public class RepositoryRegistry implements ConfigurationListener, RepositoryEventHandler, RepositoryEventListener {
 
-    private static final Logger log = LoggerFactory.getLogger( RepositoryRegistry.class );
+    private static final Logger log = LoggerFactory.getLogger(RepositoryRegistry.class);
 
     /**
      * We inject all repository providers
@@ -82,164 +73,157 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     RepositoryContentFactory repositoryContentFactory;
 
     private List<RepositoryEventListener> listeners = new ArrayList<>();
+    private Map<EventType, List<RepositoryEventListener>> typeListenerMap = new HashMap<>();
 
 
-    private Map<String, ManagedRepository> managedRepositories = new HashMap<>( );
-    private Map<String, ManagedRepository> uManagedRepository = Collections.unmodifiableMap( managedRepositories );
+    private Map<String, ManagedRepository> managedRepositories = new HashMap<>();
+    private Map<String, ManagedRepository> uManagedRepository = Collections.unmodifiableMap(managedRepositories);
 
-    private Map<String, RemoteRepository> remoteRepositories = new HashMap<>( );
-    private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap( remoteRepositories );
+    private Map<String, RemoteRepository> remoteRepositories = new HashMap<>();
+    private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap(remoteRepositories);
 
     private Map<String, RepositoryGroup> repositoryGroups = new HashMap<>();
     private Map<String, RepositoryGroup> uRepositoryGroups = Collections.unmodifiableMap(repositoryGroups);
 
-    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( );
+    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
+
+    private volatile boolean ignoreConfigEvents = false;
 
-    public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration) {
+    public void setArchivaConfiguration(ArchivaConfiguration archivaConfiguration) {
         this.archivaConfiguration = archivaConfiguration;
     }
 
     @PostConstruct
-    private void initialize( )
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    private void initialize() {
+        rwLock.writeLock().lock();
+        try {
             log.debug("Initializing repository registry");
-            for(ManagedRepository rep : managedRepositories.values()) {
+            for (ManagedRepository rep : managedRepositories.values()) {
                 rep.close();
             }
-            managedRepositories.clear( );
-            managedRepositories.putAll( getManagedRepositoriesFromConfig( ) );
+            managedRepositories.clear();
+            updateManagedRepositoriesFromConfig();
             for (RemoteRepository repo : remoteRepositories.values()) {
                 repo.close();
             }
-            remoteRepositories.clear( );
-            remoteRepositories.putAll( getRemoteRepositoriesFromConfig( ) );
+            remoteRepositories.clear();
+            updateRemoteRepositoriesFromConfig();
 
             repositoryGroups.clear();
-            repositoryGroups.putAll(getRepositorGroupsFromConfig());
+            Map<String, RepositoryGroup> repositoryGroups = getRepositorGroupsFromConfig();
+            this.repositoryGroups.putAll(repositoryGroups);
 
             // archivaConfiguration.addChangeListener(this);
             archivaConfiguration.addListener(this);
+        } finally {
+            rwLock.writeLock().unlock();
         }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
-        }
+        pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.RegistryEventType.RELOADED, this));
     }
 
     @PreDestroy
     public void destroy() {
-        for(ManagedRepository rep : managedRepositories.values()) {
+        for (ManagedRepository rep : managedRepositories.values()) {
             rep.close();
         }
+        managedRepositories.clear();
         for (RemoteRepository repo : remoteRepositories.values()) {
             repo.close();
         }
+        remoteRepositories.clear();
+        pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.RegistryEventType.DESTROYED, this));
     }
 
 
-
-    private Map<RepositoryType, RepositoryProvider> createProviderMap( )
-    {
-        Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
-        if ( repositoryProviders != null )
-        {
-            for ( RepositoryProvider provider : repositoryProviders )
-            {
-                for ( RepositoryType type : provider.provides( ) )
-                {
-                    map.put( type, provider );
+    private Map<RepositoryType, RepositoryProvider> createProviderMap() {
+        Map<RepositoryType, RepositoryProvider> map = new HashMap<>();
+        if (repositoryProviders != null) {
+            for (RepositoryProvider provider : repositoryProviders) {
+                for (RepositoryType type : provider.provides()) {
+                    map.put(type, provider);
                 }
             }
         }
         return map;
     }
 
-    private RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
-    {
-        return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
+    private RepositoryProvider getProvider(RepositoryType type) throws RepositoryException {
+        return repositoryProviders.stream().filter(repositoryProvider -> repositoryProvider.provides().contains(type)).findFirst().orElseThrow(() -> new RepositoryException("Repository type cannot be handled: " + type));
     }
 
-    private Map<String, ManagedRepository> getManagedRepositoriesFromConfig( )
-    {
-        try
-        {
+    private void updateManagedRepositoriesFromConfig() {
+        try {
             List<ManagedRepositoryConfiguration> managedRepoConfigs =
-                getArchivaConfiguration( ).getConfiguration( ).getManagedRepositories( );
+                    getArchivaConfiguration().getConfiguration().getManagedRepositories();
 
-            if ( managedRepoConfigs == null )
-            {
-                return Collections.emptyMap();
+            if (managedRepoConfigs == null) {
+                return;
             }
 
-            Map<String, ManagedRepository> managedRepos = new LinkedHashMap<>( managedRepoConfigs.size( ) );
-
-            Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap( );
-            for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
-            {
-                if (managedRepos.containsKey(repoConfig.getId())) {
-                    log.warn( "Duplicate repository definitions for {} in config found.", repoConfig.getId( ) );
+            Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap();
+            for (ManagedRepositoryConfiguration repoConfig : managedRepoConfigs) {
+                if (managedRepositories.containsKey(repoConfig.getId())) {
+                    log.warn("Duplicate repository definitions for {} in config found.", repoConfig.getId());
                     continue;
                 }
-                RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
-                if ( providerMap.containsKey( repositoryType ) )
-                {
-                    try
-                    {
-                        ManagedRepository repo = createNewManagedRepository( providerMap.get( repositoryType ), repoConfig );
-                        managedRepos.put( repo.getId( ), repo );
-                    }
-                    catch ( Exception e )
-                    {
-                        log.error( "Could not create managed repository {}: {}", repoConfig.getId( ), e.getMessage( ), e );
+                RepositoryType repositoryType = RepositoryType.valueOf(repoConfig.getType());
+                if (providerMap.containsKey(repositoryType)) {
+                    try {
+                        ManagedRepository repo = createNewManagedRepository(providerMap.get(repositoryType), repoConfig);
+                        managedRepositories.put(repo.getId(), repo);
+                        pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
+                    } catch (Exception e) {
+                        log.error("Could not create managed repository {}: {}", repoConfig.getId(), e.getMessage(), e);
                     }
                 }
             }
-            return managedRepos;
+            return;
         } catch (Throwable e) {
-            log.error("Could not initialize repositories from config: {}",e.getMessage(), e );
+            log.error("Could not initialize repositories from config: {}", e.getMessage(), e);
             //noinspection unchecked
-            return Collections.emptyMap();
+            return;
         }
     }
 
-    private ManagedRepository createNewManagedRepository( RepositoryProvider provider, ManagedRepositoryConfiguration cfg ) throws RepositoryException
-    {
+    private ManagedRepository createNewManagedRepository(RepositoryProvider provider, ManagedRepositoryConfiguration cfg) throws RepositoryException {
         log.debug("Creating repo {}", cfg.getId());
-        ManagedRepository repo = provider.createManagedInstance( cfg );
-        repo.addListener(this);
-        updateRepositoryReferences( provider, repo, cfg , null);
+        ManagedRepository repo = provider.createManagedInstance(cfg);
+        repo.register(this);
+        updateRepositoryReferences(provider, repo, cfg, null);
         return repo;
 
     }
 
-    @SuppressWarnings( "unchecked" )
-    private void updateRepositoryReferences(RepositoryProvider provider, ManagedRepository repo, ManagedRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException
-    {
-        log.debug("Updating references of repo {}",repo.getId());
-        if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
-        {
-            StagingRepositoryFeature feature = repo.getFeature( StagingRepositoryFeature.class ).get( );
-            if ( feature.isStageRepoNeeded( ) && feature.getStagingRepository() == null)
-            {
-                ManagedRepository stageRepo = getStagingRepository( provider, cfg, configuration);
-                managedRepositories.put(stageRepo.getId(), stageRepo);
-                feature.setStagingRepository( stageRepo );
-                if (configuration!=null) {
-                    replaceOrAddRepositoryConfig( provider.getManagedConfiguration( stageRepo ), configuration );
+    private String getStagingId(String repoId) {
+        return repoId + StagingRepositoryFeature.STAGING_REPO_POSTFIX;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void updateRepositoryReferences(RepositoryProvider provider, ManagedRepository repo, ManagedRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException {
+        log.debug("Updating references of repo {}", repo.getId());
+        if (repo.supportsFeature(StagingRepositoryFeature.class)) {
+            StagingRepositoryFeature feature = repo.getFeature(StagingRepositoryFeature.class).get();
+            if (feature.isStageRepoNeeded() && feature.getStagingRepository() == null) {
+                ManagedRepository stageRepo = getManagedRepository(getStagingId(repo.getId()));
+                if (stageRepo==null) {
+                    stageRepo = getStagingRepository(provider, cfg, configuration);
+                    managedRepositories.put(stageRepo.getId(), stageRepo);
+                    if (configuration != null) {
+                        replaceOrAddRepositoryConfig(provider.getManagedConfiguration(stageRepo), configuration);
+                    }
                 }
+                feature.setStagingRepository(stageRepo);
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, stageRepo));
             }
         }
-        if ( repo instanceof EditableManagedRepository)
-        {
+        if (repo instanceof EditableManagedRepository) {
             EditableManagedRepository editableRepo = (EditableManagedRepository) repo;
-            if (repo.getContent()==null) {
+            if (repo.getContent() == null) {
                 editableRepo.setContent(repositoryContentFactory.getManagedRepositoryContent(repo));
+                editableRepo.getContent().setRepository(editableRepo);
             }
-            log.debug("Index repo: "+repo.hasIndex());
-            if (repo.hasIndex() && repo.getIndexingContext()==null) {
+            log.debug("Index repo: " + repo.hasIndex());
+            if (repo.hasIndex() && repo.getIndexingContext() == null) {
                 log.debug("Creating indexing context for {}", repo.getId());
                 createIndexingContext(editableRepo);
             }
@@ -258,129 +242,105 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 editableRepo.setIndexingContext(idxManager.createContext(editableRepo));
                 idxManager.updateLocalIndexPath(editableRepo);
             } catch (IndexCreationFailedException e) {
-                throw new RepositoryException("Could not create index for repository "+editableRepo.getId()+": "+e.getMessage(),e);
+                throw new RepositoryException("Could not create index for repository " + editableRepo.getId() + ": " + e.getMessage(), e);
             }
         }
     }
 
-    private ManagedRepository getStagingRepository(RepositoryProvider provider, ManagedRepositoryConfiguration baseRepoCfg, Configuration configuration) throws RepositoryException
-    {
-        ManagedRepository stageRepo = getManagedRepository( baseRepoCfg.getId( ) + StagingRepositoryFeature.STAGING_REPO_POSTFIX );
-        if ( stageRepo == null )
-        {
-            stageRepo = provider.createStagingInstance( baseRepoCfg );
+    private ManagedRepository getStagingRepository(RepositoryProvider provider, ManagedRepositoryConfiguration baseRepoCfg, Configuration configuration) throws RepositoryException {
+        ManagedRepository stageRepo = getManagedRepository(getStagingId(baseRepoCfg.getId()));
+        if (stageRepo == null) {
+            stageRepo = provider.createStagingInstance(baseRepoCfg);
             if (stageRepo.supportsFeature(StagingRepositoryFeature.class)) {
                 stageRepo.getFeature(StagingRepositoryFeature.class).get().setStageRepoNeeded(false);
             }
-            ManagedRepositoryConfiguration stageCfg = provider.getManagedConfiguration( stageRepo );
-            updateRepositoryReferences( provider, stageRepo, stageCfg, configuration);
+            ManagedRepositoryConfiguration stageCfg = provider.getManagedConfiguration(stageRepo);
+            updateRepositoryReferences(provider, stageRepo, stageCfg, configuration);
         }
         return stageRepo;
     }
 
 
-
-
-    private Map<String, RemoteRepository> getRemoteRepositoriesFromConfig( )
-    {
-        try
-        {
+    private void updateRemoteRepositoriesFromConfig() {
+        try {
             List<RemoteRepositoryConfiguration> remoteRepoConfigs =
-                getArchivaConfiguration( ).getConfiguration( ).getRemoteRepositories( );
+                    getArchivaConfiguration().getConfiguration().getRemoteRepositories();
 
-            if ( remoteRepoConfigs == null )
-            {
+            if (remoteRepoConfigs == null) {
                 //noinspection unchecked
-                return Collections.emptyMap();
+                return;
             }
 
-            Map<String, RemoteRepository> remoteRepos = new LinkedHashMap<>( remoteRepoConfigs.size( ) );
-
-            Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap( );
-            for ( RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs )
-            {
-                RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
-                if ( providerMap.containsKey( repositoryType ) )
-                {
-                    RepositoryProvider provider = getProvider( repositoryType );
-                    try
-                    {
+            Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap();
+            for (RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs) {
+                RepositoryType repositoryType = RepositoryType.valueOf(repoConfig.getType());
+                if (providerMap.containsKey(repositoryType)) {
+                    RepositoryProvider provider = getProvider(repositoryType);
+                    try {
 
-                        RemoteRepository remoteRepository = createNewRemoteRepository( provider, repoConfig );
-                        remoteRepos.put( repoConfig.getId( ), remoteRepository);
-                    }
-                    catch ( Exception e )
-                    {
-                        log.error( "Could not create repository {} from config: {}", repoConfig.getId( ), e.getMessage( ), e );
+                        RemoteRepository remoteRepository = createNewRemoteRepository(provider, repoConfig);
+                        remoteRepositories.put(repoConfig.getId(), remoteRepository);
+                        pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, remoteRepository));
+                    } catch (Exception e) {
+                        log.error("Could not create repository {} from config: {}", repoConfig.getId(), e.getMessage(), e);
                     }
                 }
             }
 
-            return remoteRepos;
+            return;
         } catch (Throwable e) {
             log.error("Could not initialize remote repositories from config: {}", e.getMessage(), e);
             //noinspection unchecked
-            return Collections.emptyMap();
+            return;
         }
     }
 
-    private RemoteRepository createNewRemoteRepository( RepositoryProvider provider, RemoteRepositoryConfiguration cfg ) throws RepositoryException
-    {
+    private RemoteRepository createNewRemoteRepository(RepositoryProvider provider, RemoteRepositoryConfiguration cfg) throws RepositoryException {
         log.debug("Creating remote repo {}", cfg.getId());
-        RemoteRepository repo = provider.createRemoteInstance( cfg );
-        repo.addListener(this);
-        updateRepositoryReferences( provider, repo, cfg , null);
+        RemoteRepository repo = provider.createRemoteInstance(cfg);
+        repo.register(this);
+        updateRepositoryReferences(provider, repo, cfg, null);
         return repo;
 
     }
 
-    @SuppressWarnings( "unchecked" )
-    private void updateRepositoryReferences( RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException
-    {
-        if ( repo instanceof EditableRemoteRepository && repo.getContent() == null)
-        {
+    @SuppressWarnings("unchecked")
+    private void updateRepositoryReferences(RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException {
+        if (repo instanceof EditableRemoteRepository && repo.getContent() == null) {
             EditableRemoteRepository editableRepo = (EditableRemoteRepository) repo;
-            editableRepo.setContent( repositoryContentFactory.getRemoteRepositoryContent( repo ) );
-            if (repo.supportsFeature(IndexCreationFeature.class) && repo.getIndexingContext()==null ) {
+            editableRepo.setContent(repositoryContentFactory.getRemoteRepositoryContent(repo));
+            if (repo.supportsFeature(IndexCreationFeature.class) && repo.getIndexingContext() == null) {
                 createIndexingContext(editableRepo);
             }
         }
     }
 
-    private Map<String, RepositoryGroup> getRepositorGroupsFromConfig( )
-    {
-        try
-        {
+    private Map<String, RepositoryGroup> getRepositorGroupsFromConfig() {
+        try {
             List<RepositoryGroupConfiguration> repositoryGroupConfigurations =
-                    getArchivaConfiguration( ).getConfiguration( ).getRepositoryGroups();
+                    getArchivaConfiguration().getConfiguration().getRepositoryGroups();
 
-            if ( repositoryGroupConfigurations == null )
-            {
+            if (repositoryGroupConfigurations == null) {
                 return Collections.emptyMap();
             }
 
-            Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>( repositoryGroupConfigurations.size( ) );
-
-            Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap( );
-            for ( RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations )
-            {
-                RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
-                if ( providerMap.containsKey( repositoryType ) )
-                {
-                    try
-                    {
-                        RepositoryGroup repo = createNewRepositoryGroup( providerMap.get( repositoryType ), repoConfig );
-                        repositoryGroupMap.put( repo.getId( ), repo );
-                    }
-                    catch ( Exception e )
-                    {
-                        log.error( "Could not create repository group {}: {}", repoConfig.getId( ), e.getMessage( ), e );
+            Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>(repositoryGroupConfigurations.size());
+
+            Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap();
+            for (RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations) {
+                RepositoryType repositoryType = RepositoryType.valueOf(repoConfig.getType());
+                if (providerMap.containsKey(repositoryType)) {
+                    try {
+                        RepositoryGroup repo = createNewRepositoryGroup(providerMap.get(repositoryType), repoConfig);
+                        repositoryGroupMap.put(repo.getId(), repo);
+                    } catch (Exception e) {
+                        log.error("Could not create repository group {}: {}", repoConfig.getId(), e.getMessage(), e);
                     }
                 }
             }
             return repositoryGroupMap;
         } catch (Throwable e) {
-            log.error("Could not initialize repositories from config: {}",e.getMessage(), e );
+            log.error("Could not initialize repositories from config: {}", e.getMessage(), e);
             //noinspection unchecked
             return Collections.emptyMap();
         }
@@ -388,7 +348,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
 
     RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException {
         RepositoryGroup repositoryGroup = provider.createRepositoryGroup(config);
-        repositoryGroup.addListener(this);
+        repositoryGroup.register(this);
         updateRepositoryReferences(provider, repositoryGroup, config);
         return repositoryGroup;
     }
@@ -400,8 +360,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         }
     }
 
-    private ArchivaConfiguration getArchivaConfiguration( )
-    {
+    private ArchivaConfiguration getArchivaConfiguration() {
         return this.archivaConfiguration;
     }
 
@@ -410,16 +369,12 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      *
      * @return a list of managed and remote repositories
      */
-    public Collection<Repository> getRepositories( )
-    {
-        rwLock.readLock( ).lock( );
-        try
-        {
-            return Stream.concat( managedRepositories.values( ).stream( ), remoteRepositories.values( ).stream( )).collect( Collectors.toList( ) );
-        }
-        finally
-        {
-            rwLock.readLock( ).unlock( );
+    public Collection<Repository> getRepositories() {
+        rwLock.readLock().lock();
+        try {
+            return Stream.concat(managedRepositories.values().stream(), remoteRepositories.values().stream()).collect(Collectors.toList());
+        } finally {
+            rwLock.readLock().unlock();
         }
     }
 
@@ -428,14 +383,11 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      *
      * @return a list of managed repositories
      */
-    public Collection<ManagedRepository> getManagedRepositories( )
-    {
+    public Collection<ManagedRepository> getManagedRepositories() {
         rwLock.readLock().lock();
-        try
-        {
-            return uManagedRepository.values( );
-        } finally
-        {
+        try {
+            return uManagedRepository.values();
+        } finally {
             rwLock.readLock().unlock();
         }
     }
@@ -445,19 +397,16 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      *
      * @return a list of remote repositories
      */
-    public Collection<RemoteRepository> getRemoteRepositories( )
-    {
+    public Collection<RemoteRepository> getRemoteRepositories() {
         rwLock.readLock().lock();
-        try
-        {
-            return uRemoteRepositories.values( );
-        } finally
-        {
+        try {
+            return uRemoteRepositories.values();
+        } finally {
             rwLock.readLock().unlock();
         }
     }
 
-    public Collection<RepositoryGroup>  getRepositoryGroups() {
+    public Collection<RepositoryGroup> getRepositoryGroups() {
         rwLock.readLock().lock();
         try {
             return uRepositoryGroups.values();
@@ -473,30 +422,23 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param repoId the repository id
      * @return the repository if found, otherwise null
      */
-    public Repository getRepository( String repoId )
-    {
-        rwLock.readLock( ).lock( );
-        try
-        {
+    public Repository getRepository(String repoId) {
+        rwLock.readLock().lock();
+        try {
             log.debug("getRepository {}", repoId);
-            if ( managedRepositories.containsKey( repoId ) )
-            {
+            if (managedRepositories.containsKey(repoId)) {
                 log.debug("Managed repo");
-                return managedRepositories.get( repoId );
-            }
-            else if (remoteRepositories.containsKey(repoId))
-            {
+                return managedRepositories.get(repoId);
+            } else if (remoteRepositories.containsKey(repoId)) {
                 log.debug("Remote repo");
-                return remoteRepositories.get( repoId );
+                return remoteRepositories.get(repoId);
             } else if (repositoryGroups.containsKey(repoId)) {
                 return repositoryGroups.get(repoId);
             } else {
                 return null;
             }
-        }
-        finally
-        {
-            rwLock.readLock( ).unlock( );
+        } finally {
+            rwLock.readLock().unlock();
         }
     }
 
@@ -507,16 +449,12 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param repoId the repository id
      * @return the managed repository if found, otherwise null
      */
-    public ManagedRepository getManagedRepository( String repoId )
-    {
-        rwLock.readLock( ).lock( );
-        try
-        {
-            return managedRepositories.get( repoId );
-        }
-        finally
-        {
-            rwLock.readLock( ).unlock( );
+    public ManagedRepository getManagedRepository(String repoId) {
+        rwLock.readLock().lock();
+        try {
+            return managedRepositories.get(repoId);
+        } finally {
+            rwLock.readLock().unlock();
         }
     }
 
@@ -527,20 +465,16 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param repoId the repository id
      * @return the remote repository if found, otherwise null
      */
-    public RemoteRepository getRemoteRepository( String repoId )
-    {
-        rwLock.readLock( ).lock( );
-        try
-        {
-            return remoteRepositories.get( repoId );
-        }
-        finally
-        {
-            rwLock.readLock( ).unlock( );
+    public RemoteRepository getRemoteRepository(String repoId) {
+        rwLock.readLock().lock();
+        try {
+            return remoteRepositories.get(repoId);
+        } finally {
+            rwLock.readLock().unlock();
         }
     }
 
-    public RepositoryGroup getRepositoryGroup( String groupId ) {
+    public RepositoryGroup getRepositoryGroup(String groupId) {
         rwLock.readLock().lock();
         try {
             return repositoryGroups.get(groupId);
@@ -549,6 +483,19 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         }
     }
 
+    /*
+     * The <code>ignoreConfigEvents</code> works only for synchronized configuration events.
+     * If the configuration throws async events, we cannot know, if the event is caused by this instance or another thread.
+     */
+    private void saveConfiguration(Configuration configuration) throws IndeterminateConfigurationException, RegistryException {
+        ignoreConfigEvents = true;
+        try {
+            getArchivaConfiguration().save(configuration);
+        } finally {
+            ignoreConfigEvents = false;
+        }
+    }
+
     /**
      * Adds a new repository to the current list, or replaces the repository definition with
      * the same id, if it exists already.
@@ -557,50 +504,43 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param managedRepository the new repository.
      * @throws RepositoryException if the new repository could not be saved to the configuration.
      */
-    public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    public ManagedRepository putRepository(ManagedRepository managedRepository) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = managedRepository.getId();
-            if (remoteRepositories.containsKey( id )) {
-                throw new RepositoryException( "There exists a remote repository with id "+id+". Could not update with managed repository." );
+            if (remoteRepositories.containsKey(id)) {
+                throw new RepositoryException("There exists a remote repository with id " + id + ". Could not update with managed repository.");
             }
 
-            ManagedRepository originRepo = managedRepositories.put( id, managedRepository );
-            try
-            {
-                if (originRepo!=null) {
+            ManagedRepository originRepo = managedRepositories.put(id, managedRepository);
+            try {
+                if (originRepo != null) {
                     originRepo.close();
                 }
-                RepositoryProvider provider = getProvider( managedRepository.getType() );
-                ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration( managedRepository );
-                Configuration configuration = getArchivaConfiguration( ).getConfiguration( );
-                updateRepositoryReferences( provider, managedRepository, newCfg, configuration );
-                ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( id );
-                if (oldCfg!=null) {
-                    configuration.removeManagedRepository( oldCfg );
+                RepositoryProvider provider = getProvider(managedRepository.getType());
+                ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration(managedRepository);
+                Configuration configuration = getArchivaConfiguration().getConfiguration();
+                updateRepositoryReferences(provider, managedRepository, newCfg, configuration);
+                ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById(id);
+                if (oldCfg != null) {
+                    configuration.removeManagedRepository(oldCfg);
                 }
-                configuration.addManagedRepository( newCfg );
-                getArchivaConfiguration( ).save( configuration );
+                configuration.addManagedRepository(newCfg);
+                saveConfiguration(configuration);
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, managedRepository));
                 return managedRepository;
-            }
-            catch ( Exception e )
-            {
+            } catch (Exception e) {
                 // Rollback
-                if ( originRepo != null )
-                {
-                    managedRepositories.put( id, originRepo );
+                if (originRepo != null) {
+                    managedRepositories.put(id, originRepo);
                 } else {
                     managedRepositories.remove(id);
                 }
                 log.error("Exception during configuration update {}", e.getMessage(), e);
-                throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
+                throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage()));
             }
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
     }
 
@@ -612,34 +552,27 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @return the updated or created repository
      * @throws RepositoryException if an error occurs, or the configuration is not valid.
      */
-    public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    public ManagedRepository putRepository(ManagedRepositoryConfiguration managedRepositoryConfiguration) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = managedRepositoryConfiguration.getId();
-            final RepositoryType repositoryType = RepositoryType.valueOf( managedRepositoryConfiguration.getType() );
+            final RepositoryType repositoryType = RepositoryType.valueOf(managedRepositoryConfiguration.getType());
             Configuration configuration = getArchivaConfiguration().getConfiguration();
             ManagedRepository repo = managedRepositories.get(id);
-            ManagedRepositoryConfiguration oldCfg = repo!=null ? getProvider( repositoryType ).getManagedConfiguration( repo ) : null;
-            repo = putRepository( managedRepositoryConfiguration, configuration );
-            try
-            {
-                getArchivaConfiguration().save(configuration);
-            }
-            catch ( IndeterminateConfigurationException | RegistryException e )
-            {
-                if (oldCfg!=null) {
-                    getProvider( repositoryType ).updateManagedInstance( (EditableManagedRepository)repo, oldCfg );
+            ManagedRepositoryConfiguration oldCfg = repo != null ? getProvider(repositoryType).getManagedConfiguration(repo) : null;
+            repo = putRepository(managedRepositoryConfiguration, configuration);
+            try {
+                saveConfiguration(configuration);
+            } catch (IndeterminateConfigurationException | RegistryException e) {
+                if (oldCfg != null) {
+                    getProvider(repositoryType).updateManagedInstance((EditableManagedRepository) repo, oldCfg);
                 }
-                log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(),e );
-                throw new RepositoryException( "Could not save the configuration for repository "+id+": "+e.getMessage() );
+                log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(), e);
+                throw new RepositoryException("Could not save the configuration for repository " + id + ": " + e.getMessage());
             }
             return repo;
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
 
     }
@@ -649,40 +582,35 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * the configuration is not saved.
      *
      * @param managedRepositoryConfiguration the new or changed repository configuration
-     * @param configuration the configuration object
+     * @param configuration                  the configuration object
      * @return the new or updated repository
      * @throws RepositoryException if the configuration cannot be saved or updated
      */
-    @SuppressWarnings( "unchecked" )
-    public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    @SuppressWarnings("unchecked")
+    public ManagedRepository putRepository(ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = managedRepositoryConfiguration.getId();
-            final RepositoryType repoType = RepositoryType.valueOf( managedRepositoryConfiguration.getType() );
+            final RepositoryType repoType = RepositoryType.valueOf(managedRepositoryConfiguration.getType());
             ManagedRepository repo;
-            if (managedRepositories.containsKey( id )) {
+            if (managedRepositories.containsKey(id)) {
                 repo = managedRepositories.get(id);
-                if (repo instanceof EditableManagedRepository)
-                {
-                    getProvider( repoType ).updateManagedInstance( (EditableManagedRepository) repo, managedRepositoryConfiguration );
+                if (repo instanceof EditableManagedRepository) {
+                    getProvider(repoType).updateManagedInstance((EditableManagedRepository) repo, managedRepositoryConfiguration);
                 } else {
-                    throw new RepositoryException( "The repository is not editable "+id );
+                    throw new RepositoryException("The repository is not editable " + id);
                 }
-            } else
-            {
-                repo = getProvider( repoType ).createManagedInstance( managedRepositoryConfiguration );
-                repo.addListener(this);
+            } else {
+                repo = getProvider(repoType).createManagedInstance(managedRepositoryConfiguration);
+                repo.register(this);
                 managedRepositories.put(id, repo);
             }
-            updateRepositoryReferences( getProvider( repoType  ), repo, managedRepositoryConfiguration, configuration );
-            replaceOrAddRepositoryConfig( managedRepositoryConfiguration, configuration );
+            updateRepositoryReferences(getProvider(repoType), repo, managedRepositoryConfiguration, configuration);
+            replaceOrAddRepositoryConfig(managedRepositoryConfiguration, configuration);
+            pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
             return repo;
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
     }
 
@@ -695,46 +623,38 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param repositoryGroup the new repository group.
      * @throws RepositoryException if the new repository group could not be saved to the configuration.
      */
-    public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    public RepositoryGroup putRepositoryGroup(RepositoryGroup repositoryGroup) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = repositoryGroup.getId();
-            RepositoryGroup originRepo = repositoryGroups.put( id, repositoryGroup );
-            try
-            {
-                if (originRepo!=null) {
+            RepositoryGroup originRepo = repositoryGroups.put(id, repositoryGroup);
+            try {
+                if (originRepo != null) {
                     originRepo.close();
                 }
-                RepositoryProvider provider = getProvider( repositoryGroup.getType() );
-                RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration( repositoryGroup );
-                Configuration configuration = getArchivaConfiguration( ).getConfiguration( );
-                updateRepositoryReferences( provider, repositoryGroup, newCfg );
-                RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( id );
-                if (oldCfg!=null) {
-                    configuration.removeRepositoryGroup( oldCfg );
+                RepositoryProvider provider = getProvider(repositoryGroup.getType());
+                RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration(repositoryGroup);
+                Configuration configuration = getArchivaConfiguration().getConfiguration();
+                updateRepositoryReferences(provider, repositoryGroup, newCfg);
+                RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById(id);
+                if (oldCfg != null) {
+                    configuration.removeRepositoryGroup(oldCfg);
                 }
-                configuration.addRepositoryGroup( newCfg );
-                getArchivaConfiguration( ).save( configuration );
+                configuration.addRepositoryGroup(newCfg);
+                saveConfiguration(configuration);
                 return repositoryGroup;
-            }
-            catch ( Exception e )
-            {
+            } catch (Exception e) {
                 // Rollback
-                if ( originRepo != null )
-                {
-                    repositoryGroups.put( id, originRepo );
+                if (originRepo != null) {
+                    repositoryGroups.put(id, originRepo);
                 } else {
                     repositoryGroups.remove(id);
                 }
                 log.error("Exception during configuration update {}", e.getMessage(), e);
-                throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
+                throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage()));
             }
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
     }
 
@@ -746,34 +666,27 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @return the updated or created repository
      * @throws RepositoryException if an error occurs, or the configuration is not valid.
      */
-    public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    public RepositoryGroup putRepositoryGroup(RepositoryGroupConfiguration repositoryGroupConfiguration) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = repositoryGroupConfiguration.getId();
-            final RepositoryType repositoryType = RepositoryType.valueOf( repositoryGroupConfiguration.getType() );
+            final RepositoryType repositoryType = RepositoryType.valueOf(repositoryGroupConfiguration.getType());
             Configuration configuration = getArchivaConfiguration().getConfiguration();
             RepositoryGroup repo = repositoryGroups.get(id);
-            RepositoryGroupConfiguration oldCfg = repo!=null ? getProvider( repositoryType ).getRepositoryGroupConfiguration( repo ) : null;
-            repo = putRepositoryGroup( repositoryGroupConfiguration, configuration );
-            try
-            {
-                getArchivaConfiguration().save(configuration);
-            }
-            catch ( IndeterminateConfigurationException | RegistryException e )
-            {
-                if (oldCfg!=null) {
-                    getProvider( repositoryType ).updateRepositoryGroupInstance( (EditableRepositoryGroup) repo, oldCfg );
+            RepositoryGroupConfiguration oldCfg = repo != null ? getProvider(repositoryType).getRepositoryGroupConfiguration(repo) : null;
+            repo = putRepositoryGroup(repositoryGroupConfiguration, configuration);
+            try {
+                saveConfiguration(configuration);
+            } catch (IndeterminateConfigurationException | RegistryException e) {
+                if (oldCfg != null) {
+                    getProvider(repositoryType).updateRepositoryGroupInstance((EditableRepositoryGroup) repo, oldCfg);
                 }
-                log.error("Could not save the configuration for repository group {}: {}", id, e.getMessage(),e );
-                throw new RepositoryException( "Could not save the configuration for repository group "+id+": "+e.getMessage() );
+                log.error("Could not save the configuration for repository group {}: {}", id, e.getMessage(), e);
+                throw new RepositoryException("Could not save the configuration for repository group " + id + ": " + e.getMessage());
             }
             return repo;
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
 
     }
@@ -783,41 +696,35 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * the configuration is not saved.
      *
      * @param repositoryGroupConfiguration the new or changed repository configuration
-     * @param configuration the configuration object
+     * @param configuration                the configuration object
      * @return the new or updated repository
      * @throws RepositoryException if the configuration cannot be saved or updated
      */
-    @SuppressWarnings( "unchecked" )
-    public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    @SuppressWarnings("unchecked")
+    public RepositoryGroup putRepositoryGroup(RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = repositoryGroupConfiguration.getId();
-            final RepositoryType repoType = RepositoryType.valueOf( repositoryGroupConfiguration.getType() );
+            final RepositoryType repoType = RepositoryType.valueOf(repositoryGroupConfiguration.getType());
             RepositoryGroup repo;
             setRepositoryGroupDefaults(repositoryGroupConfiguration);
-            if (repositoryGroups.containsKey( id )) {
+            if (repositoryGroups.containsKey(id)) {
                 repo = repositoryGroups.get(id);
-                if (repo instanceof EditableRepositoryGroup)
-                {
-                    getProvider( repoType ).updateRepositoryGroupInstance( (EditableRepositoryGroup) repo, repositoryGroupConfiguration );
+                if (repo instanceof EditableRepositoryGroup) {
+                    getProvider(repoType).updateRepositoryGroupInstance((EditableRepositoryGroup) repo, repositoryGroupConfiguration);
                 } else {
-                    throw new RepositoryException( "The repository is not editable "+id );
+                    throw new RepositoryException("The repository is not editable " + id);
                 }
-            } else
-            {
-                repo = getProvider( repoType ).createRepositoryGroup( repositoryGroupConfiguration );
-                repo.addListener(this);
+            } else {
+                repo = getProvider(repoType).createRepositoryGroup(repositoryGroupConfiguration);
+                repo.register(this);
                 repositoryGroups.put(id, repo);
             }
-            updateRepositoryReferences( getProvider( repoType  ), repo, repositoryGroupConfiguration );
-            replaceOrAddRepositoryConfig( repositoryGroupConfiguration, configuration );
+            updateRepositoryReferences(getProvider(repoType), repo, repositoryGroupConfiguration);
+            replaceOrAddRepositoryConfig(repositoryGroupConfiguration, configuration);
             return repo;
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
     }
 
@@ -825,7 +732,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         if (StringUtils.isEmpty(repositoryGroupConfiguration.getMergedIndexPath())) {
             repositoryGroupConfiguration.setMergedIndexPath(DEFAULT_INDEX_PATH);
         }
-        if (repositoryGroupConfiguration.getMergedIndexTtl()<=0) {
+        if (repositoryGroupConfiguration.getMergedIndexTtl() <= 0) {
             repositoryGroupConfiguration.setMergedIndexTtl(300);
         }
         if (StringUtils.isEmpty(repositoryGroupConfiguration.getCronExpression())) {
@@ -834,79 +741,72 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     }
 
     private void replaceOrAddRepositoryConfig(ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) {
-        ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( managedRepositoryConfiguration.getId() );
-        if ( oldCfg !=null) {
-            configuration.removeManagedRepository( oldCfg );
+        ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById(managedRepositoryConfiguration.getId());
+        if (oldCfg != null) {
+            configuration.removeManagedRepository(oldCfg);
         }
-        configuration.addManagedRepository( managedRepositoryConfiguration );
+        configuration.addManagedRepository(managedRepositoryConfiguration);
     }
 
     private void replaceOrAddRepositoryConfig(RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration) {
-        RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById( remoteRepositoryConfiguration.getId() );
-        if ( oldCfg !=null) {
-            configuration.removeRemoteRepository( oldCfg );
+        RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById(remoteRepositoryConfiguration.getId());
+        if (oldCfg != null) {
+            configuration.removeRemoteRepository(oldCfg);
         }
-        configuration.addRemoteRepository( remoteRepositoryConfiguration );
+        configuration.addRemoteRepository(remoteRepositoryConfiguration);
     }
 
     private void replaceOrAddRepositoryConfig(RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration) {
-        RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( repositoryGroupConfiguration.getId() );
-        if ( oldCfg !=null) {
-            configuration.removeRepositoryGroup( oldCfg );
+        RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById(repositoryGroupConfiguration.getId());
+        if (oldCfg != null) {
+            configuration.removeRepositoryGroup(oldCfg);
         }
-        configuration.addRepositoryGroup( repositoryGroupConfiguration);
+        configuration.addRepositoryGroup(repositoryGroupConfiguration);
     }
 
-    public RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    public RemoteRepository putRepository(RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = remoteRepository.getId();
-            if (managedRepositories.containsKey( id )) {
-                throw new RepositoryException( "There exists a managed repository with id "+id+". Could not update with remote repository." );
+            if (managedRepositories.containsKey(id)) {
+                throw new RepositoryException("There exists a managed repository with id " + id + ". Could not update with remote repository.");
             }
-            RemoteRepository originRepo = remoteRepositories.put( id, remoteRepository );
-            RemoteRepositoryConfiguration oldCfg=null;
+            RemoteRepository originRepo = remoteRepositories.put(id, remoteRepository);
+            RemoteRepositoryConfiguration oldCfg = null;
             RemoteRepositoryConfiguration newCfg;
-            try
-            {
-                if (originRepo!=null) {
+            try {
+                if (originRepo != null) {
                     originRepo.close();
                 }
-                final RepositoryProvider provider = getProvider( remoteRepository.getType() );
-                newCfg = provider.getRemoteConfiguration( remoteRepository );
-                updateRepositoryReferences( provider, remoteRepository, newCfg, configuration );
-                oldCfg = configuration.findRemoteRepositoryById( id );
-                if (oldCfg!=null) {
-                    configuration.removeRemoteRepository( oldCfg );
+                final RepositoryProvider provider = getProvider(remoteRepository.getType());
+                newCfg = provider.getRemoteConfiguration(remoteRepository);
+                updateRepositoryReferences(provider, remoteRepository, newCfg, configuration);
+                oldCfg = configuration.findRemoteRepositoryById(id);
+                if (oldCfg != null) {
+                    configuration.removeRemoteRepository(oldCfg);
                 }
-                configuration.addRemoteRepository( newCfg );
+                configuration.addRemoteRepository(newCfg);
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, remoteRepository));
                 return remoteRepository;
-            }
-            catch ( Exception e )
-            {
+            } catch (Exception e) {
                 // Rollback
-                if ( originRepo != null )
-                {
-                    remoteRepositories.put( id, originRepo );
+                if (originRepo != null) {
+                    remoteRepositories.put(id, originRepo);
                 } else {
-                    remoteRepositories.remove( id);
+                    remoteRepositories.remove(id);
                 }
-                if (oldCfg!=null) {
-                    RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
-                    if (cfg!=null) {
-                        configuration.removeRemoteRepository( cfg );
-                        configuration.addRemoteRepository( oldCfg );
+                if (oldCfg != null) {
+                    RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById(id);
+                    if (cfg != null) {
+                        configuration.removeRemoteRepository(cfg);
+                        configuration.addRemoteRepository(oldCfg);
                     }
                 }
                 log.error("Error while adding remote repository {}", e.getMessage(), e);
-                throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
+                throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage()));
             }
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
     }
 
@@ -917,27 +817,20 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param remoteRepository the remote repository to add
      * @throws RepositoryException if an error occurs during configuration save
      */
-    public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    public RemoteRepository putRepository(RemoteRepository remoteRepository) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             Configuration configuration = getArchivaConfiguration().getConfiguration();
-            try
-            {
-                RemoteRepository repo = putRepository( remoteRepository, configuration );
-                getArchivaConfiguration().save(configuration);
+            try {
+                RemoteRepository repo = putRepository(remoteRepository, configuration);
+                saveConfiguration(configuration);
                 return repo;
-            }
-            catch ( RegistryException | IndeterminateConfigurationException e )
-            {
+            } catch (RegistryException | IndeterminateConfigurationException e) {
                 log.error("Error while saving remote repository {}", e.getMessage(), e);
-                throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
+                throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage()));
             }
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
     }
 
@@ -949,34 +842,27 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @return the updated or created repository
      * @throws RepositoryException if an error occurs, or the configuration is not valid.
      */
-    public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    public RemoteRepository putRepository(RemoteRepositoryConfiguration remoteRepositoryConfiguration) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = remoteRepositoryConfiguration.getId();
-            final RepositoryType repositoryType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType() );
+            final RepositoryType repositoryType = RepositoryType.valueOf(remoteRepositoryConfiguration.getType());
             Configuration configuration = getArchivaConfiguration().getConfiguration();
             RemoteRepository repo = remoteRepositories.get(id);
-            RemoteRepositoryConfiguration oldCfg = repo!=null ? getProvider( repositoryType ).getRemoteConfiguration( repo ) : null;
-            repo = putRepository( remoteRepositoryConfiguration, configuration );
-            try
-            {
-                getArchivaConfiguration().save(configuration);
-            }
-            catch ( IndeterminateConfigurationException | RegistryException e )
-            {
-                if (oldCfg!=null) {
-                    getProvider( repositoryType ).updateRemoteInstance( (EditableRemoteRepository)repo, oldCfg );
+            RemoteRepositoryConfiguration oldCfg = repo != null ? getProvider(repositoryType).getRemoteConfiguration(repo) : null;
+            repo = putRepository(remoteRepositoryConfiguration, configuration);
+            try {
+                saveConfiguration(configuration);
+            } catch (IndeterminateConfigurationException | RegistryException e) {
+                if (oldCfg != null) {
+                    getProvider(repositoryType).updateRemoteInstance((EditableRemoteRepository) repo, oldCfg);
                 }
-                log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(),e );
-                throw new RepositoryException( "Could not save the configuration for repository "+id+": "+e.getMessage() );
+                log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(), e);
+                throw new RepositoryException("Could not save the configuration for repository " + id + ": " + e.getMessage());
             }
             return repo;
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
 
     }
@@ -986,40 +872,35 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * the configuration is not saved.
      *
      * @param remoteRepositoryConfiguration the new or changed repository configuration
-     * @param configuration the configuration object
+     * @param configuration                 the configuration object
      * @return the new or updated repository
      * @throws RepositoryException if the configuration cannot be saved or updated
      */
-    @SuppressWarnings( "unchecked" )
-    public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration) throws RepositoryException
-    {
-        rwLock.writeLock( ).lock( );
-        try
-        {
+    @SuppressWarnings("unchecked")
+    public RemoteRepository putRepository(RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration) throws RepositoryException {
+        rwLock.writeLock().lock();
+        try {
             final String id = remoteRepositoryConfiguration.getId();
-            final RepositoryType repoType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType() );
+            final RepositoryType repoType = RepositoryType.valueOf(remoteRepositoryConfiguration.getType());
             RemoteRepository repo;
-            if (remoteRepositories.containsKey( id )) {
+            if (remoteRepositories.containsKey(id)) {
                 repo = remoteRepositories.get(id);
-                if (repo instanceof EditableRemoteRepository)
-                {
-                    getProvider( repoType ).updateRemoteInstance( (EditableRemoteRepository) repo, remoteRepositoryConfiguration );
+                if (repo instanceof EditableRemoteRepository) {
+                    getProvider(repoType).updateRemoteInstance((EditableRemoteRepository) repo, remoteRepositoryConfiguration);
                 } else {
-                    throw new RepositoryException( "The repository is not editable "+id );
+                    throw new RepositoryException("The repository is not editable " + id);
                 }
-            } else
-            {
-                repo = getProvider( repoType ).createRemoteInstance( remoteRepositoryConfiguration );
-                repo.addListener(this);
+            } else {
+                repo = getProvider(repoType).createRemoteInstance(remoteRepositoryConfiguration);
+                repo.register(this);
                 remoteRepositories.put(id, repo);
             }
-            updateRepositoryReferences( getProvider( repoType  ), repo, remoteRepositoryConfiguration, configuration );
-            replaceOrAddRepositoryConfig( remoteRepositoryConfiguration, configuration );
+            updateRepositoryReferences(getProvider(repoType), repo, remoteRepositoryConfiguration, configuration);
+            replaceOrAddRepositoryConfig(remoteRepositoryConfiguration, configuration);
+            pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
             return repo;
-        }
-        finally
-        {
-            rwLock.writeLock( ).unlock( );
+        } finally {
+            rwLock.writeLock().unlock();
         }
 
 
@@ -1027,26 +908,25 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
 
     public void removeRepository(String repoId) throws RepositoryException {
         Repository repo = getRepository(repoId);
-        if (repo!=null) {
+        if (repo != null) {
             removeRepository(repo);
         }
     }
 
-    @SuppressWarnings( "unchecked" )
-    public void removeRepository(Repository repo) throws RepositoryException
-    {
-        if (repo==null) {
+    @SuppressWarnings("unchecked")
+    public void removeRepository(Repository repo) throws RepositoryException {
+        if (repo == null) {
             log.warn("Trying to remove null repository");
             return;
         }
-        if (repo instanceof RemoteRepository ) {
-            removeRepository( (RemoteRepository)repo );
+        if (repo instanceof RemoteRepository) {
+            removeRepository((RemoteRepository) repo);
         } else if (repo instanceof ManagedRepository) {
-            removeRepository( (ManagedRepository)repo);
-        } else if (repo instanceof RepositoryGroup ) {
+            removeRepository((ManagedRepository) repo);
+        } else if (repo instanceof RepositoryGroup) {
             removeRepositoryGroup((RepositoryGroup) repo);
-        }else {
-            throw new RepositoryException( "Repository type not known: "+repo.getClass() );
+        } else {
+            throw new RepositoryException("Repository type not known: " + repo.getClass());
         }
     }
 
@@ -1057,64 +937,59 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param managedRepository the managed repository to remove
      * @throws RepositoryException if a error occurs during configuration save
      */
-    public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException
-    {
+    public void removeRepository(ManagedRepository managedRepository) throws RepositoryException {
         final String id = managedRepository.getId();
-        ManagedRepository repo = getManagedRepository( id );
-        if (repo!=null) {
+        ManagedRepository repo = getManagedRepository(id);
+        if (repo != null) {
             rwLock.writeLock().lock();
             try {
-                repo = managedRepositories.remove( id );
-                if (repo!=null) {
+                repo = managedRepositories.remove(id);
+                if (repo != null) {
                     repo.close();
                     removeRepositoryFromGroups(repo);
                     Configuration configuration = getArchivaConfiguration().getConfiguration();
-                    ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
-                    if (cfg!=null) {
-                        configuration.removeManagedRepository( cfg );
+                    ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById(id);
+                    if (cfg != null) {
+                        configuration.removeManagedRepository(cfg);
                     }
-                    getArchivaConfiguration().save( configuration );
+                    saveConfiguration(configuration);
                 }
-
-            }
-            catch ( RegistryException | IndeterminateConfigurationException e )
-            {
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+            } catch (RegistryException | IndeterminateConfigurationException e) {
                 // Rollback
                 log.error("Could not save config after repository removal: {}", e.getMessage(), e);
                 managedRepositories.put(repo.getId(), repo);
-                throw new RepositoryException( "Could not save configuration after repository removal: "+e.getMessage() );
-            } finally
-            {
+                throw new RepositoryException("Could not save configuration after repository removal: " + e.getMessage());
+            } finally {
                 rwLock.writeLock().unlock();
             }
         }
     }
 
     private void removeRepositoryFromGroups(ManagedRepository repo) {
-        if (repo!=null) {
+        if (repo != null) {
             repositoryGroups.values().stream().filter(repoGroup -> repoGroup instanceof EditableRepository).
                     map(repoGroup -> (EditableRepositoryGroup) repoGroup).forEach(repoGroup -> repoGroup.removeRepository(repo));
         }
     }
 
-    public void removeRepository(ManagedRepository managedRepository, Configuration configuration) throws RepositoryException
-    {
+    public void removeRepository(ManagedRepository managedRepository, Configuration configuration) throws RepositoryException {
         final String id = managedRepository.getId();
-        ManagedRepository repo = getManagedRepository( id );
-        if (repo!=null) {
+        ManagedRepository repo = getManagedRepository(id);
+        if (repo != null) {
             rwLock.writeLock().lock();
             try {
-                repo = managedRepositories.remove( id );
-                if (repo!=null) {
+                repo = managedRepositories.remove(id);
+                if (repo != null) {
                     repo.close();
                     removeRepositoryFromGroups(repo);
-                    ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
-                    if (cfg!=null) {
-                        configuration.removeManagedRepository( cfg );
+                    ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById(id);
+                    if (cfg != null) {
+                        configuration.removeManagedRepository(cfg);
                     }
                 }
-            } finally
-            {
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+            } finally {
                 rwLock.writeLock().unlock();
             }
         }
@@ -1129,55 +1004,49 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param repositoryGroup the repository group to remove
      * @throws RepositoryException if a error occurs during configuration save
      */
-    public void removeRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
-    {
+    public void removeRepositoryGroup(RepositoryGroup repositoryGroup) throws RepositoryException {
         final String id = repositoryGroup.getId();
-        RepositoryGroup repo = getRepositoryGroup( id );
-        if (repo!=null) {
+        RepositoryGroup repo = getRepositoryGroup(id);
+        if (repo != null) {
             rwLock.writeLock().lock();
             try {
-                repo = repositoryGroups.remove( id );
-                if (repo!=null) {
+                repo = repositoryGroups.remove(id);
+                if (repo != null) {
                     repo.close();
                     Configuration configuration = getArchivaConfiguration().getConfiguration();
-                    RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
-                    if (cfg!=null) {
-                        configuration.removeRepositoryGroup( cfg );
+                    RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById(id);
+                    if (cfg != null) {
+                        configuration.removeRepositoryGroup(cfg);
                     }
-                    getArchivaConfiguration().save( configuration );
+                    saveConfiguration(configuration);
                 }
 
-            }
-            catch ( RegistryException | IndeterminateConfigurationException e )
-            {
+            } catch (RegistryException | IndeterminateConfigurationException e) {
                 // Rollback
                 log.error("Could not save config after repository removal: {}", e.getMessage(), e);
                 repositoryGroups.put(repo.getId(), repo);
-                throw new RepositoryException( "Could not save configuration after repository removal: "+e.getMessage() );
-            } finally
-            {
+                throw new RepositoryException("Could not save configuration after repository removal: " + e.getMessage());
+            } finally {
                 rwLock.writeLock().unlock();
             }
         }
     }
 
-    public void removeRepositoryGroup(RepositoryGroup repositoryGroup, Configuration configuration) throws RepositoryException
-    {
+    public void removeRepositoryGroup(RepositoryGroup repositoryGroup, Configuration configuration) throws RepositoryException {
         final String id = repositoryGroup.getId();
-        RepositoryGroup repo = getRepositoryGroup( id );
-        if (repo!=null) {
+        RepositoryGroup repo = getRepositoryGroup(id);
+        if (repo != null) {
             rwLock.writeLock().lock();
             try {
-                repo = repositoryGroups.remove( id );
-                if (repo!=null) {
+                repo = repositoryGroups.remove(id);
+                if (repo != null) {
                     repo.close();
-                    RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
-                    if (cfg!=null) {
-                        configuration.removeRepositoryGroup( cfg );
+                    RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById(id);
+                    if (cfg != null) {
+                        configuration.removeRepositoryGroup(cfg);
                     }
                 }
-            } finally
-            {
+            } finally {
                 rwLock.writeLock().unlock();
             }
         }
@@ -1185,17 +1054,17 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     }
 
     private void doRemoveRepo(RemoteRepository repo, Configuration configuration) {
-            repo.close();
-            RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById(repo.getId());
-            if (cfg != null) {
-                configuration.removeRemoteRepository(cfg);
-            }
-            List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>(configuration.getProxyConnectors());
-            for (ProxyConnectorConfiguration proxyConnector : proxyConnectors) {
-                if (StringUtils.equals(proxyConnector.getTargetRepoId(), repo.getId())) {
-                    configuration.removeProxyConnector(proxyConnector);
-                }
+        repo.close();
+        RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById(repo.getId());
+        if (cfg != null) {
+            configuration.removeRemoteRepository(cfg);
+        }
+        List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>(configuration.getProxyConnectors());
+        for (ProxyConnectorConfiguration proxyConnector : proxyConnectors) {
+            if (StringUtils.equals(proxyConnector.getTargetRepoId(), repo.getId())) {
+                configuration.removeProxyConnector(proxyConnector);
             }
+        }
     }
 
     /**
@@ -1205,47 +1074,43 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param remoteRepository the remote repository to remove
      * @throws RepositoryException if a error occurs during configuration save
      */
-    public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException
-    {
+    public void removeRepository(RemoteRepository remoteRepository) throws RepositoryException {
 
         final String id = remoteRepository.getId();
-        RemoteRepository repo = getRemoteRepository( id );
-        if (repo!=null) {
+        RemoteRepository repo = getRemoteRepository(id);
+        if (repo != null) {
             rwLock.writeLock().lock();
             try {
-                repo = remoteRepositories.remove( id );
-                if (repo!=null) {
+                repo = remoteRepositories.remove(id);
+                if (repo != null) {
                     Configuration configuration = getArchivaConfiguration().getConfiguration();
                     doRemoveRepo(repo, configuration);
-                    getArchivaConfiguration().save( configuration );
+                    saveConfiguration(configuration);
                 }
-            }
-            catch ( RegistryException | IndeterminateConfigurationException e )
-            {
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+            } catch (RegistryException | IndeterminateConfigurationException e) {
                 // Rollback
                 log.error("Could not save config after repository removal: {}", e.getMessage(), e);
                 remoteRepositories.put(repo.getId(), repo);
-                throw new RepositoryException( "Could not save configuration after repository removal: "+e.getMessage() );
-            } finally
-            {
+                throw new RepositoryException("Could not save configuration after repository removal: " + e.getMessage());
+            } finally {
                 rwLock.writeLock().unlock();
             }
         }
     }
 
-    public void removeRepository( RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException
-    {
+    public void removeRepository(RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException {
         final String id = remoteRepository.getId();
-        RemoteRepository repo = getRemoteRepository( id );
-        if (repo!=null) {
+        RemoteRepository repo = getRemoteRepository(id);
+        if (repo != null) {
             rwLock.writeLock().lock();
             try {
-                repo = remoteRepositories.remove( id );
-                if (repo!=null) {
+                repo = remoteRepositories.remove(id);
+                if (repo != null) {
                     doRemoveRepo(repo, configuration);
                 }
-            } finally
-            {
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+            } finally {
                 rwLock.writeLock().unlock();
             }
         }
@@ -1265,7 +1130,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param repo
      * @throws IndexUpdateFailedException
      */
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     public void resetIndexingContext(Repository repo) throws IndexUpdateFailedException {
         if (repo.hasIndex() && repo instanceof EditableRepository) {
             EditableRepository eRepo = (EditableRepository) repo;
@@ -1282,27 +1147,26 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param repo The origin repository
      * @return The cloned repository.
      */
-    public ManagedRepository clone(ManagedRepository repo, String newId) throws RepositoryException
-    {
+    public ManagedRepository clone(ManagedRepository repo, String newId) throws RepositoryException {
         if (managedRepositories.containsKey(newId) || remoteRepositories.containsKey(newId)) {
-            throw new RepositoryException("The given id exists already "+newId);
+            throw new RepositoryException("The given id exists already " + newId);
         }
         RepositoryProvider provider = getProvider(repo.getType());
         ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration(repo);
         cfg.setId(newId);
         ManagedRepository cloned = provider.createManagedInstance(cfg);
-        cloned.addListener(this);
+        cloned.register(this);
         return cloned;
     }
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     public <T extends Repository> Repository clone(T repo, String newId) throws RepositoryException {
-        if (repo instanceof RemoteRepository ) {
-            return this.clone((RemoteRepository)repo, newId);
+        if (repo instanceof RemoteRepository) {
+            return this.clone((RemoteRepository) repo, newId);
         } else if (repo instanceof ManagedRepository) {
-            return this.clone((ManagedRepository)repo, newId);
+            return this.clone((ManagedRepository) repo, newId);
         } else {
-            throw new RepositoryException("This repository class is not supported "+ repo.getClass().getName());
+            throw new RepositoryException("This repository class is not supported " + repo.getClass().getName());
         }
     }
 
@@ -1313,51 +1177,83 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @param repo The origin repository
      * @return The cloned repository.
      */
-    public RemoteRepository clone( RemoteRepository repo, String newId) throws RepositoryException
-    {
+    public RemoteRepository clone(RemoteRepository repo, String newId) throws RepositoryException {
         if (managedRepositories.containsKey(newId) || remoteRepositories.containsKey(newId)) {
-            throw new RepositoryException("The given id exists already "+newId);
+            throw new RepositoryException("The given id exists already " + newId);
         }
         RepositoryProvider provider = getProvider(repo.getType());
         RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration(repo);
         cfg.setId(newId);
         RemoteRepository cloned = provider.createRemoteInstance(cfg);
-        cloned.addListener(this);
+        cloned.register(this);
         return cloned;
     }
 
 
     @Override
     public void configurationEvent(ConfigurationEvent event) {
-
+        // Note: the ignoreConfigEvents flag does not work, if the config events are asynchronous.
+        if (!ignoreConfigEvents) {
+            reload();
+        }
     }
 
 
     @Override
-    public void addListener(RepositoryEventListener listener) {
+    public void register(RepositoryEventListener listener) {
         if (!this.listeners.contains(listener)) {
             this.listeners.add(listener);
         }
     }
 
     @Override
-    public void removeListener(RepositoryEventListener listener) {
+    public void register(RepositoryEventListener listener, EventType type) {
+        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);
+        }
+    }
+
+    @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()) {
+            listeners.remove(listener);
+        }
     }
 
     @Override
     public void clearListeners() {
         this.listeners.clear();
+        this.typeListenerMap.clear();
     }
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     @Override
-    public <T> void raise(RepositoryEvent<T> event) {
-        if (event instanceof IndexCreationEvent ) {
-            if (managedRepositories.containsKey(event.getRepository().getId()) ||
-                    remoteRepositories.containsKey(event.getRepository().getId())) {
-                EditableRepository repo = (EditableRepository) event.getRepository();
-                if (repo != null && repo.getIndexingContext()!=null) {
+    public void raise(Event event) {
+        // To avoid event cycles:
+        if (sameOriginator(event)) {
+            return;
+        }
+        if (event instanceof IndexCreationEvent) {
+            IndexCreationEvent idxEvent = (IndexCreationEvent) event;
+            if (managedRepositories.containsKey(idxEvent.getRepository().getId()) ||
+                    remoteRepositories.containsKey(idxEvent.getRepository().getId())) {
+                EditableRepository repo = (EditableRepository) idxEvent.getRepository();
+                if (repo != null && repo.getIndexingContext() != null) {
                     try {
                         ArchivaIndexManager idxmgr = getIndexManager(repo.getType());
                         if (idxmgr != null) {
@@ -1372,9 +1268,36 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 }
             }
         }
-        for(RepositoryEventListener listener : listeners) {
-            listener.raise(event);
+        // We propagate all events to our listeners
+        pushEvent(event.recreate(this));
+    }
+
+    private boolean sameOriginator(Event event) {
+        if (event.getOriginator()==this) {
+            return true;
+        } else if (event.hasPreviousEvent()) {
+            return sameOriginator(event.getPreviousEvent());
+        } else {
+            return false;
+        }
+    }
+
+    private void pushEvent(Event<RepositoryRegistry> event) {
+        callListeners(event, listeners);
+        if (typeListenerMap.containsKey(event.getType())) {
+            callListeners(event, typeListenerMap.get(event.getType()));
         }
     }
 
+    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());
+            }
+        }
+    }
+
+
 }
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 3a5e476..0f75218 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
@@ -23,6 +23,8 @@ import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
 import org.apache.archiva.repository.*;
+import org.apache.archiva.repository.events.Event;
+import org.apache.archiva.repository.events.RepositoryValueEvent;
 import org.apache.archiva.repository.features.ArtifactCleanupFeature;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.RemoteIndexFeature;
@@ -259,7 +261,7 @@ public class RepositoryProviderMock implements RepositoryProvider
     }
 
     @Override
-    public <T> void raise(RepositoryEvent<T> event) {
+    public void raise(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 cc99d15..0a8c573 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
@@ -32,7 +32,8 @@ import org.apache.archiva.repository.PasswordCredentials;
 import org.apache.archiva.repository.ReleaseScheme;
 import org.apache.archiva.repository.RemoteRepository;
 import org.apache.archiva.repository.RepositoryCredentials;
-import org.apache.archiva.repository.RepositoryEvent;
+import org.apache.archiva.repository.events.Event;
+import org.apache.archiva.repository.events.RepositoryValueEvent;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryGroup;
 import org.apache.archiva.repository.RepositoryProvider;
@@ -280,7 +281,7 @@ public class RepositoryProviderMock implements RepositoryProvider
     }
 
     @Override
-    public <T> void raise(RepositoryEvent<T> event) {
+    public void raise(Event event) {
 
     }
 }


[archiva] 02/02: Fixing proxy connector handling

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 1c379926f04a60c68c291067094732b9b07d0c5a
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Thu Sep 12 13:10:22 2019 +0200

    Fixing proxy connector handling
---
 .../apache/archiva/proxy/ArchivaProxyRegistry.java | 34 +++++++++++++++-------
 .../managed/ManagedRepositoryAdminTest.java        |  1 -
 .../archiva/proxy/HttpProxyTransferTest.java       |  2 ++
 .../maven2/ArchivaRepositoryConnectorFactory.java  |  2 ++
 .../repository/maven2/MavenRepositoryProvider.java |  8 +++--
 .../maven2/DependencyTreeBuilderTestMaven3.java    |  2 ++
 6 files changed, 36 insertions(+), 13 deletions(-)

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 17b1f4e..b59091a 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
@@ -27,6 +27,9 @@ 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.events.RepositoryEventListener;
+import org.apache.archiva.repository.events.RepositoryRegistryEvent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
@@ -44,7 +47,7 @@ import java.util.stream.Collectors;
  */
 @SuppressWarnings( "SpringJavaInjectionPointsAutowiringInspection" )
 @Service("proxyRegistry#default")
-public class ArchivaProxyRegistry implements ProxyRegistry, ConfigurationListener {
+public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListener {
 
     private static final Logger log = LoggerFactory.getLogger(ArchivaProxyRegistry.class);
 
@@ -74,10 +77,10 @@ public class ArchivaProxyRegistry implements ProxyRegistry, ConfigurationListene
         if (repositoryProxyHandlers == null) {
             repositoryProxyHandlers = new ArrayList<>();
         }
-        archivaConfiguration.addListener( this );
         updateHandler();
         updateConnectors();
         updateNetworkProxies();
+        repositoryRegistry.register(this, RepositoryRegistryEvent.RegistryEventType.RELOADED);
     }
 
     private ArchivaConfiguration getArchivaConfiguration() {
@@ -125,7 +128,9 @@ public class ArchivaProxyRegistry implements ProxyRegistry, ConfigurationListene
             getArchivaConfiguration().getConfiguration().getProxyConnectors();
 
         connectorList = proxyConnectorConfigurations.stream()
-                .map(configuration -> buildProxyConnector(configuration))
+                .map(this::buildProxyConnector)
+                .filter(Optional::isPresent)
+                .map(Optional::get)
                 .sorted(comparator).collect(Collectors.toList());
         connectorMap = connectorList.stream().collect(Collectors.groupingBy(a -> a.getSourceRepository().getId()));
         for (RepositoryProxyHandler handler : repositoryProxyHandlers) {
@@ -139,7 +144,7 @@ public class ArchivaProxyRegistry implements ProxyRegistry, ConfigurationListene
         return policies.stream().collect( Collectors.toMap( Function.identity(), p -> PolicyUtil.findOption( policyConfig.get(p.getId()), p ) ) );
     }
 
-    private ProxyConnector buildProxyConnector(ProxyConnectorConfiguration configuration) {
+    private Optional<ProxyConnector> buildProxyConnector(ProxyConnectorConfiguration configuration) {
         ProxyConnector proxyConnector = new ProxyConnector();
         proxyConnector.setOrder(configuration.getOrder());
         proxyConnector.setBlacklist(configuration.getBlackListPatterns());
@@ -153,10 +158,16 @@ public class ArchivaProxyRegistry implements ProxyRegistry, ConfigurationListene
         proxyConnector.setProperties(configuration.getProperties());
         proxyConnector.setProxyId(configuration.getProxyId());
         ManagedRepository srcRepo = repositoryRegistry.getManagedRepository(configuration.getSourceRepoId());
+        if (srcRepo==null) {
+            return Optional.empty();
+        }
         proxyConnector.setSourceRepository(srcRepo);
         RemoteRepository targetRepo = repositoryRegistry.getRemoteRepository(configuration.getTargetRepoId());
+        if (targetRepo==null) {
+            return Optional.empty();
+        }
         proxyConnector.setTargetRepository(targetRepo);
-        return proxyConnector;
+        return Optional.of(proxyConnector);
     }
 
     @Override
@@ -183,11 +194,6 @@ public class ArchivaProxyRegistry implements ProxyRegistry, ConfigurationListene
         return this.handlerMap.containsKey(type);
     }
 
-    @Override
-    public void configurationEvent(ConfigurationEvent event) {
-        log.debug("Config changed updating proxy list");
-        init( );
-    }
 
     @Override
     public List<ProxyConnector> getProxyConnectors() {
@@ -205,4 +211,12 @@ public class ArchivaProxyRegistry implements ProxyRegistry, ConfigurationListene
     {
         init();
     }
+
+    @Override
+    public void raise(Event event) {
+        log.debug("Reload happened, updating proxy list");
+        if (event.getType()== RepositoryRegistryEvent.RegistryEventType.RELOADED) {
+            init();
+        }
+    }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/managed/ManagedRepositoryAdminTest.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/managed/ManagedRepositoryAdminTest.java
index 05b40c3..2e542d5 100644
--- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/managed/ManagedRepositoryAdminTest.java
+++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/managed/ManagedRepositoryAdminTest.java
@@ -316,7 +316,6 @@ public class ManagedRepositoryAdminTest
         managedRepositoryAdmin.updateManagedRepository( repo, true, getFakeAuditInformation(), false );
 
         repo = managedRepositoryAdmin.getManagedRepository( repoId );
-        System.err.println("REPOSITORY "+repo.getLocation());
         assertNotNull( repo );
         assertEquals( newName, repo.getName() );
         assertEquals( Paths.get( repoLocation ).toAbsolutePath(), Paths.get( repo.getLocation() ).toAbsolutePath() );
diff --git a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/HttpProxyTransferTest.java b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/HttpProxyTransferTest.java
index b35967f..dd74487 100644
--- a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/HttpProxyTransferTest.java
+++ b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/HttpProxyTransferTest.java
@@ -219,6 +219,8 @@ public class HttpProxyTransferTest
         // Configure Connector (usually done within archiva.xml configuration)
         addConnector();
 
+        managedDefaultRepository = repositoryRegistry.getManagedRepository(MANAGED_ID).getContent();
+
         Path expectedFile = Paths.get( managedDefaultRepository.getRepoRoot() ).resolve( path );
         Files.deleteIfExists( expectedFile );
         ArtifactReference artifact = managedDefaultRepository.toArtifactReference( path );
diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/dependency/tree/maven2/ArchivaRepositoryConnectorFactory.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/dependency/tree/maven2/ArchivaRepositoryConnectorFactory.java
index dd401ae..f099292 100644
--- a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/dependency/tree/maven2/ArchivaRepositoryConnectorFactory.java
+++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/dependency/tree/maven2/ArchivaRepositoryConnectorFactory.java
@@ -19,6 +19,7 @@ package org.apache.archiva.dependency.tree.maven2;
  */
 
 import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
+import org.eclipse.aether.internal.impl.DefaultRepositoryLayoutProvider;
 import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,6 +50,7 @@ public class ArchivaRepositoryConnectorFactory
     public ArchivaRepositoryConnectorFactory()
     {
         // no op but empty constructor needed by aether
+        delegate.setRepositoryLayoutProvider(new DefaultRepositoryLayoutProvider());
     }
 
     @Override
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 cdc03db..15dbf6a 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
@@ -22,6 +22,8 @@ package org.apache.archiva.repository.maven2;
 import org.apache.archiva.common.filelock.FileLockManager;
 import org.apache.archiva.configuration.*;
 import org.apache.archiva.repository.*;
+import org.apache.archiva.repository.events.Event;
+import org.apache.archiva.repository.events.RepositoryValueEvent;
 import org.apache.archiva.repository.storage.FilesystemStorage;
 import org.apache.archiva.repository.features.ArtifactCleanupFeature;
 import org.apache.archiva.repository.features.IndexCreationFeature;
@@ -347,7 +349,9 @@ public class MavenRepositoryProvider implements RepositoryProvider {
         cfg.setPackedIndexDir(convertUriToPath(indexCreationFeature.getPackedIndexPath()));
 
         RemoteIndexFeature remoteIndexFeature = remoteRepository.getFeature(RemoteIndexFeature.class).get();
-        cfg.setRemoteIndexUrl(remoteIndexFeature.getIndexUri().toString());
+        if (remoteIndexFeature.getIndexUri()!=null) {
+            cfg.setRemoteIndexUrl(remoteIndexFeature.getIndexUri().toString());
+        }
         cfg.setRemoteDownloadTimeout((int) remoteIndexFeature.getDownloadTimeout().get(ChronoUnit.SECONDS));
         cfg.setDownloadRemoteIndexOnStartup(remoteIndexFeature.isDownloadRemoteIndexOnStartup());
         cfg.setDownloadRemoteIndex(remoteIndexFeature.isDownloadRemoteIndex());
@@ -495,7 +499,7 @@ public class MavenRepositoryProvider implements RepositoryProvider {
     }
 
     @Override
-    public <T> void raise(RepositoryEvent<T> event) {
+    public void raise(Event event) {
         //
     }
 
diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/dependency/tree/maven2/DependencyTreeBuilderTestMaven3.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/dependency/tree/maven2/DependencyTreeBuilderTestMaven3.java
index fb0b802..df2f104 100644
--- a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/dependency/tree/maven2/DependencyTreeBuilderTestMaven3.java
+++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/dependency/tree/maven2/DependencyTreeBuilderTestMaven3.java
@@ -81,6 +81,8 @@ public class DependencyTreeBuilderTestMaven3
         repoConfig.setId( TEST_REPO_ID );
         repoConfig.setLocation(Paths.get("target/test-repository").toAbsolutePath().toString() );
         configuration.addManagedRepository( repoConfig );
+
+        config.getConfiguration().getProxyConnectors().clear();
         config.save( configuration );
 
         repositoryRegistry.reload();