diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c6954936de..9249d1ae8c 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -56,7 +56,7 @@ The parameter `allowConflictingDependencies` was removed from the target platfor #### Choosable HTTP transports Tycho uses a custom P2 transport to download items from updatesites, previously URLConnection was used for this but now the Java HTTP 11 Client is the new default because it supports HTTP/2 now. -To use the old URLConnection one can pass `-Dtycho.p2.transport.type=JavaUrl` to the build. +To use the old URLConnection one can pass `-Dtycho.p2.httptransport.type=JavaUrl` to the build. Valid values are: - `JavaUrl` - uses URLConnection to retrieve files diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/DefaultHttpCacheConfig.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/DefaultTransportCacheConfig.java similarity index 93% rename from p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/DefaultHttpCacheConfig.java rename to p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/DefaultTransportCacheConfig.java index fcb2dcf977..f2889fdb6f 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/DefaultHttpCacheConfig.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/DefaultTransportCacheConfig.java @@ -22,8 +22,8 @@ import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -@Component(role = HttpCacheConfig.class) -public class DefaultHttpCacheConfig implements HttpCacheConfig, Initializable { +@Component(role = TransportCacheConfig.class) +public class DefaultTransportCacheConfig implements TransportCacheConfig, Initializable { private boolean offline; private boolean update; diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/FileTransportProtocolHandler.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/FileTransportProtocolHandler.java new file mode 100644 index 0000000000..6abc31bd28 --- /dev/null +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/FileTransportProtocolHandler.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2022 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.p2maven.transport; + +import java.io.File; +import java.io.IOException; +import java.net.URI; + +import org.codehaus.plexus.component.annotations.Component; + +@Component(role = TransportProtocolHandler.class, hint = "file") +public class FileTransportProtocolHandler implements TransportProtocolHandler { + + @Override + public long getLastModified(URI uri) throws IOException { + return getFile(uri).lastModified(); + } + + + @Override + public File getFile(URI remoteFile) throws IOException { + try { + return new File(remoteFile); + } catch (IllegalArgumentException e) { + throw new IOException("Not a valid file URI: " + remoteFile); + } + } + +} diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpCache.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpCache.java index 565c1db3cb..409186ee1d 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpCache.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpCache.java @@ -29,6 +29,4 @@ public interface HttpCache { */ CacheEntry getCacheEntry(URI uri, Logger logger) throws FileNotFoundException; - HttpCacheConfig getCacheConfig(); - } \ No newline at end of file diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpTransportProtocolHandler.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpTransportProtocolHandler.java new file mode 100644 index 0000000000..456a491956 --- /dev/null +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpTransportProtocolHandler.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2022 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.p2maven.transport; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.Map; +import java.util.Objects; + +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.codehaus.plexus.logging.Logger; + +@Component(role = TransportProtocolHandler.class, hint = "http") +public class HttpTransportProtocolHandler implements TransportProtocolHandler { + + static final String TRANSPORT_TYPE = System.getProperty("tycho.p2.httptransport.type", + Java11HttpTransportFactory.HINT); + + @Requirement + Map transportFactoryMap; + @Requirement + HttpCache httpCache; + + @Requirement + Logger logger; + + private HttpTransportFactory getTransportFactory() { + return Objects.requireNonNull(transportFactoryMap.get(TRANSPORT_TYPE), "Invalid transport configuration"); + } + + @Override + public long getLastModified(URI uri) throws IOException { + return httpCache.getCacheEntry(uri, logger).getLastModified(getTransportFactory()); + } + + @Override + public File getFile(URI remoteFile) throws IOException { + return httpCache.getCacheEntry(remoteFile, logger).getCacheFile(getTransportFactory()); + } + +} diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpsTransportProtocolHandler.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpsTransportProtocolHandler.java new file mode 100644 index 0000000000..279ab8f274 --- /dev/null +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpsTransportProtocolHandler.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2022 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.p2maven.transport; + +import org.codehaus.plexus.component.annotations.Component; + +@Component(role = TransportProtocolHandler.class, hint = "https") +public class HttpsTransportProtocolHandler extends HttpTransportProtocolHandler { + +} diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/SharedHttpCacheStorage.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/SharedHttpCacheStorage.java index dd0dd79ebb..a0a12783bb 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/SharedHttpCacheStorage.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/SharedHttpCacheStorage.java @@ -61,7 +61,7 @@ public class SharedHttpCacheStorage implements HttpCache { private static final int MAX_IN_MEMORY = 1000; @Requirement - HttpCacheConfig cacheConfig; + TransportCacheConfig cacheConfig; private final Map entryCache; @@ -80,11 +80,6 @@ protected boolean removeEldestEntry(final Map.Entry eldest) { }; } - @Override - public HttpCacheConfig getCacheConfig() { - return cacheConfig; - } - /** * Fetches the cache entry for this URI * diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpCacheConfig.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TransportCacheConfig.java similarity index 94% rename from p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpCacheConfig.java rename to p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TransportCacheConfig.java index c3d1dffa57..fa59627ad2 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/HttpCacheConfig.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TransportCacheConfig.java @@ -14,7 +14,7 @@ import java.io.File; -public interface HttpCacheConfig { +public interface TransportCacheConfig { boolean isOffline(); diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TransportProtocolHandler.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TransportProtocolHandler.java new file mode 100644 index 0000000000..dede30f13c --- /dev/null +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TransportProtocolHandler.java @@ -0,0 +1,13 @@ +package org.eclipse.tycho.p2maven.transport; + +import java.io.File; +import java.io.IOException; +import java.net.URI; + +public interface TransportProtocolHandler { + + long getLastModified(URI uri) throws IOException; + + File getFile(URI remoteFile) throws IOException; + +} diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransport.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransport.java index dfefba8b69..b88d3d0d00 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransport.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransport.java @@ -22,7 +22,6 @@ import java.net.URLConnection; import java.text.NumberFormat; import java.util.Map; -import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -49,8 +48,7 @@ public class TychoRepositoryTransport extends org.eclipse.equinox.internal.p2.re implements IAgentServiceFactory { private static final int MAX_DOWNLOAD_THREADS = Integer.getInteger("tycho.p2.transport.max-download-threads", 4); - static final String TRANSPORT_TYPE = System.getProperty("tycho.p2.transport.type", - Java11HttpTransportFactory.HINT); + private static final boolean DEBUG_REQUESTS = Boolean.getBoolean("tycho.p2.transport.debug"); private static final Executor DOWNLOAD_EXECUTOR = Executors.newFixedThreadPool(MAX_DOWNLOAD_THREADS, new ThreadFactory() { @@ -67,13 +65,14 @@ public Thread newThread(Runnable r) { private NumberFormat numberFormat = NumberFormat.getNumberInstance(); - @Requirement - Map transportFactoryMap; - @Requirement Logger logger; + @Requirement - HttpCache httpCache; + TransportCacheConfig cacheConfig; + + @Requirement(role = TransportProtocolHandler.class) + Map transportProtocolHandlers; private LongAdder requests = new LongAdder(); private LongAdder indexRequests = new LongAdder(); @@ -94,7 +93,7 @@ public IStatus download(URI toDownload, OutputStream target, long startPos, IPro @Override public IStatus download(URI toDownload, OutputStream target, IProgressMonitor monitor) { String id = "p2"; // TODO we might compute the id from the IRepositoryIdManager based on the URI? - if (httpCache.getCacheConfig().isInteractive()) { + if (cacheConfig.isInteractive()) { logger.info("Downloading from " + id + ": " + toDownload); } try { @@ -102,7 +101,7 @@ public IStatus download(URI toDownload, OutputStream target, IProgressMonitor mo "Download of " + toDownload); IOUtils.copy(stream(toDownload, monitor), statusOutputStream); DownloadStatus downloadStatus = statusOutputStream.getStatus(); - if (httpCache.getCacheConfig().isInteractive()) { + if (cacheConfig.isInteractive()) { logger.info( "Downloaded from " + id + ": " + toDownload + " (" + FileUtils.byteCountToDisplaySize(downloadStatus.getFileSize()) @@ -138,13 +137,16 @@ public synchronized InputStream stream(URI toDownload, IProgressMonitor monitor) indexRequests.increment(); } try { - File cachedFile = getCachedFile(toDownload); - if (cachedFile != null) { - if (DEBUG_REQUESTS) { - logger.debug(" --> routed through http-cache ..."); - } - return new FileInputStream(cachedFile); - } + TransportProtocolHandler handler = getHandler(toDownload); + if (handler != null) { + File cachedFile = handler.getFile(toDownload); + if (cachedFile != null) { + if (DEBUG_REQUESTS) { + logger.debug(" --> routed through handler " + handler.getClass().getSimpleName() + " ..."); + } + return new FileInputStream(cachedFile); + } + } return toDownload.toURL().openStream(); } catch (FileNotFoundException e) { if (DEBUG_REQUESTS) { @@ -165,53 +167,42 @@ public synchronized InputStream stream(URI toDownload, IProgressMonitor monitor) } } + TransportProtocolHandler getHandler(URI uri) { + String scheme = uri.getScheme(); + if (scheme != null) { + String lc = scheme.toLowerCase(); + TransportProtocolHandler handler = transportProtocolHandlers.get(lc); + if (handler != null) { + return handler; + } + } + return null; + } + @Override public long getLastModified(URI toDownload, IProgressMonitor monitor) throws CoreException, FileNotFoundException, AuthenticationFailedException { - //TODO P2 cache manager relies on this method to throw an exception to work correctly - try { - if (isHttp(toDownload)) { - return httpCache.getCacheEntry(toDownload, logger) - .getLastModified(getTransportFactory()); - } - URLConnection connection = toDownload.toURL().openConnection(); - long lastModified = connection.getLastModified(); - connection.getInputStream().close(); - return lastModified; - } catch (FileNotFoundException e) { - throw e; - } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, TychoRepositoryTransport.class.getName(), - "download from " + toDownload + " failed", e)); - } + try { + TransportProtocolHandler handler = getHandler(toDownload); + if (handler != null) { + return handler.getLastModified(toDownload); + } + URLConnection connection = toDownload.toURL().openConnection(); + long lastModified = connection.getLastModified(); + connection.getInputStream().close(); + return lastModified; + } catch (FileNotFoundException e) { + throw e; + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, TychoRepositoryTransport.class.getName(), + "download from " + toDownload + " failed", e)); + } } - - private HttpTransportFactory getTransportFactory() { - return Objects.requireNonNull(transportFactoryMap.get(TRANSPORT_TYPE), "Invalid transport configuration"); - } - @Override public Object createService(IProvisioningAgent agent) { return this; } - public HttpCache getHttpCache() { - return httpCache; - } - - public File getCachedFile(URI remoteFile) throws IOException { - - if (isHttp(remoteFile)) { - return httpCache.getCacheEntry(remoteFile, logger).getCacheFile(getTransportFactory()); - } - return null; - } - - public static boolean isHttp(URI remoteFile) { - String scheme = remoteFile.getScheme(); - return scheme != null && scheme.toLowerCase().startsWith("http"); - } - public static Executor getDownloadExecutor() { return DOWNLOAD_EXECUTOR; } diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransportAgentFactory.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransportAgentFactory.java index 3d59f2e13f..61f066a72f 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransportAgentFactory.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransportAgentFactory.java @@ -12,6 +12,8 @@ *******************************************************************************/ package org.eclipse.tycho.p2maven.transport; +import java.util.concurrent.atomic.AtomicBoolean; + import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.Logger; @@ -30,24 +32,26 @@ public class TychoRepositoryTransportAgentFactory implements IAgentServiceFactor private Logger logger; @Requirement - HttpCache cache; + TransportCacheConfig config; @Requirement(hint = "tycho") org.eclipse.equinox.internal.p2.repository.Transport repositoryTransport; + private AtomicBoolean infoPrinted = new AtomicBoolean(); + @Override public Object createService(IProvisioningAgent agent) { - HttpCacheConfig config = cache.getCacheConfig(); - logger.info("### Using TychoRepositoryTransport for remote P2 access ###"); - logger.info(" Cache location: " + config.getCacheLocation()); - logger.info(" Transport mode: " + (config.isOffline() ? "offline" : "online")); - logger.info(" Transport type: " + TychoRepositoryTransport.TRANSPORT_TYPE); - logger.info(" Update mode: " + (config.isUpdate() ? "forced" : "cache first")); - logger.info(" Minimum cache duration: " + SharedHttpCacheStorage.MIN_CACHE_PERIOD + " minutes"); - logger.info( - " (you can configure this with -Dtycho.p2.transport.min-cache-minutes=)"); - + if (infoPrinted.compareAndSet(false, true)) { + logger.info("### Using TychoRepositoryTransport for remote P2 access ###"); + logger.info(" Cache location: " + config.getCacheLocation()); + logger.info(" Transport mode: " + (config.isOffline() ? "offline" : "online")); + logger.info(" Http Transport type: " + HttpTransportProtocolHandler.TRANSPORT_TYPE); + logger.info(" Update mode: " + (config.isUpdate() ? "forced" : "cache first")); + logger.info(" Minimum cache duration: " + SharedHttpCacheStorage.MIN_CACHE_PERIOD + " minutes"); + logger.info( + " (you can configure this with -Dtycho.p2.transport.min-cache-minutes=)"); + } return repositoryTransport; } diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransportCacheManager.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransportCacheManager.java index 0248976f21..a36cb8b40f 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransportCacheManager.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/transport/TychoRepositoryTransportCacheManager.java @@ -42,31 +42,36 @@ public TychoRepositoryTransportCacheManager(TychoRepositoryTransport transport, @Override public File createCache(URI repositoryLocation, String prefix, IProgressMonitor monitor) throws IOException, ProvisionException { - if (TychoRepositoryTransport.isHttp(repositoryLocation)) { - for (String extension : EXTENSIONS) { - URI fileLocation = URIUtil.append(repositoryLocation, prefix + extension); - try { - File cachedFile = transport.getCachedFile(fileLocation); - if (cachedFile != null) { - return cachedFile; - } - } catch (FileNotFoundException e) { - continue; - } - } - throw new FileNotFoundException( - "Not found any of " + EXTENSIONS + " for " + repositoryLocation + " with prefix " + prefix); - } + TransportProtocolHandler handler = transport.getHandler(repositoryLocation); + if (handler != null) { + for (String extension : EXTENSIONS) { + URI fileLocation = URIUtil.append(repositoryLocation, prefix + extension); + try { + File cachedFile = handler.getFile(fileLocation); + if (cachedFile != null) { + return cachedFile; + } + } catch (FileNotFoundException e) { + continue; + } + } + throw new FileNotFoundException( + "Not found any of " + EXTENSIONS + " for " + repositoryLocation + " with prefix " + prefix); + + } return super.createCache(repositoryLocation, prefix, monitor); } @Override public File createCacheFromFile(URI remoteFile, IProgressMonitor monitor) throws ProvisionException, IOException { - File cachedFile = transport.getCachedFile(remoteFile); - if (cachedFile != null) { - //no need to cache this twice ... - return cachedFile; - } + TransportProtocolHandler handler = transport.getHandler(remoteFile); + if (handler != null) { + File cachedFile = handler.getFile(remoteFile); + if (cachedFile != null) { + // no need to cache this twice ... + return cachedFile; + } + } return super.createCacheFromFile(remoteFile, monitor); }