http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/managed/DefaultManagedRepositoryAdmin.java
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/managed/DefaultManagedRepositoryAdmin.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/managed/DefaultManagedRepositoryAdmin.java
index ae7cd62..469d122 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/managed/DefaultManagedRepositoryAdmin.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/managed/DefaultManagedRepositoryAdmin.java
@@ -28,6 +28,10 @@ import 
org.apache.archiva.configuration.IndeterminateConfigurationException;
 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
+import org.apache.archiva.indexer.ArchivaIndexManager;
+import org.apache.archiva.indexer.ArchivaIndexingContext;
+import org.apache.archiva.indexer.IndexManagerFactory;
+import org.apache.archiva.indexer.IndexUpdateFailedException;
 import org.apache.archiva.metadata.model.facets.AuditEvent;
 import org.apache.archiva.metadata.repository.MetadataRepository;
 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
@@ -40,6 +44,7 @@ import 
org.apache.archiva.redback.components.taskqueue.TaskQueueException;
 import org.apache.archiva.redback.role.RoleManager;
 import org.apache.archiva.redback.role.RoleManagerException;
 import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.Repository;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.features.ArtifactCleanupFeature;
@@ -50,10 +55,8 @@ import 
org.apache.archiva.scheduler.repository.model.RepositoryTask;
 import org.apache.archiva.security.common.ArchivaRoleConstants;
 import org.apache.commons.lang.StringUtils;
 import org.apache.maven.index.NexusIndexer;
-import org.apache.maven.index.context.IndexCreator;
+
 import org.apache.maven.index.context.IndexingContext;
-import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
-import org.apache.maven.index_shaded.lucene.index.IndexFormatTooOldException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
@@ -112,12 +115,11 @@ public class DefaultManagedRepositoryAdmin
     @Named(value = "cache#namespaces")
     private Cache<String, Collection<String>> namespacesCache;
 
-    // fields
     @Inject
-    private List<? extends IndexCreator> indexCreators;
+    private IndexManagerFactory indexManagerFactory;
+
+
 
-    @Inject
-    private NexusIndexer indexer;
 
     @PostConstruct
     public void initialize()
@@ -127,7 +129,6 @@ public class DefaultManagedRepositoryAdmin
         for ( ManagedRepository managedRepository : getManagedRepositories() )
         {
             log.debug("Initializating {}", managedRepository.getId());
-            createIndexContext( managedRepository );
             addRepositoryRoles( managedRepository.getId() );
 
         }
