Пример #1
0
 /// <summary>
 /// Performs the actual HTTP head request to check for the presence of a maven artifact with a
 /// given extension.
 /// </summary>
 /// <returns>true if the package exists, and false otherwise</returns>
 bool MavenPackageExists(MavenPackageID mavenGavParser, Uri feedUri, ICredentials feedCredentials, XmlDocument snapshotMetadata)
 {
     return(feedUri.ToString().TrimEnd('/')
            .Map(uri => uri + (snapshotMetadata == null ?
                               mavenGavParser.DefaultArtifactPath :
                               mavenGavParser.SnapshotArtifactPath(MetadataParser.GetLatestSnapshotRelease(
                                                                       snapshotMetadata,
                                                                       mavenGavParser.Packaging,
                                                                       mavenGavParser.Version))))
            .Map(uri =>
     {
         try
         {
             return WebRequest.Create(uri)
             .Tee(c => c.Method = "HEAD")
             .Tee(c => c.Credentials = feedCredentials)
             .GetResponse()
             .Map(response => response as HttpWebResponse)
             .Map(response => (int)response.StatusCode >= 200 && (int)response.StatusCode <= 299);
         }
         catch
         {
             return false;
         }
     }));
 }
Пример #2
0
        /// <summary>
        /// Performs the actual HTTP head request to check for the presence of a maven artifact with a
        /// given extension.
        /// </summary>
        /// <returns>true if the package exists, and false otherwise</returns>
        bool MavenPackageExists(MavenPackageID mavenGavParser, Uri feedUri, ICredentials feedCredentials,
                                XmlDocument snapshotMetadata)
        {
            var uri = feedUri.ToString().TrimEnd('/') + (snapshotMetadata == null
                          ? mavenGavParser.DefaultArtifactPath
                          : mavenGavParser.SnapshotArtifactPath(
                                                             GetLatestSnapshotRelease(
                                                                 snapshotMetadata,
                                                                 mavenGavParser.Packaging,
                                                                 mavenGavParser.Version)));

            try
            {
                var req = WebRequest.Create(uri);
                req.Method      = "HEAD";
                req.Credentials = feedCredentials;
                using (var response = (HttpWebResponse)req.GetResponse())
                {
                    return((int)response.StatusCode >= 200 && (int)response.StatusCode <= 299);
                }
            }
            catch
            {
                return(false);
            }
        }
        /// <summary>
        /// Actually download the maven file.
        /// </summary>
        /// <returns>The path to the downloaded file</returns>
        PackagePhysicalFileMetadata DownloadArtifact(
            MavenPackageID mavenGavFirst,
            string packageId,
            IVersion version,
            Uri feedUri,
            ICredentials feedCredentials,
            string cacheDirectory,
            int maxDownloadAttempts,
            TimeSpan downloadAttemptBackoff,
            XmlDocument?snapshotMetadata)
        {
            Guard.NotNull(mavenGavFirst, "mavenGavFirst can not be null");
            Guard.NotNullOrWhiteSpace(packageId, "packageId can not be null");
            Guard.NotNull(version, "version can not be null");
            Guard.NotNullOrWhiteSpace(cacheDirectory, "cacheDirectory can not be null");
            Guard.NotNull(feedUri, "feedUri can not be null");

            var localDownloadName = Path.Combine(cacheDirectory, PackageName.ToCachedFileName(packageId, version, "." + mavenGavFirst.Packaging));
            var downloadUrl       = feedUri.ToString().TrimEnd('/') +
                                    (snapshotMetadata == null
                    ? mavenGavFirst.DefaultArtifactPath
                    : mavenGavFirst.SnapshotArtifactPath(GetLatestSnapshotRelease(
                                                             snapshotMetadata,
                                                             mavenGavFirst.Packaging,
                                                             mavenGavFirst.Classifier,
                                                             mavenGavFirst.Version)));

            for (var retry = 0; retry < maxDownloadAttempts; ++retry)
            {
                try
                {
                    Log.Verbose($"Downloading Attempt {downloadUrl} TO {localDownloadName}");
                    using (var client = new WebClient
                    {
                        Credentials = feedCredentials
                    })
                    {
                        client.DownloadFile(downloadUrl, localDownloadName);
                        var packagePhysicalFileMetadata = PackagePhysicalFileMetadata.Build(localDownloadName);
                        return(packagePhysicalFileMetadata
                               ?? throw new CommandException($"Unable to retrieve metadata for package {packageId}, version {version}"));
                    }
                }
                catch (Exception ex)
                {
                    if ((retry + 1) == maxDownloadAttempts)
                    {
                        throw new MavenDownloadException("Failed to download the Maven artifact.\r\nLast Exception Message: " + ex.Message);
                    }
                    Thread.Sleep(downloadAttemptBackoff);
                }
            }

            throw new MavenDownloadException("Failed to download the Maven artifact");
        }
