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/21 22:12:01 UTC

[archiva] 04/08: Modifying repository registry behaviour

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

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

commit df8da96f9869522b6fc1b9270927942550555b99
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Sat Sep 14 15:15:31 2019 +0200

    Modifying repository registry behaviour
---
 .../archiva/admin/mock/MavenIndexContextMock.java  |   8 +
 .../networkproxy/NetworkProxyAdminTest.java        |   3 +-
 .../archiva/indexer/ArchivaIndexingContext.java    |   8 +
 .../org/apache/archiva/repository/Repository.java  |   7 +
 .../apache/archiva/repository/events/Event.java    |   2 +-
 .../{features => events}/IndexCreationEvent.java   |   4 +-
 .../archiva/repository/events/LifecycleEvent.java  |   2 +-
 .../archiva/repository/events/RepositoryEvent.java |   2 +-
 .../repository/events/RepositoryRegistryEvent.java |   4 +-
 .../repository/features/IndexCreationFeature.java  |  47 +++-
 .../repository/features/RepositoryFeature.java     |  38 ++-
 .../archiva/repository/AbstractRepository.java     |  44 ++--
 .../archiva/repository/RepositoryRegistry.java     | 254 +++++++++++----------
 .../test/utils/ArchivaSpringJUnit4ClassRunner.java |  15 ++
 .../archiva/indexer/maven/MavenIndexContext.java   |  29 ++-
 .../search/AbstractMavenRepositorySearch.java      |  39 +++-
 .../search/MavenRepositorySearchOSGITest.java      |   2 +-
 .../maven/search/MavenRepositorySearchTest.java    |  28 +--
 .../repository/maven2/MavenManagedRepository.java  |   7 +
 .../repository/maven2/MavenRepositoryProvider.java |  16 +-
 ...aven2RepositoryMetadataResolverMRM1411Test.java |   2 +
 .../index/mock/MavenIndexContextMock.java          |   8 +
 .../apache/archiva/mock/MavenIndexContextMock.java |   9 +
 archiva-modules/archiva-web/archiva-webdav/pom.xml |   1 +
 .../webdav/AbstractRepositoryServletTestCase.java  |   8 +-
 25 files changed, 396 insertions(+), 191 deletions(-)

diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java
index 4b4528b..843df59 100644
--- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java
+++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java
@@ -40,6 +40,7 @@ import java.util.Set;
  */
 public class MavenIndexContextMock implements ArchivaIndexingContext {
 
+    private boolean open = true;
     private IndexingContext delegate;
     private Repository repository;
     private FilesystemStorage filesystemStorage;
@@ -93,6 +94,7 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
 
     @Override
     public void close(boolean deleteFiles) throws IOException {
+        open = false;
         try {
             delegate.close(deleteFiles);
         } catch (NoSuchFileException e) {
@@ -102,6 +104,7 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
 
     @Override
     public void close() throws IOException {
+        open = false;
         try {
             delegate.close(false);
         } catch (NoSuchFileException e) {
@@ -110,6 +113,11 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
     }
 
     @Override
+    public boolean isOpen() {
+        return open;
+    }
+
+    @Override
     public void purge() throws IOException {
         delegate.purge();
     }
diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/networkproxy/NetworkProxyAdminTest.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/networkproxy/NetworkProxyAdminTest.java
index 21020d1..cf8f91b 100644
--- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/networkproxy/NetworkProxyAdminTest.java
+++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/networkproxy/NetworkProxyAdminTest.java
@@ -23,6 +23,7 @@ import org.apache.archiva.admin.model.beans.RemoteRepository;
 import org.apache.archiva.admin.model.networkproxy.NetworkProxyAdmin;
 import org.apache.archiva.admin.repository.AbstractRepositoryAdminTest;
 import org.apache.archiva.metadata.model.facets.AuditEvent;
+import org.apache.commons.lang.StringUtils;
 import org.junit.Test;
 
 import javax.inject.Inject;
@@ -157,7 +158,7 @@ public class NetworkProxyAdminTest
 
         remoteRepository = remoteRepositoryAdmin.getRemoteRepository( getRemoteRepository().getId() );
 
-        assertNull( remoteRepository.getRemoteDownloadNetworkProxyId() );
+        assertTrue(StringUtils.isEmpty(remoteRepository.getRemoteDownloadNetworkProxyId()) );
 
         remoteRepositoryAdmin.deleteRemoteRepository( getRemoteRepository().getId(), getFakeAuditInformation() );
     }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexingContext.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexingContext.java
index 2dee441..902d21c 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexingContext.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexingContext.java
@@ -90,6 +90,14 @@ public interface ArchivaIndexingContext {
     void close() throws IOException;
 
     /**
+     * Returns the status of this context. This method will return <code>false</code>, after the {@link #close()} method
+     * has been called.
+     *
+     * @return <code>true</code>, if the <code>close()</code> method has not been called, otherwise <code>false</code>
+     */
+    boolean isOpen();
+
+    /**
      * Removes all entries from the index. After this method finished,
      * isEmpty() should return true.
      * @throws IOException
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 9b26143..b26627f 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
@@ -175,5 +175,12 @@ public interface Repository extends RepositoryEventHandler, RepositoryStorage {
      */
     void close();
 
+    /**
+     * Returns the current status of this repository.
+     *
+     * @return <code>true</code>, if repository has not been closed, otherwise <code>false</code>
+     */
+    boolean isOpen();
+
 
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
index afac04c..7ba7f34 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java
@@ -28,7 +28,7 @@ public class Event<O> {
     final EventType type;
     final LocalDateTime instant;
 
-    public Event(EventType type, O originator) {
+    public <OO extends O> Event(EventType type, OO originator) {
         this.originator = originator;
         this.type = type;
         this.instant = LocalDateTime.now();
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/events/IndexCreationEvent.java
similarity index 91%
rename from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationEvent.java
rename to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/IndexCreationEvent.java
index 037ba47..847b679 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/events/IndexCreationEvent.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.repository.features;
+package org.apache.archiva.repository.events;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -20,8 +20,6 @@ package org.apache.archiva.repository.features;
  */
 
 import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.events.EventType;
-import org.apache.archiva.repository.events.RepositoryValueEvent;
 
 import java.net.URI;
 
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
index 5f69d1e..2c55dd8 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java
@@ -27,7 +27,7 @@ public class LifecycleEvent<O> extends RepositoryEvent<O> {
         REGISTERED,UNREGISTERED,UPDATED
     }
 
-    public LifecycleEvent(LifecycleEventType type, O origin, Repository repository) {
+    public <OO extends O> LifecycleEvent(LifecycleEventType type, OO origin, Repository repository) {
         super(type, origin, repository);
     }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
index dd5550b..7c97b87 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java
@@ -25,7 +25,7 @@ public class RepositoryEvent<O> extends Event<O> {
 
     private final Repository repository;
 
-    public RepositoryEvent(EventType type, O origin, Repository repository) {
+    public <OO extends O> RepositoryEvent(EventType type, OO origin, Repository repository) {
         super(type, origin);
         this.repository = repository;
     }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
index d9b891c..1a138cf 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java
@@ -19,13 +19,13 @@ package org.apache.archiva.repository.events;
  * under the License.
  */
 
-public class RepositoryRegistryEvent<O> extends Event {
+public class RepositoryRegistryEvent<O> extends Event<O> {
 
     public enum RegistryEventType implements EventType {
         RELOADED,DESTROYED
     }
 
-    public RepositoryRegistryEvent(RegistryEventType type, O origin) {
+    public <OO extends O> RepositoryRegistryEvent(RegistryEventType type, OO origin) {
         super(type, origin);
     }
 }
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 cf7432c..f834be1 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,6 +21,7 @@ package org.apache.archiva.repository.features;
 
 
 import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.events.IndexCreationEvent;
 import org.apache.archiva.repository.events.RepositoryEventListener;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.commons.lang3.StringUtils;
@@ -33,7 +34,17 @@ import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_PACKED_INDE
 
 /**
  *
- * This feature provides some information about index creation.
+ * This feature provides information about index creation.
+ *
+ * Repositories that support this feature are able to create indexes and download them from remote repositories.
+ *
+ * Repositories may have a normal and packed index. A normal index is used by repository search utilities, the packed
+ * index is for downloading purpose.
+ *
+ * A index may have a remote and a local representation. The remote representation is used for downloading and
+ * updating the local representation.
+ *
+ * The feature is throwing a {@link IndexCreationEvent}, if the URI of the index has been changed.
  *
  */
 public class IndexCreationFeature extends AbstractFeature implements RepositoryFeature<IndexCreationFeature>{
@@ -51,9 +62,9 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
 
     private Repository repo;
 
-    public IndexCreationFeature(Repository repoId, RepositoryEventListener listener) {
+    public IndexCreationFeature(Repository repository, RepositoryEventListener listener) {
         super(listener);
-        this.repo = repoId;
+        this.repo = repository;
         try {
             this.indexPath = new URI(DEFAULT_INDEX_PATH);
             this.packedIndexPath = new URI(DEFAULT_PACKED_INDEX_PATH);
@@ -97,7 +108,9 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
     }
 
     /**
-     * Returns the path that is used to store the index.
+     * Returns the path that is used to store the index. The path may be a absolute URI or relative to the
+     * base URI of the repository.
+     *
      * @return the uri (may be relative or absolute)
      */
     public URI getIndexPath( )
@@ -106,18 +119,26 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
     }
 
     /**
-     * Sets the path that is used to store the index.
+     * Sets the path that is used to store the index. The path may be either absolute or a
+     * path that is relative to the repository storage path (either a local or remote path).
+     *
      * @param indexPath the uri to the index path (may be relative)
      */
     public void setIndexPath( URI indexPath )
     {
-        URI oldVal = this.indexPath;
-        this.indexPath = indexPath;
-        pushEvent(IndexCreationEvent.indexUriChange(this, repo, oldVal, this.indexPath));
+        if ((this.indexPath==null && indexPath!=null) || !this.indexPath.equals(indexPath)) {
+            URI oldVal = this.indexPath;
+            this.indexPath = indexPath;
+            pushEvent(IndexCreationEvent.indexUriChange(this, repo, oldVal, this.indexPath));
+        }
 
     }
 
-
+    /**
+     * Returns true, if this repository has a index defined.
+     *
+     * @return <code>true</code>, if a index path is set, otherwise <code>false</code>
+     */
     public boolean hasIndex() {
         return this.indexPath!=null && !StringUtils.isEmpty( this.indexPath.getPath() );
     }
@@ -132,8 +153,7 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
     }
 
     /**
-     * Sets the path where the index is stored physically. This method should only be used by the
-     * MavenIndexProvider implementations.
+     * Sets the path where the index is stored locally.
      *
      * @param localIndexPath
      */
@@ -152,7 +172,10 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF
 
     /**
      * Sets the path (relative or absolute) of the packed index.
-     * @param packedIndexPath
+     *
+     * Throws a {@link IndexCreationEvent.Index#PACKED_INDEX_URI_CHANGE}, if the value changes.
+     *
+     * @param packedIndexPath the new path uri for the packed index
      */
     public void setPackedIndexPath(URI packedIndexPath) {
         URI oldVal = this.packedIndexPath;
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/RepositoryFeature.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/RepositoryFeature.java
index a4df8a2..813d39d 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/RepositoryFeature.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/RepositoryFeature.java
@@ -21,21 +21,57 @@ package org.apache.archiva.repository.features;
 
 
 /**
- * Created by martin on 30.09.17.
+ *
+ * The repository feature holds information about specific features. The may not be available by all repository implementations.
+ * Features should be simple objects for storing additional data, the should not implement too much functionality.
+ * Additional functionality the uses the information in the feature objects should be implemented in the specific repository
+ * provider and repository implementations, or in the repository registry if it is generic.
+ *
+ * But features may throw events, if it's data is changed.
+ *
+ *
+ * This interface is to get access to a concrete feature by accessing the generic interface.
+ *
+ * @param <T> the concrete feature implementation.
+ *
+ * @author Martin Stockhammer <ma...@apache.org>
+ * @since 3.0
  */
 public interface RepositoryFeature<T extends RepositoryFeature<T>> {
 
+    /**
+     * Unique Identifier of this feature. Each feature implementation has its own unique identifier.
+     *
+     * @return the identifier string which should be unique for the implementation class.
+     */
     default String getId() {
         return this.getClass().getName();
     }
 
+    /**
+     * Tells, if this instance is a feature of the given identifier.
+     *
+     * @param featureId the feature identifier string to check
+     * @return true, if this instance is a instance with the feature id, otherwise <code>false</code>
+     */
     default boolean isFeature(String featureId) {
         return this.getClass().getName().equals(featureId);
     }
 
+    /**
+     * Tells, if the this instance is a feature of the given feature class.
+     *
+     * @param clazz The class to check against.
+     * @param <K> the concrete feature implementation.
+     * @return
+     */
     default <K extends RepositoryFeature<K>> boolean isFeature(Class<K> clazz) {
         return this.getClass().equals(clazz);
     }
 
+    /**
+     * Returns the concrete feature instance.
+     * @return the feature instance.
+     */
     T get();
 }
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 d8c9e3b..0f71880 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
@@ -48,6 +48,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
 
 /**
@@ -61,6 +62,9 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
 
     Logger log = LoggerFactory.getLogger(AbstractRepository.class);
 
+    private final AtomicBoolean openStatus = new AtomicBoolean(false);
+
+
     private final RepositoryType type;
     private final String id;
     private Map<Locale, String> names = new HashMap<>(  );
@@ -90,6 +94,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
         this.type = type;
         this.storage = repositoryStorage;
         this.location = repositoryStorage.getLocation();
+        this.openStatus.compareAndSet(false, true);
     }
 
     public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) {
@@ -99,6 +104,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
         this.type = type;
         this.storage = repositoryStorage;
         this.location = repositoryStorage.getLocation();
+        this.openStatus.compareAndSet(false, true);
     }
 
     protected void setPrimaryLocale(Locale locale) {
@@ -288,6 +294,9 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
 
     @Override
     public void setIndexingContext(ArchivaIndexingContext context) {
+        if (this.indexingContext!=null) {
+
+        }
         this.indexingContext = context;
     }
 
@@ -298,21 +307,30 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
 
     @Override
     public void close() {
-        ArchivaIndexingContext ctx = getIndexingContext();
-        if (ctx!=null) {
-            try {
-                ctx.close();
-            } catch (IOException e) {
-                log.warn("Error during index context close.",e);
+        if (this.openStatus.compareAndSet(true, false)) {
+            ArchivaIndexingContext ctx = getIndexingContext();
+            if (ctx != null) {
+                try {
+                    ctx.close();
+                } catch (IOException e) {
+                    log.warn("Error during index context close.", e);
+                }
+                this.indexingContext = null;
+
             }
-        }
-        if (supportsFeature(StagingRepositoryFeature.class)) {
-            StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get();
-            if (sf.getStagingRepository()!=null) {
-                sf.getStagingRepository().close();
+            if (supportsFeature(StagingRepositoryFeature.class)) {
+                StagingRepositoryFeature sf = getFeature(StagingRepositoryFeature.class).get();
+                if (sf.getStagingRepository() != null) {
+                    sf.getStagingRepository().close();
+                }
             }
+            clearListeners();
         }
-        clearListeners();
+    }
+
+    @Override
+    public boolean isOpen() {
+        return openStatus.get();
     }
 
     @Override
@@ -326,7 +344,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito
     private void callListeners(Event event, List<RepositoryEventListener> evtListeners) {
         for(RepositoryEventListener listener : evtListeners) {
             try {
-                listener.raise(event);
+                listener.raise(event.recreate(this));
             } 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/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 a58f960..28ffc5a 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
@@ -23,7 +23,6 @@ import org.apache.archiva.configuration.*;
 import org.apache.archiva.indexer.*;
 import org.apache.archiva.redback.components.registry.RegistryException;
 import org.apache.archiva.repository.events.*;
-import org.apache.archiva.repository.features.IndexCreationEvent;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.StagingRepositoryFeature;
 import org.apache.commons.lang3.StringUtils;
@@ -50,6 +49,8 @@ import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
  * configuration save fails the changes are rolled back.
  * <p>
  * TODO: Audit events
+ *
+ * @since 3.0
  */
 @Service("repositoryRegistry")
 public class RepositoryRegistry implements ConfigurationListener, RepositoryEventHandler, RepositoryEventListener {
@@ -98,15 +99,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         rwLock.writeLock().lock();
         try {
             log.debug("Initializing repository registry");
-            for (ManagedRepository rep : managedRepositories.values()) {
-                rep.close();
-            }
-            managedRepositories.clear();
             updateManagedRepositoriesFromConfig();
-            for (RemoteRepository repo : remoteRepositories.values()) {
-                repo.close();
-            }
-            remoteRepositories.clear();
             updateRemoteRepositoriesFromConfig();
 
             repositoryGroups.clear();
@@ -118,7 +111,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         } finally {
             rwLock.writeLock().unlock();
         }
-        pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.RegistryEventType.RELOADED, this));
+        pushEvent(new RepositoryRegistryEvent<>(RepositoryRegistryEvent.RegistryEventType.RELOADED, this));
     }
 
     @PreDestroy
@@ -131,7 +124,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             repo.close();
         }
         remoteRepositories.clear();
-        pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.RegistryEventType.DESTROYED, this));
+        pushEvent(new RepositoryRegistryEvent<>(RepositoryRegistryEvent.RegistryEventType.DESTROYED, this));
     }
 
 
@@ -151,8 +144,13 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         return repositoryProviders.stream().filter(repositoryProvider -> repositoryProvider.provides().contains(type)).findFirst().orElseThrow(() -> new RepositoryException("Repository type cannot be handled: " + type));
     }
 
+    /*
+     * Updates the repositories
+     */
     private void updateManagedRepositoriesFromConfig() {
         try {
+
+            Set<String> configRepoIds = new HashSet<>();
             List<ManagedRepositoryConfiguration> managedRepoConfigs =
                     getArchivaConfiguration().getConfiguration().getManagedRepositories();
 
@@ -160,27 +158,23 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 return;
             }
 
-            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);
-                        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);
+                ManagedRepository repo = putRepository(repoConfig, null);
+                configRepoIds.add(repoConfig.getId());
+                if (repo.supportsFeature(StagingRepositoryFeature.class)) {
+                    StagingRepositoryFeature stagF = repo.getFeature(StagingRepositoryFeature.class).get();
+                    if (stagF.getStagingRepository() != null) {
+                        configRepoIds.add(stagF.getStagingRepository().getId());
                     }
                 }
             }
-            return;
+            List<String> toRemove = managedRepositories.keySet().stream().filter(id -> !configRepoIds.contains(id)).collect(Collectors.toList());
+            for (String id : toRemove) {
+                ManagedRepository removed = managedRepositories.remove(id);
+                removed.close();
+            }
         } catch (Throwable e) {
             log.error("Could not initialize repositories from config: {}", e.getMessage(), e);
-            //noinspection unchecked
             return;
         }
     }
@@ -205,15 +199,15 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             StagingRepositoryFeature feature = repo.getFeature(StagingRepositoryFeature.class).get();
             if (feature.isStageRepoNeeded() && feature.getStagingRepository() == null) {
                 ManagedRepository stageRepo = getManagedRepository(getStagingId(repo.getId()));
-                if (stageRepo==null) {
+                if (stageRepo == null) {
                     stageRepo = getStagingRepository(provider, cfg, configuration);
                     managedRepositories.put(stageRepo.getId(), stageRepo);
                     if (configuration != null) {
                         replaceOrAddRepositoryConfig(provider.getManagedConfiguration(stageRepo), configuration);
                     }
+                    pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, stageRepo));
                 }
                 feature.setStagingRepository(stageRepo);
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, stageRepo));
             }
         }
         if (repo instanceof EditableManagedRepository) {
@@ -223,12 +217,12 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 editableRepo.getContent().setRepository(editableRepo);
             }
             log.debug("Index repo: " + repo.hasIndex());
