diff --git a/pkg/tools/base_tool.go b/pkg/tools/base_tool.go index ec449ec..ef91d8a 100644 --- a/pkg/tools/base_tool.go +++ b/pkg/tools/base_tool.go @@ -168,14 +168,7 @@ func (b *BaseTool) CreateInstallDir(version, distribution string) (string, error // Download performs a robust download with checksum verification func (b *BaseTool) Download(url, version string, cfg config.ToolConfig) (string, error) { // Always determine file extension from the download URL - fileExtension := ExtTarGz // fallback - if strings.HasSuffix(url, ExtZip) { - fileExtension = ExtZip - } else if strings.HasSuffix(url, ExtTarXz) { - fileExtension = ExtTarXz - } else if strings.HasSuffix(url, ExtTarGz) { - fileExtension = ExtTarGz - } + fileExtension := detectFileExtensionFromURL(url) // Create temporary file for download tmpFile, err := os.CreateTemp("", fmt.Sprintf("%s-*%s", b.toolName, fileExtension)) @@ -554,6 +547,49 @@ func (b *BaseTool) StandardVerify(version string, cfg config.ToolConfig, getPath return nil } +// detectFileExtensionFromURL detects the correct file extension from a download URL +// This handles both direct URLs and redirect URLs (like Java's Disco API) +func detectFileExtensionFromURL(downloadURL string) string { + // First try direct URL suffix detection + if strings.HasSuffix(downloadURL, ExtZip) { + return ExtZip + } + if strings.HasSuffix(downloadURL, ExtTarXz) { + return ExtTarXz + } + if strings.HasSuffix(downloadURL, ExtTarGz) { + return ExtTarGz + } + + // For redirect URLs (like Java Disco API), try to extract filename from URL path + // Example: https://github.com/adoptium/temurin22-binaries/releases/download/jdk-22.0.2%2B9/OpenJDK22U-jdk_x64_windows_hotspot_22.0.2_9.zip + if parsed, err := url.Parse(downloadURL); err == nil { + // Extract filename from URL path + pathParts := strings.Split(parsed.Path, "/") + if len(pathParts) > 0 { + filename := pathParts[len(pathParts)-1] + // URL decode the filename in case it's encoded + if decoded, err := url.QueryUnescape(filename); err == nil { + filename = decoded + } + + // Check file extension in the filename + if strings.HasSuffix(strings.ToLower(filename), ".zip") { + return ExtZip + } + if strings.HasSuffix(strings.ToLower(filename), ".tar.xz") { + return ExtTarXz + } + if strings.HasSuffix(strings.ToLower(filename), ".tar.gz") || strings.HasSuffix(strings.ToLower(filename), ".tgz") { + return ExtTarGz + } + } + } + + // Default fallback + return ExtTarGz +} + // StandardVerifyWithConfig provides standard verification using VerificationConfig func (b *BaseTool) StandardVerifyWithConfig(version string, cfg config.ToolConfig, verifyConfig VerificationConfig) error { return b.VerifyWithConfig(version, cfg, verifyConfig) diff --git a/pkg/tools/url_extension_test.go b/pkg/tools/url_extension_test.go index 8b713cc..aaebbdc 100644 --- a/pkg/tools/url_extension_test.go +++ b/pkg/tools/url_extension_test.go @@ -1,7 +1,6 @@ package tools import ( - "strings" "testing" ) @@ -39,19 +38,22 @@ func TestURLExtensionDetection(t *testing.T) { downloadURL: "https://example.com/tool-1.0.0.tar.xz", expectedExt: ".tar.xz", }, + { + name: "Java Windows ZIP (GitHub redirect)", + downloadURL: "https://github.com/adoptium/temurin22-binaries/releases/download/jdk-22.0.2%2B9/OpenJDK22U-jdk_x64_windows_hotspot_22.0.2_9.zip", + expectedExt: ".zip", + }, + { + name: "Java Linux tar.gz (GitHub redirect)", + downloadURL: "https://github.com/adoptium/temurin22-binaries/releases/download/jdk-22.0.2%2B9/OpenJDK22U-jdk_x64_linux_hotspot_22.0.2_9.tar.gz", + expectedExt: ".tar.gz", + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - // Simulate what happens in Download method - always detect from URL - fileExtension := ExtTarGz // fallback - if strings.HasSuffix(tc.downloadURL, ExtZip) { - fileExtension = ExtZip - } else if strings.HasSuffix(tc.downloadURL, ExtTarXz) { - fileExtension = ExtTarXz - } else if strings.HasSuffix(tc.downloadURL, ExtTarGz) { - fileExtension = ExtTarGz - } + // Use the actual detection function from Download method + fileExtension := detectFileExtensionFromURL(tc.downloadURL) if fileExtension != tc.expectedExt { t.Errorf("Expected extension %s for URL %s, got %s", tc.expectedExt, tc.downloadURL, fileExtension)