Пример #4
0
        /// <summary>
        /// Attempt to get the snapshot maven-metadata.xml file, which we will need to use to build up
        /// the filenames of snapshot versions.
        /// </summary>
        /// <returns>The snapshot maven-metadata.xml file if it exists, and a null result otherwise</returns>
        XmlDocument GetSnapshotMetadata(
            MavenPackageID mavenPackageID,
            Uri feedUri,
            ICredentials feedCredentials,
            int maxDownloadAttempts,
            TimeSpan downloadAttemptBackoff)
        {
            var url = feedUri.ToString().TrimEnd('/') + mavenPackageID.GroupVersionMetadataPath;

            for (var retry = 0; retry < maxDownloadAttempts; ++retry)
            {
                try
                {
                    var request = WebRequest.Create(url);
                    request.Credentials = feedCredentials;
                    using (var response = (HttpWebResponse)request.GetResponse())
                    {
                        if (response.IsSuccessStatusCode() || (int)response.StatusCode == 404)
                        {
                            using (var respStream = response.GetResponseStream())
                            {
                                var xmlDoc = new XmlDocument();
                                xmlDoc.Load(respStream);
                                return(xmlDoc);
                            }
                        }
                    }
                    return(null);
                }
                catch (WebException ex)
                {
                    if (ex.Response is HttpWebResponse response)
                    {
                        if ((int)(response.StatusCode) == 404)
                        {
                            return(null);
                        }
                    }

                    Thread.Sleep(downloadAttemptBackoff);
                }
                catch
                {
                    Thread.Sleep(downloadAttemptBackoff);
                }
            }

            throw new MavenDownloadException("Failed to download the Maven artifact");
        }
Пример #5
0
        /// <summary>
        /// Actually download the maven file.
        /// </summary>
        /// <returns>The path to the downloaded file</returns>
        string DownloadArtifact(
            MavenPackageID mavenGavFirst,
            string packageId,
            IVersion version,
            Uri feedUri,
            ICredentials feedCredentials,
            string cacheDirectory,
            int maxDownloadAttempts,
            TimeSpan downloadAttemptBackoff,
            XmlDocument snapshotMetadata)
        {
            Guard.NotNull(mavenGavFirst, "mavenGavFirst can not be null");
            Guard.NotNullOrWhiteSpace(packageId, "packageId can not be null");
            Guard.NotNull(version, "version can not be null");
            Guard.NotNullOrWhiteSpace(cacheDirectory, "cacheDirectory can not be null");
            Guard.NotNull(feedUri, "feedUri can not be null");

            for (var retry = 0; retry < maxDownloadAttempts; ++retry)
            {
                try
                {
                    return(GetFilePathToDownloadPackageTo(
                               cacheDirectory,
                               packageId,
                               version.ToString(),
                               mavenGavFirst.Packaging)
                           .Tee(path => feedUri.ToString().TrimEnd('/')
                                .Map(uri => uri + (snapshotMetadata == null ?
                                                   mavenGavFirst.DefaultArtifactPath :
                                                   mavenGavFirst.SnapshotArtifactPath(MetadataParser.GetLatestSnapshotRelease(
                                                                                          snapshotMetadata,
                                                                                          mavenGavFirst.Packaging,
                                                                                          mavenGavFirst.Version))))
                                .Map(uri => FunctionalExtensions.Using(
                                         () => new WebClient(),
                                         client => client
                                         .Tee(c => c.Credentials = feedCredentials)
                                         .Tee(c => c.DownloadFile(uri, path))))
                                ));
                }
                catch
                {
                    Thread.Sleep(downloadAttemptBackoff);
                }
            }

            throw new MavenDownloadException("Failed to download the Maven artifact");
        }