-            if (repo.hasIndex() && repo.getIndexingContext() == null) {
+            if (repo.hasIndex() && ( repo.getIndexingContext() == null || !repo.getIndexingContext().isOpen() )) {
                 log.debug("Creating indexing context for {}", repo.getId());
                 createIndexingContext(editableRepo);
             }
         }
-
+        repo.register(this);
     }
 
     public ArchivaIndexManager getIndexManager(RepositoryType type) {
@@ -267,30 +261,22 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                     getArchivaConfiguration().getConfiguration().getRemoteRepositories();
 
             if (remoteRepoConfigs == null) {
-                //noinspection unchecked
                 return;
             }
-
-            Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap();
+            Set<String> repoIds = new HashSet<>();
             for (RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs) {
-                RepositoryType repositoryType = RepositoryType.valueOf(repoConfig.getType());
-                if (providerMap.containsKey(repositoryType)) {
-                    RepositoryProvider provider = getProvider(repositoryType);
-                    try {
+                putRepository(repoConfig, null);
+                repoIds.add(repoConfig.getId());
+            }
 
-                        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);
-                    }
-                }
+            List<String> toRemove = remoteRepositories.keySet().stream().filter(id -> !repoIds.contains(id)).collect(Collectors.toList());
+            for (String id : toRemove) {
+                RemoteRepository removed = remoteRepositories.remove(id);
+                removed.close();
             }
 
