Java tutorial
package org.apache.archiva.indexer.maven; /* * 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.ArchivaIndexManager; import org.apache.archiva.indexer.ArchivaIndexingContext; import org.apache.archiva.indexer.IndexCreationFailedException; import org.apache.archiva.indexer.IndexUpdateFailedException; import org.apache.archiva.indexer.UnsupportedBaseContextException; 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.EditableRepository; import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.PasswordCredentials; import org.apache.archiva.repository.RemoteRepository; import org.apache.archiva.repository.Repository; import org.apache.archiva.repository.RepositoryType; import org.apache.archiva.repository.UnsupportedRepositoryTypeException; 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.ArtifactContext; import org.apache.maven.index.ArtifactContextProducer; import org.apache.maven.index.DefaultScannerListener; import org.apache.maven.index.Indexer; import org.apache.maven.index.IndexerEngine; import org.apache.maven.index.Scanner; import org.apache.maven.index.ScanningRequest; import org.apache.maven.index.ScanningResult; 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.IndexUpdater; import org.apache.maven.index.updater.ResourceFetcher; import org.apache.maven.index_shaded.lucene.index.IndexFormatTooOldException; import org.apache.maven.wagon.ConnectionException; import org.apache.maven.wagon.ResourceDoesNotExistException; import org.apache.maven.wagon.StreamWagon; import org.apache.maven.wagon.TransferFailedException; import org.apache.maven.wagon.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; /** * Maven implementation of index manager. * The index manager is a singleton, so we try to make sure, that index operations are not running * parallel by synchronizing on the index path. * A update operation waits for parallel running methods to finish before starting, but after a certain * time of retries a IndexUpdateFailedException is thrown. */ @Service("archivaIndexManager#maven") public class MavenIndexManager implements ArchivaIndexManager { private static final Logger log = LoggerFactory.getLogger(MavenIndexManager.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 IndexUpdater indexUpdater; @Inject private ArtifactContextProducer artifactContextProducer; public static final String DEFAULT_INDEXER_DIR = ".indexer"; public static final String DEFAULT_PACKED_INDEX_DIR = ".index"; 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); } MavenIndexContext context = new MavenIndexContext(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."); } } @Override public void updateLocalIndexPath(Repository repo) { if (repo.supportsFeature(IndexCreationFeature.class)) { IndexCreationFeature icf = repo.getFeature(IndexCreationFeature.class).get(); try { icf.setLocalIndexPath(getIndexPath(repo)); icf.setLocalPackedIndexPath(getPackedIndexPath(repo)); } catch (IOException e) { log.error("Could not set local index path for {}. New URI: {}", repo.getId(), icf.getIndexPath()); } } } 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(DEFAULT_INDEXER_DIR); } if (!Files.exists(indexDirectory)) { Files.createDirectories(indexDirectory); } return indexDirectory; } private Path getPackedIndexPath(Repository repo) throws IOException { IndexCreationFeature icf = repo.getFeature(IndexCreationFeature.class).get(); Path repoDir = repo.getLocalPath(); URI indexDir = icf.getPackedIndexPath(); 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(DEFAULT_PACKED_INDEX_DIR); } 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(DEFAULT_INDEXER_DIR).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(); } } }