Пример #6
0
        /// <summary>
        /// Attempt to get the snapshot maven-metadata.xml file, which we will need to use to build up
        /// the filenames of snapshot versions.
        /// </summary>
        /// <returns>The snapshot maven-metadata.xml file if it exists, and a null result otherwise</returns>
        XmlDocument GetSnapshotMetadata(
            MavenPackageID mavenPackageID,
            Uri feedUri,
            ICredentials feedCredentials,
            int maxDownloadAttempts,
            TimeSpan downloadAttemptBackoff)
        {
            for (var retry = 0; retry < maxDownloadAttempts; ++retry)
            {
                try
                {
                    var metadataResponse = (feedUri.ToString().TrimEnd('/') + mavenPackageID.GroupVersionMetadataPath)
                                           .ToEnumerable()
                                           .Select(uri => WebRequest.Create(uri).Tee(request => request.Credentials = feedCredentials))
                                           .Select(request => request.GetResponse())
                                           .Select(response => response as HttpWebResponse)
                                           .First(response => response.IsSuccessStatusCode() || (int)response.StatusCode == 404);

                    if (metadataResponse.IsSuccessStatusCode())
                    {
                        return(FunctionalExtensions.Using(
                                   () => metadataResponse.GetResponseStream(),
                                   stream => new XmlDocument().Tee(doc => doc.Load(stream))));
                    }

                    return(null);
                }
                catch (WebException ex)
                {
                    if (ex.Response is HttpWebResponse response)
                    {
                        if ((int)(response.StatusCode) == 404)
                        {
                            return(null);
                        }
                    }

                    Thread.Sleep(downloadAttemptBackoff);
                }
                catch
                {
                    Thread.Sleep(downloadAttemptBackoff);
                }
            }

            throw new MavenDownloadException("Failed to download the Maven artifact");
        }
Пример #7
0
        /// <summary>
        /// Find the first artifact to respond to a HTTP head request. We use this to find the extension
        /// of the artifact that we are trying to download.
        /// </summary>
        /// <returns>The details of the first (and only) artifact to respond to a head request</returns>
        MavenPackageID FirstToRespond(
            MavenPackageID mavenPackageId,
            Uri feedUri,
            ICredentials feedCredentials,
            XmlDocument snapshotMetadata)
        {
            Guard.NotNull(mavenPackageId, "mavenPackageId can not be null");
            Guard.NotNull(feedUri, "feedUri can not be null");

            return(JarExtractor.EXTENSIONS
                   .AsParallel()
                   .Select(extension => new MavenPackageID(
                               mavenPackageId.Group,
                               mavenPackageId.Artifact,
                               mavenPackageId.Version,
                               Regex.Replace(extension, "^\\.", "")))
                   .FirstOrDefault(mavenGavParser => MavenPackageExists(mavenGavParser, feedUri, feedCredentials, snapshotMetadata))
                   ?? throw new MavenDownloadException("Failed to find the Maven artifact"));
        }