-            return;
         } catch (Throwable e) {
             log.error("Could not initialize remote repositories from config: {}", e.getMessage(), e);
-            //noinspection unchecked
             return;
         }
     }
@@ -298,13 +284,11 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     private RemoteRepository createNewRemoteRepository(RepositoryProvider provider, RemoteRepositoryConfiguration cfg) throws RepositoryException {
         log.debug("Creating remote repo {}", cfg.getId());
         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) {
             EditableRemoteRepository editableRepo = (EditableRemoteRepository) repo;
@@ -313,6 +297,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 createIndexingContext(editableRepo);
             }
         }
+        repo.register(this);
     }
 
     private Map<String, RepositoryGroup> getRepositorGroupsFromConfig() {
@@ -341,12 +326,11 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             return repositoryGroupMap;
         } catch (Throwable e) {
             log.error("Could not initialize repositories from config: {}", e.getMessage(), e);
-            //noinspection unchecked
             return Collections.emptyMap();
         }
     }
 
-    RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException {
+    private RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException {
         RepositoryGroup repositoryGroup = provider.createRepositoryGroup(config);
         repositoryGroup.register(this);
         updateRepositoryReferences(provider, repositoryGroup, config);
@@ -511,10 +495,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             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) {
+                if (originRepo != null && originRepo != managedRepository) {
                     originRepo.close();
                 }
                 RepositoryProvider provider = getProvider(managedRepository.getType());
@@ -527,10 +510,14 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 }
                 configuration.addManagedRepository(newCfg);
                 saveConfiguration(configuration);
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, managedRepository));
+                if (originRepo != managedRepository) {
+                    pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.REGISTERED, this, managedRepository));
+                } else {
+                    pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UPDATED, this, managedRepository));
+                }
                 return managedRepository;
             } catch (Exception e) {
-                // Rollback
+                // Rollback only partly, because repository is closed already
                 if (originRepo != null) {
                     managedRepositories.put(id, originRepo);
                 } else {
@@ -581,20 +568,20 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
      * the configuration is not saved.
      *
-     * @param managedRepositoryConfiguration the new or changed repository configuration
-     * @param configuration                  the configuration object
+     * @param managedRepositoryConfiguration the new or changed managed repository configuration
+     * @param configuration                  the configuration object (may be <code>null</code>)
      * @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 {
             final String id = managedRepositoryConfiguration.getId();
             final RepositoryType repoType = RepositoryType.valueOf(managedRepositoryConfiguration.getType());
             ManagedRepository repo;
-            if (managedRepositories.containsKey(id)) {
-                repo = managedRepositories.get(id);
+            boolean registeredNew = false;
+            repo = managedRepositories.get(id);
+            if (repo != null && repo.isOpen()) {
                 if (repo instanceof EditableManagedRepository) {
                     getProvider(repoType).updateManagedInstance((EditableManagedRepository) repo, managedRepositoryConfiguration);
                 } else {
@@ -602,12 +589,16 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 }
             } else {
                 repo = getProvider(repoType).createManagedInstance(managedRepositoryConfiguration);
-                repo.register(this);
                 managedRepositories.put(id, repo);
+                registeredNew = true;
             }
             updateRepositoryReferences(getProvider(repoType), repo, managedRepositoryConfiguration, configuration);
             replaceOrAddRepositoryConfig(managedRepositoryConfiguration, configuration);
-            pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
+            if (registeredNew) {
+                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
+            } else {
+                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UPDATED, this, repo));
+            }
             return repo;
         } finally {
             rwLock.writeLock().unlock();
@@ -627,10 +618,10 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         rwLock.writeLock().lock();
         try {
             final String id = repositoryGroup.getId();
-            RepositoryGroup originRepo = repositoryGroups.put(id, repositoryGroup);
+            RepositoryGroup originRepoGroup = repositoryGroups.put(id, repositoryGroup);
             try {
-                if (originRepo != null) {
-                    originRepo.close();
+                if (originRepoGroup != null && originRepoGroup != repositoryGroup) {
+                    originRepoGroup.close();
                 }
                 RepositoryProvider provider = getProvider(repositoryGroup.getType());
                 RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration(repositoryGroup);
@@ -645,8 +636,8 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 return repositoryGroup;
             } catch (Exception e) {
                 // Rollback
-                if (originRepo != null) {
-                    repositoryGroups.put(id, originRepo);
+                if (originRepoGroup != null) {
+                    repositoryGroups.put(id, originRepoGroup);
                 } else {
                     repositoryGroups.remove(id);
                 }
@@ -695,12 +686,11 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * Adds a new repository group or updates the repository group with the same id. The given configuration object is updated, but
      * the configuration is not saved.
      *
-     * @param repositoryGroupConfiguration the new or changed repository configuration
-     * @param configuration                the configuration object
-     * @return the new or updated repository
+     * @param repositoryGroupConfiguration The configuration of the new or changed repository group.
+     * @param configuration                The configuration object. If it is <code>null</code>, the configuration is not saved.
+     * @return The new or updated repository group
      * @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 {
@@ -717,7 +707,6 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 }
             } else {
                 repo = getProvider(repoType).createRepositoryGroup(repositoryGroupConfiguration);
-                repo.register(this);
                 repositoryGroups.put(id, repo);
             }
             updateRepositoryReferences(getProvider(repoType), repo, repositoryGroupConfiguration);
@@ -741,19 +730,23 @@ 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);
+        if (configuration != null) {
+            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);
+        if (configuration != null) {
+            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) {
@@ -775,7 +768,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             RemoteRepositoryConfiguration oldCfg = null;
             RemoteRepositoryConfiguration newCfg;
             try {
-                if (originRepo != null) {
+                if (originRepo != null && originRepo != remoteRepository) {
                     originRepo.close();
                 }
                 final RepositoryProvider provider = getProvider(remoteRepository.getType());
@@ -786,7 +779,11 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                     configuration.removeRemoteRepository(oldCfg);
                 }
                 configuration.addRemoteRepository(newCfg);
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, remoteRepository));
+                if (remoteRepository != originRepo) {
+                    pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.REGISTERED, this, remoteRepository));
+                } else {
+                    pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UPDATED, this, remoteRepository));
+                }
                 return remoteRepository;
             } catch (Exception e) {
                 // Rollback
@@ -883,8 +880,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             final String id = remoteRepositoryConfiguration.getId();
             final RepositoryType repoType = RepositoryType.valueOf(remoteRepositoryConfiguration.getType());
             RemoteRepository repo;
-            if (remoteRepositories.containsKey(id)) {
-                repo = remoteRepositories.get(id);
+            boolean registeredNew = false;
+            repo = remoteRepositories.get(id);
+            if (repo != null && repo.isOpen()) {
                 if (repo instanceof EditableRemoteRepository) {
                     getProvider(repoType).updateRemoteInstance((EditableRemoteRepository) repo, remoteRepositoryConfiguration);
                 } else {
@@ -892,12 +890,16 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 }
             } else {
                 repo = getProvider(repoType).createRemoteInstance(remoteRepositoryConfiguration);
-                repo.register(this);
                 remoteRepositories.put(id, repo);
+                registeredNew = true;
             }
             updateRepositoryReferences(getProvider(repoType), repo, remoteRepositoryConfiguration, configuration);
             replaceOrAddRepositoryConfig(remoteRepositoryConfiguration, configuration);
-            pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
+            if (registeredNew) {
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.REGISTERED, this, repo));
+            } else {
+                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UPDATED, this, repo));
+            }
             return repo;
         } finally {
             rwLock.writeLock().unlock();
@@ -913,7 +915,6 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         }
     }
 