@@ -137,22 +138,6 @@ public class DefaultManagedRepositoryAdmin
     public void shutdown()
         throws RepositoryAdminException
     {
-        try
-        {
-            // close index on shutdown
-            for ( ManagedRepository managedRepository : 
getManagedRepositories() )
-            {
-                IndexingContext context = indexer.getIndexingContexts().get( 
managedRepository.getId() );
-                if ( context != null )
-                {
-                    indexer.removeIndexingContext( context, false );
-                }
-            }
-        }
-        catch ( IOException e )
-        {
-            throw new RepositoryAdminException( e.getMessage(), e );
-        }
     }
 
     /*
@@ -290,7 +275,6 @@ public class DefaultManagedRepositoryAdmin
             log.error("Could not add repository roles for repository [{}]: 
{}", managedRepository.getId(), e.getMessage(), e);
             throw new RepositoryAdminException( "Could not add roles to 
repository "+e.getMessage() );
         }
-        createIndexContext( managedRepository );
         return Boolean.TRUE;
 
     }
@@ -304,64 +288,56 @@ public class DefaultManagedRepositoryAdmin
     {
         Configuration config = getArchivaConfiguration().getConfiguration();
         ManagedRepositoryConfiguration 
repoConfig=config.findManagedRepositoryById( repositoryId );
-
-        log.debug("Repo location "+repoConfig.getLocation());
-
-        org.apache.archiva.repository.ManagedRepository repo = 
repositoryRegistry.getManagedRepository( repositoryId );
-        org.apache.archiva.repository.ManagedRepository stagingRepository = 
null;
-        if (repo!=null) {
-            try
-            {
-                if (repo.supportsFeature( StagingRepositoryFeature.class )) {
-                    stagingRepository = repo.getFeature( 
StagingRepositoryFeature.class ).get().getStagingRepository();
+        if (repoConfig!=null) {
+
+            log.debug("Repo location " + repoConfig.getLocation());
+
+            org.apache.archiva.repository.ManagedRepository repo = 
repositoryRegistry.getManagedRepository(repositoryId);
+            org.apache.archiva.repository.ManagedRepository stagingRepository 
= null;
+            if (repo != null) {
+                try {
+                    if (repo.supportsFeature(StagingRepositoryFeature.class)) {
+                        stagingRepository = 
repo.getFeature(StagingRepositoryFeature.class).get().getStagingRepository();
+                    }
+                    repositoryRegistry.removeRepository(repo, config);
+                } catch (RepositoryException e) {
+                    log.error("Removal of repository {} failed: {}", 
repositoryId, e.getMessage(), e);
+                    throw new RepositoryAdminException("Removal of repository 
" + repositoryId + " failed.");
                 }
-                repositoryRegistry.removeRepository( repo, config );
-            }
-            catch ( RepositoryException e )
-            {
-                log.error("Removal of repository {} failed: {}", repositoryId, 
e.getMessage(), e);
-                throw new RepositoryAdminException( "Removal of repository 
"+repositoryId+" failed." );
+            } else {
+                throw new RepositoryAdminException("A repository with that id 
does not exist");
             }
-        } else {
-            throw new RepositoryAdminException( "A repository with that id 
does not exist" );
-        }
 
-        triggerAuditEvent( repositoryId, null, AuditEvent.DELETE_MANAGED_REPO, 
auditInformation );
-        if (repoConfig!=null)
-        {
-            deleteManagedRepository( repoConfig, deleteContent, config, false 
);
-        }
+            triggerAuditEvent(repositoryId, null, 
AuditEvent.DELETE_MANAGED_REPO, auditInformation);
+            if (repoConfig != null) {
+                deleteManagedRepository(repoConfig, deleteContent, config, 
false);
+            }
 
 
-        // stage repo exists ?
-        if ( stagingRepository != null )
-        {
-            // do not trigger event when deleting the staged one
-            ManagedRepositoryConfiguration stagingRepositoryConfig = 
config.findManagedRepositoryById( stagingRepository.getId( ) );
-            try
-            {
-                repositoryRegistry.removeRepository( stagingRepository );
-                if (stagingRepositoryConfig!=null)
-                {
-                    deleteManagedRepository( stagingRepositoryConfig, 
deleteContent, config, true );
+            // stage repo exists ?
+            if (stagingRepository != null) {
+                // do not trigger event when deleting the staged one
+                ManagedRepositoryConfiguration stagingRepositoryConfig = 
config.findManagedRepositoryById(stagingRepository.getId());
+                try {
+                    repositoryRegistry.removeRepository(stagingRepository);
+                    if (stagingRepositoryConfig != null) {
+                        deleteManagedRepository(stagingRepositoryConfig, 
deleteContent, config, true);
+                    }
+                } catch (RepositoryException e) {
+                    log.error("Removal of staging repository {} failed: {}", 
stagingRepository.getId(), e.getMessage(), e);
                 }
             }
-            catch ( RepositoryException e )
-            {
-                log.error("Removal of staging repository {} failed: {}", 
stagingRepository.getId(), e.getMessage(), e);
+
+            try {
+                saveConfiguration(config);
+            } catch (Exception e) {
+                throw new RepositoryAdminException("Error saving configuration 
for delete action" + e.getMessage(), e);
             }
-        }
 
-        try
-        {
-            saveConfiguration( config );
-        }
-        catch ( Exception e )
-        {
-            throw new RepositoryAdminException( "Error saving configuration 
for delete action" + e.getMessage(), e );
+            return Boolean.TRUE;
+        } else {
+            return Boolean.FALSE;
         }
-
-        return Boolean.TRUE;
     }
 
     private Boolean deleteManagedRepository( ManagedRepositoryConfiguration 
repository, boolean deleteContent,
@@ -369,20 +345,6 @@ public class DefaultManagedRepositoryAdmin
         throws RepositoryAdminException
     {
 
-        try
-        {
-            IndexingContext context = indexer.getIndexingContexts().get( 
repository.getId() );
-            if ( context != null )
-            {
-                // delete content only if directory exists
-                indexer.removeIndexingContext( context,
-                                                    deleteContent && 
context.getIndexDirectoryFile().exists() );
-            }
-        }
-        catch ( IOException e )
-        {
-            throw new RepositoryAdminException( e.getMessage(), e );
-        }
         if ( !stagedOne )
         {
             RepositorySession repositorySession = 
getRepositorySessionFactory().createSession();
@@ -454,11 +416,24 @@ public class DefaultManagedRepositoryAdmin
                 "fail to remove repository roles for repository " + 
repository.getId() + " : " + e.getMessage(), e );
         }
 
+        try {
+            final RepositoryRegistry reg = getRepositoryRegistry();
+            if (reg.getManagedRepository(repository.getId())!=null) {
+                
reg.removeRepository(reg.getManagedRepository(repository.getId()));
+            }
+        } catch (RepositoryException e) {
+            throw new RepositoryAdminException("Removal of repository 
"+repository.getId()+ " failed: "+e.getMessage());
+        }
+
         saveConfiguration( config );
 
         return Boolean.TRUE;
     }
 
+    ArchivaIndexManager getIndexManager(ManagedRepository managedRepository) {
+        org.apache.archiva.repository.ManagedRepository repo = 
getRepositoryRegistry().getManagedRepository(managedRepository.getId());
+        return indexManagerFactory.getIndexManager(repo.getType());
+    }
 
     @Override
     public Boolean updateManagedRepository( ManagedRepository 
managedRepository, boolean needStageRepo,
@@ -486,11 +461,11 @@ public class DefaultManagedRepositoryAdmin
             stagingExists = oldRepo.getFeature( StagingRepositoryFeature.class 
).get().getStagingRepository() != null;
         }
         boolean updateIndexContext = !StringUtils.equals( 
updatedRepoConfig.getIndexDir(), managedRepository.getIndexDirectory() );
-
+        org.apache.archiva.repository.ManagedRepository newRepo;
         // TODO remove content from old if path has changed !!!!!
         try
         {
-            org.apache.archiva.repository.ManagedRepository newRepo = 
repositoryRegistry.putRepository( updatedRepoConfig, configuration );
+            newRepo = repositoryRegistry.putRepository( updatedRepoConfig, 
configuration );
             if (newRepo.supportsFeature( StagingRepositoryFeature.class )) {
                 org.apache.archiva.repository.ManagedRepository stagingRepo = 
newRepo.getFeature( StagingRepositoryFeature.class ).get( 
).getStagingRepository( );
                 if (stagingRepo!=null && !stagingExists)
@@ -551,21 +526,10 @@ public class DefaultManagedRepositoryAdmin
         {
             try
             {
-                IndexingContext indexingContext = 
indexer.getIndexingContexts().get( managedRepository.getId() );
-                if ( indexingContext != null )
-                {
-                    indexer.removeIndexingContext( indexingContext, true );
-                }
-
-                // delete directory too as only content is deleted
-                Path indexDirectory = 
indexingContext.getIndexDirectoryFile().toPath();
-                org.apache.archiva.common.utils.FileUtils.deleteDirectory( 
indexDirectory );
 
-                createIndexContext( managedRepository );
-            }
-            catch ( IOException e )
-            {
-                throw new RepositoryAdminException( e.getMessage(), e );
+                repositoryRegistry.resetIndexingContext(newRepo);
+            } catch (IndexUpdateFailedException e) {
+                e.printStackTrace();
             }
         }
 
@@ -591,110 +555,6 @@ public class DefaultManagedRepositoryAdmin
 
     }
 
-    public IndexingContext createIndexContext( 
org.apache.archiva.repository.ManagedRepository repository) throws 
RepositoryAdminException
-    {
-        return createIndexContext( convertRepo( repository ) );
-    }
-
-    @Override
-    public IndexingContext createIndexContext( ManagedRepository repository )
-        throws RepositoryAdminException
-    {
-
-        IndexingContext context = indexer.getIndexingContexts().get( 
repository.getId() );
-
-        if ( context != null )
-        {
-            log.debug( "skip creating repository indexingContent with id {} as 
already exists", repository.getId() );
-            return context;
-        }
-
-        // take care first about repository location as can be relative
-        Path repositoryDirectory = Paths.get( repository.getLocation() );
-
-        if ( !repositoryDirectory.isAbsolute() )
-        {
-            repositoryDirectory =
-                Paths.get( getRegistry().getString( "appserver.base" ), 
"repositories",
-                          repository.getLocation() );
-        }
-
-        if ( !Files.exists(repositoryDirectory) )
-        {
-            try {
-                Files.createDirectories(repositoryDirectory);
-            } catch (IOException e) {
-                log.error("Could not create directory {}", 
repositoryDirectory);
-            }
-        }
-
-        try
-        {
-
-            String indexDir = repository.getIndexDirectory();
-            //File managedRepository = new File( repository.getLocation() );
-
-            Path indexDirectory = null;
-            if ( StringUtils.isNotBlank( indexDir ) )
-            {
-                indexDirectory = Paths.get( repository.getIndexDirectory() );
-                // not absolute so create it in repository directory
-                if ( !indexDirectory.isAbsolute() )
-                {
-                    indexDirectory = 
repositoryDirectory.resolve(repository.getIndexDirectory() );
-                }
-                repository.setIndexDirectory( 
indexDirectory.toAbsolutePath().toString() );
-            }
-            else
-            {
-                indexDirectory = repositoryDirectory.resolve(".indexer" );
-                if ( !repositoryDirectory.isAbsolute() )
-                {
-                    indexDirectory = repositoryDirectory.resolve( ".indexer" );
-                }
-                repository.setIndexDirectory( 
indexDirectory.toAbsolutePath().toString() );
-            }
-
-            if ( !Files.exists(indexDirectory) )
-            {
-                Files.createDirectories(indexDirectory);
-            }
-
-            context = indexer.getIndexingContexts().get( repository.getId() );
-
-            if ( context == null )
-            {
-                try
-                {
-                    context = indexer.addIndexingContext( repository.getId(), 
repository.getId(), repositoryDirectory.toFile(),
-                                                          
indexDirectory.toFile(),
-                                                          
repositoryDirectory.toUri().toURL().toExternalForm(),
-                                                          
indexDirectory.toUri().toURL().toString(), indexCreators );
-
-                    context.setSearchable( repository.isScanned() );
-                }
-                catch ( IndexFormatTooOldException e )
-                {
-                    // existing index with an old lucene format so we need to 
delete it!!!
-                    // delete it first then recreate it.
-                    log.warn( "the index of repository {} is too old we have 
to delete and recreate it", //
-                              repository.getId() );
-                    org.apache.archiva.common.utils.FileUtils.deleteDirectory( 
indexDirectory );
-                    context = indexer.addIndexingContext( repository.getId(), 
repository.getId(), repositoryDirectory.toFile(),
-                                                          
indexDirectory.toFile(),
-                                                          
repositoryDirectory.toUri().toURL().toExternalForm(),
-                                                          
indexDirectory.toUri().toURL().toString(), indexCreators );
-
-                    context.setSearchable( repository.isScanned() );
-                }
-            }
-            return context;
-        }
-        catch ( IOException| UnsupportedExistingLuceneIndexException e )
-        {
-            throw new RepositoryAdminException( e.getMessage(), e );
-        }
-    }
 
     public Boolean scanRepository( String repositoryId, boolean fullScan )
     {
@@ -799,25 +659,6 @@ public class DefaultManagedRepositoryAdmin
         this.repositoryTaskScheduler = repositoryTaskScheduler;
     }
 
-    public NexusIndexer getIndexer()
-    {
-        return indexer;
-    }
-
-    public void setIndexer( NexusIndexer indexer )
-    {
-        this.indexer = indexer;
-    }
-
-    public List<? extends IndexCreator> getIndexCreators()
-    {
-        return indexCreators;
-    }
-
-    public void setIndexCreators( List<? extends IndexCreator> indexCreators )
-    {
-        this.indexCreators = indexCreators;
-    }
 
     public RepositoryRegistry getRepositoryRegistry( )
     {

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/proxyconnector/DefaultProxyConnectorAdmin.java
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/proxyconnector/DefaultProxyConnectorAdmin.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/proxyconnector/DefaultProxyConnectorAdmin.java
index fbf2048..94ace55 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/proxyconnector/DefaultProxyConnectorAdmin.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/proxyconnector/DefaultProxyConnectorAdmin.java
@@ -30,6 +30,7 @@ import org.apache.archiva.configuration.Configuration;
 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
 import 
org.apache.archiva.configuration.functors.ProxyConnectorSelectionPredicate;
 import org.apache.archiva.metadata.model.facets.AuditEvent;
+import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.stereotype.Service;
@@ -53,10 +54,7 @@ public class DefaultProxyConnectorAdmin
 {
 
     @Inject
-    private ManagedRepositoryAdmin managedRepositoryAdmin;
-
-    @Inject
-    private RemoteRepositoryAdmin remoteRepositoryAdmin;
+    RepositoryRegistry repositoryRegistry;
 
     @Override
     public List<ProxyConnector> getProxyConnectors()
@@ -230,13 +228,13 @@ public class DefaultProxyConnectorAdmin
         throws RepositoryAdminException
     {
         // validate source a Managed target a Remote
-        if ( managedRepositoryAdmin.getManagedRepository( 
proxyConnector.getSourceRepoId() ) == null )
+        if ( repositoryRegistry.getManagedRepository( 
proxyConnector.getSourceRepoId() ) == null )
         {
             throw new RepositoryAdminException(
                 "non valid ProxyConnector sourceRepo with id " + 
proxyConnector.getSourceRepoId()
                     + " is not a ManagedRepository" );
         }
-        if ( remoteRepositoryAdmin.getRemoteRepository( 
proxyConnector.getTargetRepoId() ) == null )
+        if ( repositoryRegistry.getRemoteRepository( 
proxyConnector.getTargetRepoId() ) == null )
         {
             throw new RepositoryAdminException(
                 "non valid ProxyConnector sourceRepo with id " + 
proxyConnector.getTargetRepoId()

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
index 19b540a..3f8c58b 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
@@ -26,6 +26,7 @@ import org.apache.archiva.configuration.Configuration;
 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
 import org.apache.archiva.configuration.RepositoryCheckPath;
+import org.apache.archiva.indexer.UnsupportedBaseContextException;
 import org.apache.archiva.metadata.model.facets.AuditEvent;
 import org.apache.archiva.repository.RemoteRepository;
 import org.apache.archiva.repository.PasswordCredentials;
@@ -307,7 +308,9 @@ public class DefaultRemoteRepositoryAdmin
     {
         try
         {
-            String appServerBase = getRegistry().getString( "appserver.base" );
+            RemoteRepository repo = 
repositoryRegistry.getRemoteRepository(remoteRepository.getId());
+            return 
repo.getIndexingContext().getBaseContext(IndexingContext.class);
+            /*String appServerBase = getRegistry().getString( "appserver.base" 
);
 
             String contextKey = "remote-" + remoteRepository.getId();
             IndexingContext indexingContext = 
indexer.getIndexingContexts().get( contextKey );
@@ -359,11 +362,9 @@ public class DefaultRemoteRepositoryAdmin
                                                    remoteRepository.getUrl(), 
calculateIndexRemoteUrl( remoteRepository ),
                                                    indexCreators );
 
-            }
-        }
-        catch ( IOException | UnsupportedExistingLuceneIndexException e )
-        {
-            throw new RepositoryAdminException( e.getMessage(), e );
+            }*/
+        } catch (UnsupportedBaseContextException e) {
+            throw new RepositoryAdminException( e.getMessage(), e);
         }
 
     }

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/ArchivaIndexManagerMock.java
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/ArchivaIndexManagerMock.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/ArchivaIndexManagerMock.java
new file mode 100644
index 0000000..049f4a7
--- /dev/null
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/ArchivaIndexManagerMock.java
@@ -0,0 +1,777 @@
+package org.apache.archiva.admin.mock;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.admin.model.RepositoryAdminException;
+import org.apache.archiva.admin.model.beans.NetworkProxy;
+import org.apache.archiva.admin.model.networkproxy.NetworkProxyAdmin;
+import org.apache.archiva.common.utils.FileUtils;
+import org.apache.archiva.common.utils.PathUtil;
+import org.apache.archiva.configuration.ArchivaConfiguration;
+import org.apache.archiva.indexer.*;
+import org.apache.archiva.proxy.common.WagonFactory;
+import org.apache.archiva.proxy.common.WagonFactoryException;
+import org.apache.archiva.proxy.common.WagonFactoryRequest;
+import org.apache.archiva.repository.*;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.features.RemoteIndexFeature;
+import org.apache.commons.lang.StringUtils;
+import org.apache.maven.index.*;
+import org.apache.maven.index.context.IndexCreator;
+import org.apache.maven.index.context.IndexingContext;
+import org.apache.maven.index.packer.IndexPacker;
+import org.apache.maven.index.packer.IndexPackingRequest;
+import org.apache.maven.index.updater.IndexUpdateRequest;
+import org.apache.maven.index.updater.ResourceFetcher;
+import org.apache.maven.index_shaded.lucene.index.IndexFormatTooOldException;
+import org.apache.maven.wagon.*;
+import org.apache.maven.wagon.authentication.AuthenticationException;
+import org.apache.maven.wagon.authentication.AuthenticationInfo;
+import org.apache.maven.wagon.authorization.AuthorizationException;
+import org.apache.maven.wagon.events.TransferEvent;
+import org.apache.maven.wagon.events.TransferListener;
+import org.apache.maven.wagon.proxy.ProxyInfo;
+import org.apache.maven.wagon.shared.http.AbstractHttpClientWagon;
+import org.apache.maven.wagon.shared.http.HttpConfiguration;
+import org.apache.maven.wagon.shared.http.HttpMethodConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.inject.Inject;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.stream.Collectors;
+
+@Service("archivaIndexManager#maven")
+public class ArchivaIndexManagerMock implements ArchivaIndexManager {
+
+    private static final Logger log = LoggerFactory.getLogger( 
ArchivaIndexManagerMock.class );
+
+    @Inject
+    private Indexer indexer;
+
+    @Inject
+    private IndexerEngine indexerEngine;
+
+    @Inject
+    private List<? extends IndexCreator> indexCreators;
+
+    @Inject
+    private IndexPacker indexPacker;
+
+    @Inject
+    private Scanner scanner;
+
+    @Inject
+    private ArchivaConfiguration archivaConfiguration;
+
+    @Inject
+    private WagonFactory wagonFactory;
+
+    @Inject
+    private NetworkProxyAdmin networkProxyAdmin;
+
+
+    @Inject
+    private ArtifactContextProducer artifactContextProducer;
+
+    private ConcurrentSkipListSet<Path> activeContexts = new 
ConcurrentSkipListSet<>( );
+
+    private static final int WAIT_TIME = 100;
+    private static final int MAX_WAIT = 10;
+
+
+    public static IndexingContext getMvnContext(ArchivaIndexingContext context 
) throws UnsupportedBaseContextException
+    {
+        if ( !context.supports( IndexingContext.class ) )
+        {
+            log.error( "The provided archiva index context does not support 
the maven IndexingContext" );
+            throw new UnsupportedBaseContextException( "The context does not 
support the Maven IndexingContext" );
+        }
+        return context.getBaseContext( IndexingContext.class );
+    }
+
+    private Path getIndexPath( ArchivaIndexingContext ctx )
+    {
+        return PathUtil.getPathFromUri( ctx.getPath( ) );
+    }
+
+    @FunctionalInterface
+    interface IndexUpdateConsumer
+    {
+
+        void accept( IndexingContext indexingContext ) throws 
IndexUpdateFailedException;
+    }
+
+    /*
+     * This method is used to do some actions around the update execution 
code. And to make sure, that no other
+     * method is running on the same index.
+     */
+    private void executeUpdateFunction( ArchivaIndexingContext context, 
IndexUpdateConsumer function ) throws IndexUpdateFailedException
+    {
+        IndexingContext indexingContext = null;
+        try
+        {
+            indexingContext = getMvnContext( context );
+        }
+        catch ( UnsupportedBaseContextException e )
+        {
+            throw new IndexUpdateFailedException( "Maven index is not 
supported by this context", e );
+        }
+        final Path ctxPath = getIndexPath( context );
+        int loop = MAX_WAIT;
+        boolean active = false;
+        while ( loop-- > 0 && !active )
+        {
+            active = activeContexts.add( ctxPath );
+            try
+            {
+                Thread.currentThread( ).sleep( WAIT_TIME );
+            }
+            catch ( InterruptedException e )
+            {
+                // Ignore this
+            }
+        }
+        if ( active )
+        {
+            try
+            {
+                function.accept( indexingContext );
+            }
+            finally
+            {
+                activeContexts.remove( ctxPath );
+            }
+        }
+        else
+        {
+            throw new IndexUpdateFailedException( "Timeout while waiting for 
index release on context " + context.getId( ) );
+        }
+    }
+
+    @Override
+    public void pack( final ArchivaIndexingContext context ) throws 
IndexUpdateFailedException
+    {
+        executeUpdateFunction( context, indexingContext -> {
+                    try
+                    {
+                        IndexPackingRequest request = new IndexPackingRequest( 
indexingContext,
+                                indexingContext.acquireIndexSearcher( 
).getIndexReader( ),
+                                indexingContext.getIndexDirectoryFile( ) );
+                        indexPacker.packIndex( request );
+                        indexingContext.updateTimestamp( true );
+                    }
+                    catch ( IOException e )
+                    {
+                        log.error( "IOException while packing index of context 
" + context.getId( ) + ( StringUtils.isNotEmpty( e.getMessage( ) ) ? ": " + 
e.getMessage( ) : "" ) );
+                        throw new IndexUpdateFailedException( "IOException 
during update of " + context.getId( ), e );
+                    }
+                }
+        );
+
+    }
+
+    @Override
+    public void scan(final ArchivaIndexingContext context) throws 
IndexUpdateFailedException
+    {
+        executeUpdateFunction( context, indexingContext -> {
+            DefaultScannerListener listener = new DefaultScannerListener( 
indexingContext, indexerEngine, true, null );
+            ScanningRequest request = new ScanningRequest( indexingContext, 
listener );
+            ScanningResult result = scanner.scan( request );
+            if ( result.hasExceptions( ) )
+            {
+                log.error( "Exceptions occured during index scan of " + 
context.getId( ) );
+                result.getExceptions( ).stream( ).map( e -> e.getMessage( ) 
).distinct( ).limit( 5 ).forEach(
+                        s -> log.error( "Message: " + s )
+                );
+            }
+
+        } );
+    }
+
+    @Override
+    public void update(final ArchivaIndexingContext context, final boolean 
fullUpdate) throws IndexUpdateFailedException
+    {
+        log.info( "start download remote index for remote repository {}", 
context.getRepository( ).getId( ) );
+        URI remoteUpdateUri;
+        if ( !( context.getRepository( ) instanceof RemoteRepository) || 
!(context.getRepository().supportsFeature(RemoteIndexFeature.class)) )
+        {
+            throw new IndexUpdateFailedException( "The context is not 
associated to a remote repository with remote index " + context.getId( ) );
+        } else {
+            RemoteIndexFeature rif = 
context.getRepository().getFeature(RemoteIndexFeature.class).get();
+            remoteUpdateUri = 
context.getRepository().getLocation().resolve(rif.getIndexUri());
+        }
+        final RemoteRepository remoteRepository = (RemoteRepository) 
context.getRepository( );
+
+        executeUpdateFunction( context,
+                indexingContext -> {
+                    try
+                    {
+                        // create a temp directory to download files
+                        Path tempIndexDirectory = Paths.get( 
indexingContext.getIndexDirectoryFile( ).getParent( ), ".tmpIndex" );
+                        Path indexCacheDirectory = Paths.get( 
indexingContext.getIndexDirectoryFile( ).getParent( ), ".indexCache" );
+                        Files.createDirectories( indexCacheDirectory );
+                        if ( Files.exists( tempIndexDirectory ) )
+                        {
+                            
org.apache.archiva.common.utils.FileUtils.deleteDirectory( tempIndexDirectory );
+                        }
+                        Files.createDirectories( tempIndexDirectory );
+                        tempIndexDirectory.toFile( ).deleteOnExit( );
+                        String baseIndexUrl = 
indexingContext.getIndexUpdateUrl( );
+
+                        String wagonProtocol = remoteUpdateUri.toURL( 
).getProtocol( );
+
+                        NetworkProxy networkProxy = null;
+                        if ( remoteRepository.supportsFeature( 
RemoteIndexFeature.class ) )
+                        {
+                            RemoteIndexFeature rif = 
remoteRepository.getFeature( RemoteIndexFeature.class ).get( );
+                            if ( StringUtils.isNotBlank( rif.getProxyId( ) ) )
+                            {
+                                try
+                                {
+                                    networkProxy = 
networkProxyAdmin.getNetworkProxy( rif.getProxyId( ) );
+                                }
+                                catch ( RepositoryAdminException e )
+                                {
+                                    log.error( "Error occured while retrieving 
proxy {}", e.getMessage( ) );
+                                }
+                                if ( networkProxy == null )
+                                {
+                                    log.warn(
+                                            "your remote repository is 
configured to download remote index trought a proxy we cannot find id:{}",
+                                            rif.getProxyId( ) );
+                                }
+                            }
+
+                            final StreamWagon wagon = (StreamWagon) 
wagonFactory.getWagon(
+                                    new WagonFactoryRequest( wagonProtocol, 
remoteRepository.getExtraHeaders( ) ).networkProxy(
+                                            networkProxy )
+                            );
+                            int readTimeout = (int) rif.getDownloadTimeout( 
).toMillis( ) * 1000;
+                            wagon.setReadTimeout( readTimeout );
+                            wagon.setTimeout( (int) 
remoteRepository.getTimeout( ).toMillis( ) * 1000 );
+
+                            if ( wagon instanceof AbstractHttpClientWagon)
+                            {
+                                HttpConfiguration httpConfiguration = new 
HttpConfiguration( );
+                                HttpMethodConfiguration 
httpMethodConfiguration = new HttpMethodConfiguration( );
+                                httpMethodConfiguration.setUsePreemptive( true 
);
+                                httpMethodConfiguration.setReadTimeout( 
readTimeout );
+                                httpConfiguration.setGet( 
httpMethodConfiguration );
+                                AbstractHttpClientWagon.class.cast( wagon 
).setHttpConfiguration( httpConfiguration );
+                            }
+
+                            wagon.addTransferListener( new DownloadListener( ) 
);
+                            ProxyInfo proxyInfo = null;
+                            if ( networkProxy != null )
+                            {
+                                proxyInfo = new ProxyInfo( );
+                                proxyInfo.setType( networkProxy.getProtocol( ) 
);
+                                proxyInfo.setHost( networkProxy.getHost( ) );
+                                proxyInfo.setPort( networkProxy.getPort( ) );
+                                proxyInfo.setUserName( 
networkProxy.getUsername( ) );
+                                proxyInfo.setPassword( 
networkProxy.getPassword( ) );
+                            }
+                            AuthenticationInfo authenticationInfo = null;
+                            if ( remoteRepository.getLoginCredentials( ) != 
null && ( remoteRepository.getLoginCredentials( ) instanceof 
PasswordCredentials) )
+                            {
+                                PasswordCredentials creds = 
(PasswordCredentials) remoteRepository.getLoginCredentials( );
+                                authenticationInfo = new AuthenticationInfo( );
+                                authenticationInfo.setUserName( 
creds.getUsername( ) );
+                                authenticationInfo.setPassword( new String( 
creds.getPassword( ) ) );
+                            }
+                            wagon.connect( new 
org.apache.maven.wagon.repository.Repository( remoteRepository.getId( ), 
baseIndexUrl ), authenticationInfo,
+                                    proxyInfo );
+
+                            Path indexDirectory = 
indexingContext.getIndexDirectoryFile( ).toPath( );
+                            if ( !Files.exists( indexDirectory ) )
+                            {
+                                Files.createDirectories( indexDirectory );
+                            }
+
+                            ResourceFetcher resourceFetcher =
+                                    new WagonResourceFetcher( log, 
tempIndexDirectory, wagon, remoteRepository );
+                            IndexUpdateRequest request = new 
IndexUpdateRequest( indexingContext, resourceFetcher );
+                            request.setForceFullUpdate( fullUpdate );
+                            request.setLocalIndexCacheDir( 
indexCacheDirectory.toFile( ) );
+
+                            // indexUpdater.fetchAndUpdateIndex( request );
+
+                            indexingContext.updateTimestamp( true );
+                        }
+
+                    }
+                    catch ( AuthenticationException e )
+                    {
+                        log.error( "Could not login to the remote proxy for 
updating index of {}", remoteRepository.getId( ), e );
+                        throw new IndexUpdateFailedException( "Login in to 
proxy failed while updating remote repository " + remoteRepository.getId( ), e 
);
+                    }
+                    catch ( ConnectionException e )
+                    {
+                        log.error( "Connection error during index update for 
remote repository {}", remoteRepository.getId( ), e );
+                        throw new IndexUpdateFailedException( "Connection 
error during index update for remote repository " + remoteRepository.getId( ), 
e );
+                    }
+                    catch ( MalformedURLException e )
+                    {
+                        log.error( "URL for remote index update of remote 
repository {} is not correct {}", remoteRepository.getId( ), remoteUpdateUri, e 
);
+                        throw new IndexUpdateFailedException( "URL for remote 
index update of repository is not correct " + remoteUpdateUri, e );
+                    }
+                    catch ( IOException e )
+                    {
+                        log.error( "IOException during index update of remote 
repository {}: {}", remoteRepository.getId( ), e.getMessage( ), e );
+                        throw new IndexUpdateFailedException( "IOException 
during index update of remote repository " + remoteRepository.getId( )
+                                + ( StringUtils.isNotEmpty( e.getMessage( ) ) 
? ": " + e.getMessage( ) : "" ), e );
+                    }
+                    catch ( WagonFactoryException e )
+                    {
+                        log.error( "Wagon for remote index download of {} 
could not be created: {}", remoteRepository.getId( ), e.getMessage( ), e );
+                        throw new IndexUpdateFailedException( "Error while 
updating the remote index of " + remoteRepository.getId( ), e );
+                    }
+                } );
+
+    }
+
+    @Override
+    public void addArtifactsToIndex( final ArchivaIndexingContext context, 
final Collection<URI> artifactReference ) throws IndexUpdateFailedException
+    {
+        final URI ctxUri = context.getPath();
+        executeUpdateFunction(context, indexingContext -> {
+            Collection<ArtifactContext> artifacts = 
artifactReference.stream().map(r -> 
artifactContextProducer.getArtifactContext(indexingContext, 
Paths.get(ctxUri.resolve(r)).toFile())).collect(Collectors.toList());
+            try {
+                indexer.addArtifactsToIndex(artifacts, indexingContext);
+            } catch (IOException e) {
+                log.error("IOException while adding artifact {}", 
e.getMessage(), e);
+                throw new IndexUpdateFailedException("Error occured while 
adding artifact to index of "+context.getId()
+                        + (StringUtils.isNotEmpty(e.getMessage()) ? ": 
"+e.getMessage() : ""));
+            }
+        });
+    }
+
+    @Override
+    public void removeArtifactsFromIndex( ArchivaIndexingContext context, 
Collection<URI> artifactReference ) throws IndexUpdateFailedException
+    {
+        final URI ctxUri = context.getPath();
+        executeUpdateFunction(context, indexingContext -> {
+            Collection<ArtifactContext> artifacts = 
artifactReference.stream().map(r -> 
artifactContextProducer.getArtifactContext(indexingContext, 
Paths.get(ctxUri.resolve(r)).toFile())).collect(Collectors.toList());
+            try {
+                indexer.deleteArtifactsFromIndex(artifacts, indexingContext);
+            } catch (IOException e) {
+                log.error("IOException while removing artifact {}", 
e.getMessage(), e);
+                throw new IndexUpdateFailedException("Error occured while 
removing artifact from index of "+context.getId()
+                        + (StringUtils.isNotEmpty(e.getMessage()) ? ": 
"+e.getMessage() : ""));
+            }
+        });
+
+    }
+
+    @Override
+    public boolean supportsRepository( RepositoryType type )
+    {
+        return type == RepositoryType.MAVEN;
+    }
+
+    @Override
+    public ArchivaIndexingContext createContext( Repository repository ) 
throws IndexCreationFailedException
+    {
+        log.debug("Creating context for repo {}, type: {}", 
repository.getId(), repository.getType());
+        if ( repository.getType( ) != RepositoryType.MAVEN )
+        {
+            throw new UnsupportedRepositoryTypeException( repository.getType( 
) );
+        }
+        IndexingContext mvnCtx = null;
+        try
+        {
+            if ( repository instanceof RemoteRepository )
+            {
+                mvnCtx = createRemoteContext( (RemoteRepository) repository );
+            }
+            else if ( repository instanceof ManagedRepository )
+            {
+                mvnCtx = createManagedContext( (ManagedRepository) repository 
);
+            }
+        }
+        catch ( IOException e )
+        {
+            log.error( "IOException during context creation " + e.getMessage( 
), e );
+            throw new IndexCreationFailedException( "Could not create index 
context for repository " + repository.getId( )
+                    + ( StringUtils.isNotEmpty( e.getMessage( ) ) ? ": " + 
e.getMessage( ) : "" ), e );
+        }
+        MavenIndexContextMock context = new MavenIndexContextMock( repository, 
mvnCtx );
+
+        return context;
+    }
+
+    @Override
+    public ArchivaIndexingContext reset(ArchivaIndexingContext context) throws 
IndexUpdateFailedException {
+        ArchivaIndexingContext ctx;
+        executeUpdateFunction(context, indexingContext -> {
+            try {
+                indexingContext.close(true);
+            } catch (IOException e) {
+                log.warn("Index close failed");
+            }
+            try {
+                FileUtils.deleteDirectory(Paths.get(context.getPath()));
+            } catch (IOException e) {
+                throw new IndexUpdateFailedException("Could not delete index 
files");
+            }
+        });
+        try {
+            Repository repo = context.getRepository();
+            ctx = createContext(context.getRepository());
+            if (repo instanceof EditableRepository) {
+                ((EditableRepository)repo).setIndexingContext(ctx);
+            }
+        } catch (IndexCreationFailedException e) {
+            throw new IndexUpdateFailedException("Could not create index");
+        }
+        return ctx;
+    }
+
+    @Override
+    public ArchivaIndexingContext move(ArchivaIndexingContext context, 
Repository repo) throws IndexCreationFailedException {
+        if (context==null) {
+            return null;
+        }
+        if (context.supports(IndexingContext.class)) {
+            try {
+                Path newPath = getIndexPath(repo);
+                IndexingContext ctx = 
context.getBaseContext(IndexingContext.class);
+                Path oldPath = ctx.getIndexDirectoryFile().toPath();
+                if (oldPath.equals(newPath)) {
+                    // Nothing to do, if path does not change
+                    return context;
+                }
+                if (!Files.exists(oldPath)) {
+                    return createContext(repo);
+                } else if (context.isEmpty()) {
+                    context.close();
+                    return createContext(repo);
+                } else {
+                    context.close(false);
+                    Files.move(oldPath, newPath);
+                    return createContext(repo);
+                }
+            } catch (IOException e) {
+                log.error("IOException while moving index directory {}", 
e.getMessage(), e);
+                throw new IndexCreationFailedException("Could not recreated 
the index.", e);
+            } catch (UnsupportedBaseContextException e) {
+                throw new IndexCreationFailedException("The given context, is 
not a maven context.");
+            }
+        } else {
+            throw new IndexCreationFailedException("Bad context type. This is 
not a maven context.");
+        }
+    }
+
+    private Path getIndexPath(Repository repo) throws IOException {
+        IndexCreationFeature icf = 
repo.getFeature(IndexCreationFeature.class).get();
+        Path repoDir = repo.getLocalPath();
+        URI indexDir = icf.getIndexPath();
+        Path indexDirectory = null;
+        if ( ! StringUtils.isEmpty(indexDir.toString( ) ) )
+        {
+
+            indexDirectory = PathUtil.getPathFromUri( indexDir );
+            // not absolute so create it in repository directory
+            if ( !indexDirectory.isAbsolute( ) )
+            {
+                indexDirectory = repoDir.resolve( indexDirectory );
+            }
+        }
+        else
+        {
+            indexDirectory = repoDir.resolve( ".index" );
+        }
+
+        if ( !Files.exists( indexDirectory ) )
+        {
+            Files.createDirectories( indexDirectory );
+        }
+        return indexDirectory;
+    }
+
+    private IndexingContext createRemoteContext(RemoteRepository 
remoteRepository ) throws IOException
+    {
+        Path appServerBase = archivaConfiguration.getAppServerBaseDir( );
+
+        String contextKey = "remote-" + remoteRepository.getId( );
+
+
+        // create remote repository path
+        Path repoDir = remoteRepository.getLocalPath();
+        if ( !Files.exists( repoDir ) )
+        {
+            Files.createDirectories( repoDir );
+        }
+
+        Path indexDirectory = null;
+
+        // is there configured indexDirectory ?
+        if ( remoteRepository.supportsFeature( RemoteIndexFeature.class ) )
+        {
+            RemoteIndexFeature rif = remoteRepository.getFeature( 
RemoteIndexFeature.class ).get( );
+            indexDirectory = getIndexPath(remoteRepository);
+            String remoteIndexUrl = calculateIndexRemoteUrl( 
remoteRepository.getLocation( ), rif );
+            try
+            {
+
+                return getIndexingContext( remoteRepository, contextKey, 
repoDir, indexDirectory, remoteIndexUrl );
+            }
+            catch ( IndexFormatTooOldException e )
+            {
+                // existing index with an old lucene format so we need to 
delete it!!!
+                // delete it first then recreate it.
+                log.warn( "the index of repository {} is too old we have to 
delete and recreate it", //
+                        remoteRepository.getId( ) );
+                org.apache.archiva.common.utils.FileUtils.deleteDirectory( 
indexDirectory );
+                return getIndexingContext( remoteRepository, contextKey, 
repoDir, indexDirectory, remoteIndexUrl );
+
+            }
+        }
+        else
+        {
+            throw new IOException( "No remote index defined" );
+        }
+    }
+
+    private IndexingContext getIndexingContext( Repository repository, String 
contextKey, Path repoDir, Path indexDirectory, String indexUrl ) throws 
IOException
+    {
+        return indexer.createIndexingContext( contextKey, repository.getId( ), 
repoDir.toFile( ), indexDirectory.toFile( ),
+                repository.getLocation( ) == null ? null : 
repository.getLocation( ).toString( ),
+                indexUrl,
+                true, false,
+                indexCreators );
+    }
+
+    private IndexingContext createManagedContext( ManagedRepository repository 
) throws IOException
+    {
+
+        IndexingContext context;
+        // take care first about repository location as can be relative
+        Path repositoryDirectory = repository.getLocalPath();
+
+        if ( !Files.exists( repositoryDirectory ) )
+        {
+            try
+            {
+                Files.createDirectories( repositoryDirectory );
+            }
+            catch ( IOException e )
+            {
+                log.error( "Could not create directory {}", 
repositoryDirectory );
+            }
+        }
+
+        Path indexDirectory = null;
+
+        if ( repository.supportsFeature( IndexCreationFeature.class ) )
+        {
+            indexDirectory = getIndexPath(repository);
+
+            String indexUrl = repositoryDirectory.toUri( ).toURL( 
).toExternalForm( );
+            try
+            {
+                context = getIndexingContext( repository, repository.getId( ), 
repositoryDirectory, indexDirectory, indexUrl );
+                context.setSearchable( repository.isScanned( ) );
+            }
+            catch ( IndexFormatTooOldException e )
+            {
+                // existing index with an old lucene format so we need to 
delete it!!!
+                // delete it first then recreate it.
+                log.warn( "the index of repository {} is too old we have to 
delete and recreate it", //
+                        repository.getId( ) );
+                org.apache.archiva.common.utils.FileUtils.deleteDirectory( 
indexDirectory );
+                context = getIndexingContext( repository, repository.getId( ), 
repositoryDirectory, indexDirectory, indexUrl );
+                context.setSearchable( repository.isScanned( ) );
+            }
+            return context;
+        }
+        else
+        {
+            throw new IOException( "No repository index defined" );
+        }
+    }
+
+    private String calculateIndexRemoteUrl( URI baseUri, RemoteIndexFeature 
rif )
+    {
+        if ( rif.getIndexUri( ) == null )
+        {
+            return baseUri.resolve( ".index" ).toString( );
+        }
+        else
+        {
+            return baseUri.resolve( rif.getIndexUri( ) ).toString( );
+        }
+    }
+
+    private static final class DownloadListener
+            implements TransferListener
+    {
+        private Logger log = LoggerFactory.getLogger( getClass( ) );
+
+        private String resourceName;
+
+        private long startTime;
+
+        private int totalLength = 0;
+
+        @Override
+        public void transferInitiated( TransferEvent transferEvent )
+        {
+            startTime = System.currentTimeMillis( );
+            resourceName = transferEvent.getResource( ).getName( );
+            log.debug( "initiate transfer of {}", resourceName );
+        }
+
+        @Override
+        public void transferStarted( TransferEvent transferEvent )
+        {
+            this.totalLength = 0;
+            resourceName = transferEvent.getResource( ).getName( );
+            log.info( "start transfer of {}", transferEvent.getResource( 
).getName( ) );
+        }
+
+        @Override
+        public void transferProgress( TransferEvent transferEvent, byte[] 
buffer, int length )
+        {
+            log.debug( "transfer of {} : {}/{}", transferEvent.getResource( 
).getName( ), buffer.length, length );
+            this.totalLength += length;
+        }
+
+        @Override
+        public void transferCompleted( TransferEvent transferEvent )
+        {
+            resourceName = transferEvent.getResource( ).getName( );
+            long endTime = System.currentTimeMillis( );
+            log.info( "end of transfer file {} {} kb: {}s", 
transferEvent.getResource( ).getName( ),
+                    this.totalLength / 1024, ( endTime - startTime ) / 1000 );
+        }
+
+        @Override
+        public void transferError( TransferEvent transferEvent )
+        {
+            log.info( "error of transfer file {}: {}", 
transferEvent.getResource( ).getName( ),
+                    transferEvent.getException( ).getMessage( ), 
transferEvent.getException( ) );
+        }
+
+        @Override
+        public void debug( String message )
+        {
+            log.debug( "transfer debug {}", message );
+        }
+    }
+
+    private static class WagonResourceFetcher
+            implements ResourceFetcher
+    {
+
+        Logger log;
+
+        Path tempIndexDirectory;
+
+        Wagon wagon;
+
+        RemoteRepository remoteRepository;
+
+        private WagonResourceFetcher( Logger log, Path tempIndexDirectory, 
Wagon wagon,
+                                      RemoteRepository remoteRepository )
+        {
+            this.log = log;
+            this.tempIndexDirectory = tempIndexDirectory;
+            this.wagon = wagon;
+            this.remoteRepository = remoteRepository;
+        }
+
+        @Override
+        public void connect( String id, String url )
+                throws IOException
+        {
+            //no op
+        }
+
+        @Override
+        public void disconnect( )
+                throws IOException
+        {
+            // no op
+        }
+
+        @Override
+        public InputStream retrieve(String name )
+                throws IOException, FileNotFoundException
+        {
+            try
+            {
+                log.info( "index update retrieve file, name:{}", name );
+                Path file = tempIndexDirectory.resolve( name );
+                Files.deleteIfExists( file );
+                file.toFile( ).deleteOnExit( );
+                wagon.get( addParameters( name, remoteRepository ), 
file.toFile( ) );
+                return Files.newInputStream( file );
+            }
+            catch ( AuthorizationException | TransferFailedException e )
+            {
+                throw new IOException( e.getMessage( ), e );
+            }
+            catch ( ResourceDoesNotExistException e )
+            {
+                FileNotFoundException fnfe = new FileNotFoundException( 
e.getMessage( ) );
+                fnfe.initCause( e );
+                throw fnfe;
+            }
+        }
+
+        // FIXME remove crappy copy/paste
+        protected String addParameters( String path, RemoteRepository 
remoteRepository )
+        {
+            if ( remoteRepository.getExtraParameters( ).isEmpty( ) )
+            {
+                return path;
+            }
+
+            boolean question = false;
+
+            StringBuilder res = new StringBuilder( path == null ? "" : path );
+
+            for ( Map.Entry<String, String> entry : 
remoteRepository.getExtraParameters( ).entrySet( ) )
+            {
+                if ( !question )
+                {
+                    res.append( '?' ).append( entry.getKey( ) ).append( '=' 
).append( entry.getValue( ) );
+                }
+            }
+
+            return res.toString( );
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..1b6a54b
--- /dev/null
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MavenIndexContextMock.java
@@ -0,0 +1,136 @@
+package org.apache.archiva.admin.mock;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.archiva.indexer.ArchivaIndexingContext;
+import org.apache.archiva.repository.Repository;
+import org.apache.maven.index.context.IndexingContext;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.sql.Date;
+import java.time.ZonedDateTime;
+import java.util.Set;
+
+/**
+ * Maven implementation of index context
+ */
+public class MavenIndexContextMock implements ArchivaIndexingContext {
+
+    private IndexingContext delegate;
+    private Repository repository;
+
+    MavenIndexContextMock(Repository repository, IndexingContext delegate) {
+        this.delegate = delegate;
+        this.repository = repository;
+
+    }
+
+    @Override
+    public String getId() {
+        return delegate.getId();
+    }
+
+    @Override
+    public Repository getRepository() {
+        return repository;
+    }
+
+    @Override
+    public URI getPath() {
+        return delegate.getIndexDirectoryFile().toURI();
+    }
+
+    @Override
+    public boolean isEmpty() throws IOException {
+        return 
Files.list(delegate.getIndexDirectoryFile().toPath()).count()==0;
+    }
+
+    @Override
+    public void commit() throws IOException {
+        delegate.commit();
+    }
+
+    @Override
+    public void rollback() throws IOException {
+        delegate.rollback();
+    }
+
+    @Override
+    public void optimize() throws IOException {
+        delegate.optimize();
+    }
+
+    @Override
+    public void close(boolean deleteFiles) throws IOException {
+        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
+        }
+    }
+
+    @Override
+    public void purge() throws IOException {
+        delegate.purge();
+    }
+
+    @Override
+    public boolean supports(Class<?> clazz) {
+        return IndexingContext.class.equals(clazz);
+    }
+
+    @Override
+    public <T> T getBaseContext(Class<T> clazz) throws 
UnsupportedOperationException {
+        if (IndexingContext.class.equals(clazz)) {
+            return (T) delegate;
+        } else {
+            throw new UnsupportedOperationException("The class "+clazz+" is 
not supported by the maven indexer");
+        }
+    }
+
+    @Override
+    public Set<String> getGroups() throws IOException {
+        return delegate.getAllGroups();
+    }
+
+    @Override
+    public void updateTimestamp(boolean save) throws IOException {
+        delegate.updateTimestamp(save);
+    }
+
+    @Override
+    public void updateTimestamp(boolean save, ZonedDateTime time) throws 
IOException {
+        delegate.updateTimestamp(save, Date.from(time.toInstant()));
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java
index c586f23..ed6e286 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java
@@ -24,6 +24,8 @@ import org.apache.archiva.admin.model.beans.RepositoryGroup;
 import org.apache.archiva.admin.model.group.RepositoryGroupAdmin;
 import org.apache.archiva.admin.repository.AbstractRepositoryAdminTest;
 import org.apache.archiva.metadata.model.facets.AuditEvent;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryRegistry;
 import org.junit.Test;
 
 import javax.inject.Inject;
@@ -39,12 +41,23 @@ public class RepositoryGroupAdminTest
     @Inject
     RepositoryGroupAdmin repositoryGroupAdmin;
 
+    @Inject
+    RepositoryRegistry repositoryRegistry;
+
     @Test
     public void addAndDeleteGroup()
         throws Exception
     {
         try
         {
+            Repository repo = repositoryRegistry.getRepository("test-new-one");
+            if (repo!=null) {
+                repositoryRegistry.removeRepository(repo);
+            }
+            repo = repositoryRegistry.getRepository("test-new-two");
+            if (repo!=null) {
+                repositoryRegistry.removeRepository(repo);
+            }
             ManagedRepository managedRepositoryOne =
                 getTestManagedRepository( "test-new-one", 
Paths.get(APPSERVER_BASE_PATH,"test-new-one" ).toString());
 
@@ -55,8 +68,10 @@ public class RepositoryGroupAdminTest
 
             managedRepositoryAdmin.addManagedRepository( managedRepositoryTwo, 
false, getFakeAuditInformation() );
 
+
             RepositoryGroup repositoryGroup =
                 new RepositoryGroup( "repo-group-one", Arrays.asList( 
"test-new-one", "test-new-two" ) );
+            // repositoryGroupAdmin.deleteRepositoryGroup("repo-group-one", 
null);
 
             mockAuditListener.clearEvents();
 
@@ -84,8 +99,8 @@ public class RepositoryGroupAdminTest
         finally
         {
             mockAuditListener.clearEvents();
-            managedRepositoryAdmin.deleteManagedRepository( "test-new-one", 
getFakeAuditInformation(), true );
-            managedRepositoryAdmin.deleteManagedRepository( "test-new-two", 
getFakeAuditInformation(), true );
+            
repositoryRegistry.removeRepository(repositoryRegistry.getManagedRepository("test-new-one"));
+            
repositoryRegistry.removeRepository(repositoryRegistry.getManagedRepository("test-new-two"));
         }
     }
 
@@ -202,8 +217,7 @@ public class RepositoryGroupAdminTest
         finally
         {
             mockAuditListener.clearEvents();
-
-            managedRepositoryAdmin.deleteManagedRepository( "test-new-two", 
getFakeAuditInformation(), true );
+            
repositoryRegistry.removeRepository(repositoryRegistry.getRepository("test-new-two"));
         }
     }
 
@@ -231,8 +245,8 @@ public class RepositoryGroupAdminTest
         finally
         {
             mockAuditListener.clearEvents();
-            managedRepositoryAdmin.deleteManagedRepository( "test-new-one", 
getFakeAuditInformation(), true );
-            managedRepositoryAdmin.deleteManagedRepository( "test-new-two", 
getFakeAuditInformation(), true );
+            
repositoryRegistry.removeRepository(repositoryRegistry.getRepository("test-new-one"));
+            
repositoryRegistry.removeRepository(repositoryRegistry.getRepository("test-new-two"));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/default-archiva.xml
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/default-archiva.xml
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/default-archiva.xml
index 7955798..36d467f 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/default-archiva.xml
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/default-archiva.xml
@@ -53,6 +53,7 @@
       <name>Central Repository</name>
       <url>https://repo.maven.apache.org/maven2</url>
       <layout>default</layout>
+      <indexDir>.index</indexDir>
     </remoteRepository>
   </remoteRepositories>
 

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java
 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java
index fb34eb2..63a8a92 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/ArchivaIndexManager.java
@@ -20,6 +20,7 @@ package org.apache.archiva.indexer;
  */
 
 import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryEventListener;
 import org.apache.archiva.repository.RepositoryType;
 
 import java.net.URI;
@@ -75,4 +76,23 @@ public interface ArchivaIndexManager {
      * @return the index context
      */
     ArchivaIndexingContext createContext(Repository repository) throws 
IndexCreationFailedException;
+
+    /**
+     * Reinitializes the index. E.g. remove the files and create a new empty 
index.
+     *
+     * @param context
+     * @return the new created index
+     */
+    ArchivaIndexingContext reset(ArchivaIndexingContext context) throws 
IndexUpdateFailedException;
+
+    /**
+     * Moves the context to a new directory. It's up to the implementation, if 
a new context is created
+     * or the context is moved only.
+     *
+     * @param context The current context
+     * @param repo The repository
+     * @return The new context
+     * @throws IndexCreationFailedException
+     */
+    ArchivaIndexingContext move(ArchivaIndexingContext context, Repository 
repo) throws IndexCreationFailedException;
 }

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/GenericIndexManager.java
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/GenericIndexManager.java
 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/GenericIndexManager.java
index d0f8034..8d8072e 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/GenericIndexManager.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/GenericIndexManager.java
@@ -20,6 +20,7 @@ package org.apache.archiva.indexer;
  */
 
 import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryEvent;
 import org.apache.archiva.repository.RepositoryType;
 import org.springframework.stereotype.Service;
 
@@ -63,4 +64,15 @@ public class GenericIndexManager implements 
ArchivaIndexManager {
     public ArchivaIndexingContext createContext(Repository repository) {
         return null;
     }
+
+    @Override
+    public ArchivaIndexingContext reset(ArchivaIndexingContext context) throws 
IndexUpdateFailedException {
+        return null;
+    }
+
+    @Override
+    public ArchivaIndexingContext move(ArchivaIndexingContext context, 
Repository repo) throws IndexCreationFailedException {
+        return null;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java
----------------------------------------------------------------------
diff --git 
a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java
 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java
index b275492..7b7dd8f 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java
@@ -19,6 +19,8 @@ package org.apache.archiva.repository;
  * under the License.
  */
 
+import org.apache.archiva.indexer.ArchivaIndexingContext;
+
 import java.net.URI;
 import java.util.Locale;
 
@@ -120,5 +122,11 @@ public interface EditableRepository extends Repository
      */
     void setLayout(String layout);
 
+    /**
+     * Sets the indexing context reference.
+     * @param context
+     */
+    void setIndexingContext(ArchivaIndexingContext context);
+
 
 }

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java
----------------------------------------------------------------------
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 fae5745..78a330a 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
@@ -22,6 +22,7 @@ package org.apache.archiva.repository;
 import org.apache.archiva.indexer.ArchivaIndexingContext;
 import org.apache.archiva.repository.features.RepositoryFeature;
 
+import java.io.IOException;
 import java.net.URI;
 import java.nio.file.Path;
 import java.util.List;
@@ -34,7 +35,7 @@ import java.util.Set;
  *
  * Created by Martin Stockhammer on 21.09.17.
  */
-public interface Repository {
+public interface Repository extends RepositoryEventHandler {
 
     /**
      * Return the identifier of the repository. Repository identifier should 
be unique at least
@@ -175,4 +176,10 @@ public interface Repository {
      * @throws UnsupportedOperationException
      */
     ArchivaIndexingContext getIndexingContext();
+
+    /**
+     * Closes all resources that are opened by this repository.
+     */
+    void close();
+
 }

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEvent.java
----------------------------------------------------------------------
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/RepositoryEvent.java
new file mode 100644
index 0000000..d8bdf95
--- /dev/null
+++ 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEvent.java
@@ -0,0 +1,69 @@
+package org.apache.archiva.repository;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.time.LocalDateTime;
+
+/**
+ * Repository event. Repository events are used for providing information 
about repository changes.
+ *
+ * @param <T>
+ */
+public class RepositoryEvent<T> {
+
+    final EventType type;
+    final String repo;
+    final T value;
+    final T oldValue;
+    final LocalDateTime instant;
+
+    public RepositoryEvent(EventType type, String repo, T oldValue, T value) {
+        this.type = type;
+        this.repo = repo;
+        this.value = value;
+        this.oldValue = oldValue;
+        this.instant = LocalDateTime.now();
+    }
+
+    public interface EventType {
+        String name();
+    }
+
+
+    EventType getType() {
+        return type;
+    };
+
+    String getRepositoryId() {
+        return repo;
+    };
+
+    T getValue() {
+        return value;
+    }
+
+    T getOldValue() {
+        return oldValue;
+    }
+
+    public LocalDateTime getInstant() {
+        return instant;
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
----------------------------------------------------------------------
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/RepositoryEventHandler.java
new file mode 100644
index 0000000..7432627
--- /dev/null
+++ 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventHandler.java
@@ -0,0 +1,32 @@
+package org.apache.archiva.repository;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Implementations of this interface are able to handle repository event 
listeners
+ */
+public interface RepositoryEventHandler {
+
+    void addListener(RepositoryEventListener listener);
+
+    void removeListener(RepositoryEventListener listener);
+
+    void clearListeners();
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventListener.java
----------------------------------------------------------------------
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/RepositoryEventListener.java
new file mode 100644
index 0000000..0234f34
--- /dev/null
+++ 
b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryEventListener.java
@@ -0,0 +1,28 @@
+package org.apache.archiva.repository;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Listener that accepts repository events.
+ */
+public interface RepositoryEventListener {
+
+    <T> void raise(RepositoryEvent<T> event);
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java
----------------------------------------------------------------------
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 a501514..4492b01 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
@@ -37,7 +37,7 @@ import java.util.Set;
  *
  *
  */
-public interface RepositoryProvider
+public interface RepositoryProvider extends RepositoryEventListener
 {
 
     /**

http://git-wip-us.apache.org/repos/asf/archiva/blob/c544376a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java
----------------------------------------------------------------------
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 c90c5bf..d63007a 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
@@ -26,26 +26,28 @@ import com.cronutils.parser.CronParser;
 import org.apache.archiva.common.utils.PathUtil;
 import org.apache.archiva.indexer.ArchivaIndexingContext;
 import org.apache.archiva.repository.features.RepositoryFeature;
+import org.apache.archiva.repository.features.StagingRepositoryFeature;
 import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
 import java.net.URI;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * Implementation of a repository with the necessary fields for a bare 
repository.
  * No features are provided. Capabilities and features must be implemented by 
concrete classes.
  *
  */
-public abstract class AbstractRepository implements EditableRepository
+public abstract class AbstractRepository implements EditableRepository, 
RepositoryEventListener
 {
 
+
+    Logger log = LoggerFactory.getLogger(AbstractRepository.class);
+
     private final RepositoryType type;
     private final String id;
     private Map<Locale, String> names = new HashMap<>(  );
@@ -60,10 +62,13 @@ public abstract class AbstractRepository implements 
EditableRepository
     String schedulingDefinition = "0 0 02 * * ?";
     private String layout = "default";
     public static final CronDefinition CRON_DEFINITION = 
CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
+    private List<RepositoryEventListener> listeners = new ArrayList<>();
+
 
     Map<Class<? extends RepositoryFeature<?>>, RepositoryFeature<?>> 
featureMap = new HashMap<>(  );
 
     protected Path repositoryBase;
+    private ArchivaIndexingContext indexingContext;
 
     public AbstractRepository(RepositoryType type, String id, String name, 
Path repositoryBase) {
         this.id = id;
@@ -129,7 +134,7 @@ public abstract class AbstractRepository implements 
EditableRepository
     @Override
     public Path getLocalPath() {
         Path localPath;
-        if (getLocation().getScheme()=="file" || 
StringUtils.isEmpty(getLocation().getScheme())) {
+        if (StringUtils.isEmpty(getLocation().getScheme()) || 
"file".equals(getLocation().getScheme()) ) {
             localPath = PathUtil.getPathFromUri(getLocation());
             if (localPath.isAbsolute()) {
                 return localPath;
@@ -259,8 +264,53 @@ public abstract class AbstractRepository implements 
EditableRepository
     }
 
     @Override
+    public void setIndexingContext(ArchivaIndexingContext context) {
+        this.indexingContext = context;
+    }
+
+    @Override
     public ArchivaIndexingContext getIndexingContext() {
-        // TODO: Implement
-        return null;
+        return indexingContext;
+    }
+
+    @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 (supportsFeature(StagingRepositoryFeature.class)) {
+            StagingRepositoryFeature sf = 
getFeature(StagingRepositoryFeature.class).get();
+            if (sf.getStagingRepository()!=null) {
+                sf.getStagingRepository().close();
+            }
+        }
+        clearListeners();
     }
+
+    @Override
+    public <T> void raise(RepositoryEvent<T> event) {
+        for(RepositoryEventListener listener : listeners) {
+            listener.raise(event);
+        }
+    }
+
+    public void addListener(RepositoryEventListener listener) {
+        if (!this.listeners.contains(listener)) {
+            this.listeners.add(listener);
+        }
+    }
+
+    public void removeListener(RepositoryEventListener listener) {
+        this.removeListener(listener);
+    }
+
+    public void clearListeners() {
+        this.listeners.clear();
+    }
+
 }

Reply via email to