Пример #8
0
        /// <summary>
        /// Downloads the artifact from the Maven repo. This method first checks the repo for
        /// artifacts with all available extensions, as we have no indication what type of artifact
        /// (jar, war, zip etc) that we are attempting to download.
        /// </summary>
        /// <param name="packageId">The package id</param>
        /// <param name="version">The package version</param>
        /// <param name="feedUri">The maven repo uri</param>
        /// <param name="feedCredentials">The mavben repo credentials</param>
        /// <param name="cacheDirectory">The directory to download the file into</param>
        /// <param name="maxDownloadAttempts">How many times to try the download</param>
        /// <param name="downloadAttemptBackoff">How long to wait between attempts</param>
        /// <returns>The path to the downloaded artifact</returns>
        string DownloadPackage(
            string packageId,
            IVersion version,
            Uri feedUri,
            ICredentials feedCredentials,
            string cacheDirectory,
            int maxDownloadAttempts,
            TimeSpan downloadAttemptBackoff)
        {
            Guard.NotNullOrWhiteSpace(packageId, "packageId can not be null");
            Guard.NotNull(version, "version can not be null");
            Guard.NotNullOrWhiteSpace(cacheDirectory, "cacheDirectory can not be null");
            Guard.NotNull(feedUri, "feedUri can not be null");

            Log.Info("Downloading Maven package {0} {1} from feed: '{2}'", packageId, version, feedUri);
            Log.VerboseFormat("Downloaded package will be stored in: '{0}'", cacheDirectory);
            fileSystem.EnsureDirectoryExists(cacheDirectory);
            fileSystem.EnsureDiskHasEnoughFreeSpace(cacheDirectory);

            var mavenPackageId = new MavenPackageID(packageId, version);

            var snapshotMetadata = GetSnapshotMetadata(
                mavenPackageId,
                feedUri,
                feedCredentials,
                maxDownloadAttempts,
                downloadAttemptBackoff);

            return(FirstToRespond(mavenPackageId, feedUri, feedCredentials, snapshotMetadata)
                   .Tee(mavenGavFirst => Log.VerboseFormat("Found package {0} version {1}", packageId, version))
                   .Map(mavenGavFirst => DownloadArtifact(
                            mavenGavFirst,
                            packageId,
                            version,
                            feedUri,
                            feedCredentials,
                            cacheDirectory,
                            maxDownloadAttempts,
                            downloadAttemptBackoff,
                            snapshotMetadata)));
        }
Пример #9
0
        /// <summary>
        /// Downloads the artifact from the Maven repo. This method first checks the repo for
        /// artifacts with all available extensions, as we have no indication what type of artifact
        /// (jar, war, zip etc) that we are attempting to download.
        /// </summary>
        /// <param name="packageId">The package id</param>
        /// <param name="version">The package version</param>
        /// <param name="feedUri">The maven repo uri</param>
        /// <param name="feedCredentials">The mavben repo credentials</param>
        /// <param name="cacheDirectory">The directory to download the file into</param>
        /// <param name="maxDownloadAttempts">How many times to try the download</param>
        /// <param name="downloadAttemptBackoff">How long to wait between attempts</param>
        /// <returns>The path to the downloaded artifact</returns>
        PackagePhysicalFileMetadata DownloadPackage(
            string packageId,
            IVersion version,
            Uri feedUri,
            ICredentials feedCredentials,
            string cacheDirectory,
            int maxDownloadAttempts,
            TimeSpan downloadAttemptBackoff)
        {
            Guard.NotNullOrWhiteSpace(packageId, "packageId can not be null");
            Guard.NotNull(version, "version can not be null");
            Guard.NotNullOrWhiteSpace(cacheDirectory, "cacheDirectory can not be null");
            Guard.NotNull(feedUri, "feedUri can not be null");

            Log.Info("Downloading Maven package {0} v{1} from feed: '{2}'", packageId, version, feedUri);
            Log.VerboseFormat("Downloaded package will be stored in: '{0}'", cacheDirectory);
            freeSpaceChecker.EnsureDiskHasEnoughFreeSpace(cacheDirectory);

            var mavenPackageId = MavenPackageID.CreatePackageIdFromOctopusInput(packageId, version);

            var snapshotMetadata = GetSnapshotMetadata(mavenPackageId,
                                                       feedUri,
                                                       feedCredentials,
                                                       maxDownloadAttempts,
                                                       downloadAttemptBackoff);

            var found = FirstToRespond(mavenPackageId, feedUri, feedCredentials, snapshotMetadata);

            Log.VerboseFormat("Found package {0} v{1}", packageId, version);

            return(DownloadArtifact(
                       found,
                       packageId,
                       version,
                       feedUri,
                       feedCredentials,
                       cacheDirectory,
                       maxDownloadAttempts,
                       downloadAttemptBackoff,
                       snapshotMetadata));
        }