-    @SuppressWarnings("unchecked")
     public void removeRepository(Repository repo) throws RepositoryException {
         if (repo == null) {
             log.warn("Trying to remove null repository");
@@ -938,6 +939,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @throws RepositoryException if a error occurs during configuration save
      */
     public void removeRepository(ManagedRepository managedRepository) throws RepositoryException {
+        if (managedRepository == null) {
+            return;
+        }
         final String id = managedRepository.getId();
         ManagedRepository repo = getManagedRepository(id);
         if (repo != null) {
@@ -954,7 +958,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                     }
                     saveConfiguration(configuration);
                 }
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+                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);
@@ -974,6 +978,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     }
 
     public void removeRepository(ManagedRepository managedRepository, Configuration configuration) throws RepositoryException {
+        if (managedRepository == null) {
+            return;
+        }
         final String id = managedRepository.getId();
         ManagedRepository repo = getManagedRepository(id);
         if (repo != null) {
@@ -988,7 +995,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                         configuration.removeManagedRepository(cfg);
                     }
                 }
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
             } finally {
                 rwLock.writeLock().unlock();
             }
@@ -1005,6 +1012,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @throws RepositoryException if a error occurs during configuration save
      */
     public void removeRepositoryGroup(RepositoryGroup repositoryGroup) throws RepositoryException {
+        if (repositoryGroup == null) {
+            return;
+        }
         final String id = repositoryGroup.getId();
         RepositoryGroup repo = getRepositoryGroup(id);
         if (repo != null) {
@@ -1033,6 +1043,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     }
 
     public void removeRepositoryGroup(RepositoryGroup repositoryGroup, Configuration configuration) throws RepositoryException {
+        if (repositoryGroup == null) {
+            return;
+        }
         final String id = repositoryGroup.getId();
         RepositoryGroup repo = getRepositoryGroup(id);
         if (repo != null) {
@@ -1075,7 +1088,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
      * @throws RepositoryException if a error occurs during configuration save
      */
     public void removeRepository(RemoteRepository remoteRepository) throws RepositoryException {
-
+        if (remoteRepository == null) {
+            return;
+        }
         final String id = remoteRepository.getId();
         RemoteRepository repo = getRemoteRepository(id);
         if (repo != null) {
@@ -1087,7 +1102,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                     doRemoveRepo(repo, configuration);
                     saveConfiguration(configuration);
                 }
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+                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);
@@ -1100,6 +1115,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     }
 
     public void removeRepository(RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException {
+        if (remoteRepository == null) {
+            return;
+        }
         final String id = remoteRepository.getId();
         RemoteRepository repo = getRemoteRepository(id);
         if (repo != null) {
@@ -1109,7 +1127,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
                 if (repo != null) {
                     doRemoveRepo(repo, configuration);
                 }
-                pushEvent(new LifecycleEvent(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
+                pushEvent(new LifecycleEvent<>(LifecycleEvent.LifecycleEventType.UNREGISTERED, this, repo));
             } finally {
                 rwLock.writeLock().unlock();
             }
@@ -1127,14 +1145,13 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
     /**
      * Resets the indexing context of a given repository.
      *
-     * @param repo
-     * @throws IndexUpdateFailedException
+     * @param repository The repository
+     * @throws IndexUpdateFailedException If the index could not be resetted.
      */
-    @SuppressWarnings("unchecked")
-    public void resetIndexingContext(Repository repo) throws IndexUpdateFailedException {
-        if (repo.hasIndex() && repo instanceof EditableRepository) {
-            EditableRepository eRepo = (EditableRepository) repo;
-            ArchivaIndexingContext newCtx = getIndexManager(repo.getType()).reset(repo.getIndexingContext());
+    public void resetIndexingContext(Repository repository) throws IndexUpdateFailedException {
+        if (repository.hasIndex() && repository instanceof EditableRepository) {
+            EditableRepository eRepo = (EditableRepository) repository;
+            ArchivaIndexingContext newCtx = getIndexManager(repository.getType()).reset(repository.getIndexingContext());
             eRepo.setIndexingContext(newCtx);
         }
     }
@@ -1159,7 +1176,6 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
         return cloned;
     }
 
-    @SuppressWarnings("unchecked")
     public <T extends Repository> Repository clone(T repo, String newId) throws RepositoryException {
         if (repo instanceof RemoteRepository) {
             return this.clone((RemoteRepository) repo, newId);
@@ -1249,31 +1265,35 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven
             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) {
-                            ArchivaIndexingContext newCtx = idxmgr.move(repo.getIndexingContext(), repo);
-                            repo.setIndexingContext(newCtx);
-                            idxmgr.updateLocalIndexPath(repo);
-                        }
-
-                    } catch (IndexCreationFailedException e) {
-                        log.error("Could not move index to new directory {}", e.getMessage(), e);
+            handleIndexCreationEvent((IndexCreationEvent) event);
+        }
+        // We propagate all events to our listeners, but with context of repository registry
+        pushEvent(event.recreate(this));
+    }
+
+    private void handleIndexCreationEvent(IndexCreationEvent event) {
+        IndexCreationEvent idxEvent = 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) {
+                        ArchivaIndexingContext newCtx = idxmgr.move(repo.getIndexingContext(), repo);
+                        repo.setIndexingContext(newCtx);
+                        idxmgr.updateLocalIndexPath(repo);
                     }
+
+                } catch (IndexCreationFailedException e) {
+                    log.error("Could not move index to new directory {}", e.getMessage(), e);
                 }
             }
         }
-        // We propagate all events to our listeners
-        pushEvent(event.recreate(this));
     }
 
     private boolean sameOriginator(Event event) {
-        if (event.getOriginator()==this) {
+        if (event.getOriginator() == this) {
             return true;
         } else if (event.hasPreviousEvent()) {
             return sameOriginator(event.getPreviousEvent());
diff --git a/archiva-modules/archiva-base/archiva-test-utils/src/main/java/org/apache/archiva/test/utils/ArchivaSpringJUnit4ClassRunner.java b/archiva-modules/archiva-base/archiva-test-utils/src/main/java/org/apache/archiva/test/utils/ArchivaSpringJUnit4ClassRunner.java
index 34a9db0..81a9158 100644
--- a/archiva-modules/archiva-base/archiva-test-utils/src/main/java/org/apache/archiva/test/utils/ArchivaSpringJUnit4ClassRunner.java
+++ b/archiva-modules/archiva-base/archiva-test-utils/src/main/java/org/apache/archiva/test/utils/ArchivaSpringJUnit4ClassRunner.java
@@ -20,6 +20,9 @@ import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.InitializationError;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.List;
 
 /**
@@ -29,6 +32,18 @@ public class ArchivaSpringJUnit4ClassRunner
     extends SpringJUnit4ClassRunner
 {
 
+    static {
+
+        if (System.getProperty("archiva.user.configFileName")!=null && !"".equals(System.getProperty("archiva.user.configFileName").trim())) {
+            try {
+                Path file = Files.createTempFile("archiva-test-conf", ".xml");
+                System.setProperty("archiva.user.configFileName", file.toAbsolutePath().toString());
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
     public ArchivaSpringJUnit4ClassRunner( Class<?> clazz )
         throws InitializationError
     {
diff --git a/archiva-modules/archiva-maven/archiva-maven-indexer/src/main/java/org/apache/archiva/indexer/maven/MavenIndexContext.java b/archiva-modules/archiva-maven/archiva-maven-indexer/src/main/java/org/apache/archiva/indexer/maven/MavenIndexContext.java
index 7f18ad1..c4c5e3b 100644
--- a/archiva-modules/archiva-maven/archiva-maven-indexer/src/main/java/org/apache/archiva/indexer/maven/MavenIndexContext.java
+++ b/archiva-modules/archiva-maven/archiva-maven-indexer/src/main/java/org/apache/archiva/indexer/maven/MavenIndexContext.java
@@ -37,6 +37,7 @@ import java.nio.file.Path;
 import java.sql.Date;
 import java.time.ZonedDateTime;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Maven implementation of index context
@@ -45,6 +46,8 @@ public class MavenIndexContext implements ArchivaIndexingContext {
 
     private static final Logger log = LoggerFactory.getLogger(ArchivaIndexingContext.class);
 
+
+    private AtomicBoolean openStatus = new AtomicBoolean(false);
     private IndexingContext delegate;
     private Repository repository;
     private StorageAsset dir = null;
@@ -52,6 +55,7 @@ public class MavenIndexContext implements ArchivaIndexingContext {
     protected MavenIndexContext(Repository repository, IndexingContext delegate) {
         this.delegate = delegate;
         this.repository = repository;
+        this.openStatus.set(true);
 
     }
 
@@ -107,23 +111,32 @@ public class MavenIndexContext implements ArchivaIndexingContext {
 
     @Override
     public void close(boolean deleteFiles) throws IOException {
-        try {
-            delegate.close(deleteFiles);
-        } catch (NoSuchFileException e) {
-            // Ignore missing directory
+        if (openStatus.compareAndSet(true,false)) {
+            try {
+                delegate.close(deleteFiles);
+            } catch (NoSuchFileException e) {
+                // Ignore missing directory
+            }
         }
     }
 
     @Override
     public void close() throws IOException {
-        try {
-            delegate.close(false);
-        } catch (NoSuchFileException e) {
-            // Ignore missing directory
+        if (openStatus.compareAndSet(true,false)) {
+            try {
+                delegate.close(false);
+            } catch (NoSuchFileException e) {
+                // Ignore missing directory
+            }
         }
     }
 
     @Override
+    public boolean isOpen() {
+        return openStatus.get();
+    }
+
+    @Override
     public void purge() throws IOException {
         delegate.purge();
     }
diff --git a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java
index f2170f2..f36e261 100644
--- a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java
+++ b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java
@@ -26,6 +26,7 @@ import org.apache.archiva.configuration.ArchivaConfiguration;
 import org.apache.archiva.configuration.Configuration;
 import org.apache.archiva.configuration.ConfigurationListener;
 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
+import org.apache.archiva.indexer.ArchivaIndexingContext;
 import org.apache.archiva.indexer.search.SearchResultHit;
 import org.apache.archiva.indexer.search.SearchResults;
 import org.apache.archiva.repository.Repository;
@@ -145,7 +146,7 @@ public abstract class AbstractMavenRepositorySearch
         EasyMock.expectLastCall().anyTimes();
         archivaConfigControl.replay();
         repositoryRegistry.reload();
-        archivaConfigControl.reset();
+
     }
 
     @After
@@ -210,11 +211,12 @@ public abstract class AbstractMavenRepositorySearch
         IndexCreationFeature icf = rRepo.getFeature(IndexCreationFeature.class).get();
 
 
-        IndexingContext context = rRepo.getIndexingContext().getBaseContext(IndexingContext.class);
+        ArchivaIndexingContext archivaCtx = rRepo.getIndexingContext();
+        IndexingContext context = archivaCtx.getBaseContext(IndexingContext.class);
 
-        if ( context != null )
+        if ( archivaCtx != null )
         {
-            context.close(true);
+            archivaCtx.close(true);
         }
 
         Path repoDir = Paths.get(org.apache.archiva.common.utils.FileUtils.getBasedir()).resolve("target").resolve("repos").resolve(repository);
@@ -233,13 +235,7 @@ public abstract class AbstractMavenRepositorySearch
         {
             Files.delete(lockFile);
         }
-
         assertFalse( Files.exists(lockFile) );
-
-        Path repo = Paths.get( org.apache.archiva.common.utils.FileUtils.getBasedir(), "src/test/" + repository );
-        assertTrue( Files.exists(repo) );
-        org.apache.commons.io.FileUtils.copyDirectory(repo.toFile(), repoDir.toFile());
-
         if (indexDir==null) {
             Path indexDirectory =
                     Paths.get(org.apache.archiva.common.utils.FileUtils.getBasedir(), "target/index/test-" + Long.toString(System.currentTimeMillis()));
@@ -250,7 +246,28 @@ public abstract class AbstractMavenRepositorySearch
 
             icf.setIndexPath(indexDir.toUri());
         }
-        context = rRepo.getIndexingContext().getBaseContext(IndexingContext.class);
+        Path repo = Paths.get( org.apache.archiva.common.utils.FileUtils.getBasedir(), "src/test/" + repository );
+        assertTrue( Files.exists(repo) );
+        org.apache.commons.io.FileUtils.copyDirectory(repo.toFile(), repoDir.toFile());
+
+
+
+
+        archivaConfigControl.reset();
+        archivaConfig.addListener( EasyMock.anyObject( ConfigurationListener.class ) );
+        EasyMock.expect( archivaConfig.getConfiguration() ).andReturn(config).anyTimes();
+        archivaConfig.save(EasyMock.anyObject(Configuration.class));
+        EasyMock.expectLastCall().anyTimes();
+        archivaConfigControl.replay();
+        repositoryRegistry.reload();
+        archivaConfigControl.reset();
+
+        rRepo = repositoryRegistry.getRepository(repository);
+        icf = rRepo.getFeature(IndexCreationFeature.class).get();
+
+
+        archivaCtx = rRepo.getIndexingContext();
+        context = archivaCtx.getBaseContext(IndexingContext.class);
 
 
         // minimize datas in memory
diff --git a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java
index 066b2af..74819f9 100644
--- a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java
+++ b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java
@@ -61,7 +61,7 @@ public class MavenRepositorySearchOSGITest
         List<String> selectedRepos = Arrays.asList( TEST_REPO_1 );
 
         // search artifactId
-        EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
+        // EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
         EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
 
         archivaConfigControl.replay();
diff --git a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchTest.java b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchTest.java
index cb43a1a..0b5b1bd 100644
--- a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchTest.java
+++ b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchTest.java
@@ -410,10 +410,10 @@ public class MavenRepositorySearchTest
         List<String> selectedRepos = new ArrayList<>();
         selectedRepos.add( TEST_REPO_1 );
 
-        EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
-        EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
+        // EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
+        // EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
 
-        archivaConfigControl.replay();
+        // archivaConfigControl.replay();
 
         SearchResults results = search.search( "user", selectedRepos, "org.apache.archiva", null, null );
         assertNotNull( results );
@@ -429,7 +429,7 @@ public class MavenRepositorySearchTest
         List<String> selectedRepos = new ArrayList<>();
         selectedRepos.add( "non-existing-repo" );
 
-        archivaConfigControl.replay();
+        // archivaConfigControl.replay();
 
         SearchResults results = search.search( "user", selectedRepos, "org.apache.archiva", null, null );
         assertNotNull( results );
@@ -621,10 +621,10 @@ public class MavenRepositorySearchTest
 
         try
         {
-            EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
-            EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
+            // EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
+            // EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
 
-            archivaConfigControl.replay();
+            // archivaConfigControl.replay();
 
             search.search( "user", searchFields, null );
 
@@ -657,9 +657,9 @@ public class MavenRepositorySearchTest
         try
         {
 
-            EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
-            EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
-            archivaConfigControl.replay();
+            // EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
+            // EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
+            // archivaConfigControl.replay();
 
             search.search( "user", searchFields, null );
 
@@ -805,10 +805,10 @@ public class MavenRepositorySearchTest
         searchFields.setGroupId( "org.apache.archiva" );
         searchFields.setRepositories( selectedRepos );
 
-        EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
-        EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
+        // EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
+        // EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
 
-        archivaConfigControl.replay();
+        // archivaConfigControl.replay();
 
         SearchResults results = search.search( "user", searchFields, null );
 
@@ -913,7 +913,7 @@ public class MavenRepositorySearchTest
         SearchResultLimits limits = new SearchResultLimits( SearchResultLimits.ALL_PAGES );
         limits.setPageSize( 300 );
 
-        EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
+        // EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes();
         EasyMock.expect( archivaConfig.getConfiguration()).andReturn(config).anyTimes();
 
         archivaConfigControl.replay();
diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenManagedRepository.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenManagedRepository.java
index 2836ca2..96eb6e9 100644
--- a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenManagedRepository.java
+++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenManagedRepository.java
@@ -22,6 +22,7 @@ package org.apache.archiva.repository.maven2;
 import org.apache.archiva.common.filelock.DefaultFileLockManager;
 import org.apache.archiva.common.filelock.FileLockManager;
 import org.apache.archiva.common.utils.PathUtil;
+import org.apache.archiva.indexer.ArchivaIndexingContext;
 import org.apache.archiva.repository.*;
 import org.apache.archiva.repository.storage.FilesystemStorage;
 import org.apache.archiva.repository.content.maven2.MavenRepositoryRequestInfo;
@@ -131,4 +132,10 @@ public class MavenManagedRepository extends AbstractManagedRepository
         FilesystemStorage storage = new FilesystemStorage(basePath.resolve(id), lockManager);
         return new MavenManagedRepository(id, name, storage);
     }
+
+    @Override
+    public void setIndexingContext(ArchivaIndexingContext context) {
+        super.setIndexingContext(context);
+    }
+
 }
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 15dbf6a..ec78a94 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
@@ -23,12 +23,11 @@ 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;
 import org.apache.archiva.repository.features.RemoteIndexFeature;
 import org.apache.archiva.repository.features.StagingRepositoryFeature;
+import org.apache.archiva.repository.storage.FilesystemStorage;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -184,9 +183,13 @@ public class MavenRepositoryProvider implements RepositoryProvider {
         repo.setScanned(cfg.isScanned());
         if (cfg.isReleases()) {
             repo.addActiveReleaseScheme(ReleaseScheme.RELEASE);
+        } else {
+            repo.removeActiveReleaseScheme(ReleaseScheme.RELEASE);
         }
         if (cfg.isSnapshots()) {
             repo.addActiveReleaseScheme(ReleaseScheme.SNAPSHOT);
+        } else {
+            repo.removeActiveReleaseScheme(ReleaseScheme.SNAPSHOT);
         }
 
         StagingRepositoryFeature stagingRepositoryFeature = repo.getFeature(StagingRepositoryFeature.class).get();
@@ -349,13 +352,20 @@ public class MavenRepositoryProvider implements RepositoryProvider {
         cfg.setPackedIndexDir(convertUriToPath(indexCreationFeature.getPackedIndexPath()));
 
         RemoteIndexFeature remoteIndexFeature = remoteRepository.getFeature(RemoteIndexFeature.class).get();
-        if (remoteIndexFeature.getIndexUri()!=null) {
+        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());
         cfg.setRemoteDownloadNetworkProxyId(remoteIndexFeature.getProxyId());
+        if (!StringUtils.isEmpty(remoteIndexFeature.getProxyId())) {
+            cfg.setRemoteDownloadNetworkProxyId(remoteIndexFeature.getProxyId());
+        } else {
+            cfg.setRemoteDownloadNetworkProxyId("");
+        }
+
+
 
 
         return cfg;
diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/metadata/repository/storage/maven2/Maven2RepositoryMetadataResolverMRM1411Test.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/metadata/repository/storage/maven2/Maven2RepositoryMetadataResolverMRM1411Test.java
index 3bb6146..1788b9f 100644
--- a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/metadata/repository/storage/maven2/Maven2RepositoryMetadataResolverMRM1411Test.java
+++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/metadata/repository/storage/maven2/Maven2RepositoryMetadataResolverMRM1411Test.java
@@ -36,6 +36,7 @@ import org.apache.archiva.metadata.repository.storage.ReadMetadataRequest;
 import org.apache.archiva.metadata.repository.storage.RepositoryStorageRuntimeException;
 import org.apache.archiva.proxy.maven.WagonFactory;
 import org.apache.archiva.proxy.maven.WagonFactoryRequest;
+import org.apache.archiva.repository.ReleaseScheme;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
 import org.apache.commons.io.FileUtils;
@@ -311,6 +312,7 @@ public class Maven2RepositoryMetadataResolverMRM1411Test
         testRepo.setSnapshots( false );
         configuration.save( c );
         repositoryRegistry.reload();
+        assertFalse(repositoryRegistry.getManagedRepository(testRepo.getId()).getActiveReleaseSchemes().contains(ReleaseScheme.SNAPSHOT));
         assertFalse( c.getManagedRepositories().get( 0 ).isSnapshots() );
         copyTestArtifactWithParent( "target/test-classes/com/example/test/test-snapshot-artifact-module-a",
                                     "target/test-repository/com/example/test/test-snapshot-artifact-module-a" );
diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/index/mock/MavenIndexContextMock.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/index/mock/MavenIndexContextMock.java
index a6dddae..ded8ed3 100644
--- a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/index/mock/MavenIndexContextMock.java
+++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/index/mock/MavenIndexContextMock.java
@@ -38,6 +38,7 @@ import java.util.Set;
  */
 public class MavenIndexContextMock implements ArchivaIndexingContext {
 
+    private boolean open = true;
     private IndexingContext delegate;
     private Repository repository;
     private FilesystemStorage indexStorage;
@@ -86,6 +87,7 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
 
     @Override
     public void close(boolean deleteFiles) throws IOException {
+        open = false;
         try {
             delegate.close(deleteFiles);
         } catch (NoSuchFileException e) {
@@ -95,6 +97,7 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
 
     @Override
     public void close() throws IOException {
+        open = false;
         try {
             delegate.close(false);
         } catch (NoSuchFileException e) {
@@ -103,6 +106,11 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
     }
 
     @Override
+    public boolean isOpen() {
+        return open;
+    }
+
+    @Override
     public void purge() throws IOException {
         delegate.purge();
     }
diff --git a/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/mock/MavenIndexContextMock.java b/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/mock/MavenIndexContextMock.java
index fa070a7..c8e2cd4 100644
--- a/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/mock/MavenIndexContextMock.java
+++ b/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/mock/MavenIndexContextMock.java
@@ -40,6 +40,8 @@ import java.util.Set;
  */
 public class MavenIndexContextMock implements ArchivaIndexingContext {
 
+    private boolean open = true;
+
     private IndexingContext delegate;
     private Repository repository;
     private FilesystemStorage filesystemStorage;
@@ -93,6 +95,7 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
 
     @Override
     public void close(boolean deleteFiles) throws IOException {
+        this.open = false;
         try {
             delegate.close(deleteFiles);
         } catch (NoSuchFileException e) {
@@ -102,6 +105,7 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
 
     @Override
     public void close() throws IOException {
+        this.open = false;
         try {
             delegate.close(false);
         } catch (NoSuchFileException e) {
@@ -110,6 +114,11 @@ public class MavenIndexContextMock implements ArchivaIndexingContext {
     }
 
     @Override
+    public boolean isOpen() {
+        return open;
+    }
+
+    @Override
     public void purge() throws IOException {
         delegate.purge();
     }
diff --git a/archiva-modules/archiva-web/archiva-webdav/pom.xml b/archiva-modules/archiva-web/archiva-webdav/pom.xml
index 79a8e9d..37cb92a 100644
--- a/archiva-modules/archiva-web/archiva-webdav/pom.xml
+++ b/archiva-modules/archiva-web/archiva-webdav/pom.xml
@@ -332,6 +332,7 @@
             <openjpa.Log>${openjpa.Log}</openjpa.Log>
             <org.apache.jackrabbit.core.state.validatehierarchy>true</org.apache.jackrabbit.core.state.validatehierarchy>
           </systemPropertyVariables>
+          <trimStackTrace>false</trimStackTrace>
         </configuration>
       </plugin>
     </plugins>
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java
index 2d2b42c..2094ba3 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java
@@ -190,7 +190,9 @@ public abstract class AbstractRepositoryServletTestCase
         ArchivaIndexingContext ctx = repositoryRegistry.getManagedRepository( REPOID_INTERNAL ).getIndexingContext( );
         try
         {
-            repositoryRegistry.getIndexManager( RepositoryType.MAVEN ).pack( ctx );
+            if (repositoryRegistry.getIndexManager(RepositoryType.MAVEN)!=null) {
+                repositoryRegistry.getIndexManager(RepositoryType.MAVEN).pack(ctx);
+            }
         } finally
         {
             ctx.close(  );
@@ -810,6 +812,8 @@ public abstract class AbstractRepositoryServletTestCase
         repo.setLocation( location.toAbsolutePath().toString() );
         repo.setBlockRedeployments( blockRedeployments );
         repo.setType( "MAVEN" );
+        repo.setIndexDir(".indexer");
+        repo.setPackedIndexDir(".index");
 
         return repo;
     }
@@ -835,7 +839,7 @@ public abstract class AbstractRepositoryServletTestCase
         throws Exception
     {
         repositoryRegistry.setArchivaConfiguration(archivaConfiguration);
-        repositoryRegistry.reload();
+        // repositoryRegistry.reload();
         archivaConfiguration.save( archivaConfiguration.getConfiguration() );
 
     }