Пример #10
0
        /// <summary>
        /// Find the first artifact to respond to a HTTP head request. We use this to find the extension
        /// of the artifact that we are trying to download.
        /// </summary>
        /// <returns>The details of the first (and only) artifact to respond to a head request</returns>
        MavenPackageID FirstToRespond(
            MavenPackageID mavenPackageId,
            Uri feedUri,
            ICredentials feedCredentials,
            XmlDocument snapshotMetadata)
        {
            Guard.NotNull(mavenPackageId, "mavenPackageId can not be null");
            Guard.NotNull(feedUri, "feedUri can not be null");

            var errors     = new ConcurrentBag <string>();
            var fileChecks = JarPackageExtractor.SupportedExtensions
                             .Union(AdditionalExtensions)
                             // Either consider all supported extensions, or select only the specified extension
                             .Where(e => string.IsNullOrEmpty(mavenPackageId.Packaging) || e == "." + mavenPackageId.Packaging)
                             .Select(extension =>
            {
                var packageId = new MavenPackageID(
                    mavenPackageId.Group,
                    mavenPackageId.Artifact,
                    mavenPackageId.Version,
                    Regex.Replace(extension, "^\\.", ""),
                    mavenPackageId.Classifier);
                var result = MavenPackageExists(packageId, feedUri, feedCredentials, snapshotMetadata);
                errors.Add(result.ErrorMsg);
                return(new
                {
                    result.Found,
                    MavenPackageId = packageId
                });
            });


            var firstFound = fileChecks.FirstOrDefault(res => res.Found);

            if (firstFound != null)
            {
                return(firstFound.MavenPackageId);
            }

            throw new MavenDownloadException($"Failed to find the Maven artifact.\r\nReceived Error(s):\r\n{string.Join("\r\n", errors.Distinct().ToList())}");
        }
Пример #11
0
        /// <summary>
        /// Attempt to find a package id and version in the local cache
        /// </summary>
        /// <param name="packageId">The desired package id</param>
        /// <param name="version">The desired version</param>
        /// <param name="cacheDirectory">The location of cached files</param>
        /// <returns>The path to a cached version of the file, or null if none are found</returns>
        string SourceFromCache(
            string packageId,
            IVersion version,
            string cacheDirectory)
        {
            Guard.NotNullOrWhiteSpace(packageId, "packageId can not be null");
            Guard.NotNull(version, "version can not be null");
            Guard.NotNullOrWhiteSpace(cacheDirectory, "cacheDirectory can not be null");

            Log.VerboseFormat("Checking package cache for package {0} {1}", packageId, version.ToString());

            fileSystem.EnsureDirectoryExists(cacheDirectory);

            var filename = new MavenPackageID(packageId).FileSystemName;

            return(JarExtractor.EXTENSIONS
                   .Select(extension => filename + "*" + extension)
                   // Convert the search pattern to matching file paths
                   .SelectMany(searchPattern => fileSystem.EnumerateFilesRecursively(cacheDirectory, searchPattern))
                   // Filter out unparseable and unmatched results
                   .FirstOrDefault(file => FileMatchesDetails(file, packageId, version)));
        }
Пример #12
0
        /// <summary>
        /// Find the first artifact to respond to a HTTP head request. We use this to find the extension
        /// of the artifact that we are trying to download.
        /// </summary>
        /// <returns>The details of the first (and only) artifact to respond to a head request</returns>
        MavenPackageID FirstToRespond(
            MavenPackageID mavenPackageId,
            Uri feedUri,
            ICredentials feedCredentials,
            XmlDocument snapshotMetadata)
        {
            Guard.NotNull(mavenPackageId, "mavenPackageId can not be null");
            Guard.NotNull(feedUri, "feedUri can not be null");

            var errors     = new HashSet <string>();
            var fileChecks = JarExtractor.EXTENSIONS
                             .Union(AdditionalExtensions)
                             .AsParallel()
                             .Select(extension =>
            {
                var packageId = new MavenPackageID(mavenPackageId.Group, mavenPackageId.Artifact,
                                                   mavenPackageId.Version, Regex.Replace(extension, "^\\.", ""));
                var result = MavenPackageExists(packageId, feedUri, feedCredentials, snapshotMetadata);
                errors.Add(result.ErrorMsg);
                return(new
                {
                    result.Found,
                    MavenPackageId = packageId
                });
            });


            var firstFound = fileChecks.FirstOrDefault(res => res.Found);

            if (firstFound != null)
            {
                return(firstFound.MavenPackageId);
            }

            throw new MavenDownloadException($"Failed to find the Maven artifact.\r\nRecieved Error(s):\r\n{string.Join("\r\n", errors.ToList())}");
        }