diff --git a/.gitignore b/.gitignore index 1a7f8e40c35fa6ae9ee9417bc0ad4be042e064dc..20b4accefb1841348c8dccd176a48a06f9ee03f5 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ sources/ .DS_Store Mac-build/EasyInstaller-installer/ bin/ +.idea/ diff --git a/build.gradle b/build.gradle index d53a6f06ffc1a9e41754a2ca2d66fcef8f25770f..6fbb996064bf0d3a33cdf9853ddafc82e5a4614c 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,7 @@ dependencies { compile 'ch.qos.logback:logback-core:1.2.3' compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30' compile 'org.yaml:snakeyaml:1.26' + compile 'org.json:json:20240303' testCompile 'junit:junit:4.12' //compile 'org.slf4j:slf4j-log4j1:1.7.5' diff --git a/src/main/java/ecorp/easy/installer/tasks/DownloadTask.java b/src/main/java/ecorp/easy/installer/tasks/DownloadTask.java index 235dc2f1e215ccbebf3051056940614922995fdb..2d23b13409df5cb3429a750ee69bf9304f90d72d 100644 --- a/src/main/java/ecorp/easy/installer/tasks/DownloadTask.java +++ b/src/main/java/ecorp/easy/installer/tasks/DownloadTask.java @@ -26,6 +26,7 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -44,6 +45,10 @@ import java.util.Scanner; import javafx.concurrent.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javafx.util.Pair; +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONException; /** * this class verify the checksum of a file and download it @@ -73,7 +78,7 @@ public class DownloadTask extends Task{ final private ResourceBundle i18n; final private String targetUrl; - final private String fileName; + private String fileName; /** * COnstruction of the download task @@ -93,16 +98,15 @@ public class DownloadTask extends Task{ */ @Override protected Boolean call() throws Exception { + final String latestBuildFilename = fetchLatestBuildFilename(targetUrl); - //build local filePath - final String localFilePath = AppConstants.getSourcesFolderPath()+fileName; - - //Check if already exist and integrity - final String checksumFilePath = localFilePath+checkSumExtension; + final String localFilePath = AppConstants.getSourcesFolderPath() + fileName; + + final String checksumFilePath = localFilePath + checkSumExtension; if(isCancelled()) return false; - this.updateTitle("Downloading "+fileName+checkSumExtension); + this.updateTitle("Downloading " + latestBuildFilename + checkSumExtension); File checksumLmdFile = new File(AppConstants.getSourcesFolderPath()+"lmd."+fileName+checkSumExtension); @@ -123,7 +127,7 @@ public class DownloadTask extends Task{ if(isCancelled()) return false; - this.updateTitle("Downloading "+fileName); + this.updateTitle("Downloading "+ latestBuildFilename); final String tmpFilePath = AppConstants.getSourcesFolderPath()+"tmp."+fileName; @@ -177,7 +181,121 @@ public class DownloadTask extends Task{ fileWriter.write(lmd); } } - + + private String fetchLatestBuildFilename(String archiveUrl) { + // Extract codeName and codeType from the archiveUrl + Pair codeInfo = getCodeNameFromUrl(archiveUrl); + if (codeInfo == null) { + logger.error("Failed to fetch latest build filename: codeName or codeType is null."); + return null; + } + + String codeName = codeInfo.getKey(); + String codeType = codeInfo.getValue(); + + // Construct API URL using codeName and codeType + HttpURLConnection apiConnection = getApiConnection(codeName, codeType); + if (apiConnection == null) { + logger.error("Failed to fetch latest build filename: API connection is null."); + return null; + } + + try { + String latestBuildFilename = processApiResponse(apiConnection); + return latestBuildFilename; + } catch (IOException e) { + logger.error("Error processing API response: {}", e.getMessage()); + return null; + } finally { + if (apiConnection != null) { + apiConnection.disconnect(); + } + } + } + + private Pair getCodeNameFromUrl(String archiveUrl) { + try { + URL url = new URL(archiveUrl); + String[] urlParts = url.getPath().split("/"); + + for (int i = 0; i < urlParts.length; i++) { + if (urlParts[i].equals("stable") || urlParts[i].equals("dev")) { + if (i + 1 < urlParts.length) { + String codeType = urlParts[i]; + String codeName = urlParts[i + 1]; + logger.debug("CodeName extracted from URL: {}", codeName); + logger.debug("CodeType extracted from URL: {}", codeType); + return new Pair<>(codeName, codeType); + } + } + } + + logger.error("Invalid URL: Can't find codeName or codeType in: {}", archiveUrl); + } catch (MalformedURLException e) { + logger.error("Invalid URL: {}", e.getMessage()); + } + + return null; + } + + private HttpURLConnection getApiConnection(String codeName, String codeType) { + try { + URL apiUrl = new URL("https://ota.ecloud.global/api/v1/" + codeName + "/" + codeType + "?format=json"); + HttpURLConnection apiConnection = (HttpURLConnection) apiUrl.openConnection(); + apiConnection.setRequestMethod("GET"); + apiConnection.setRequestProperty("User-Agent", "null eOS v3"); + return apiConnection; + } catch (IOException e) { + logger.error("Error establishing API connection: {}", e.getMessage()); + } + + return null; + } + + private String processApiResponse(HttpURLConnection apiConnection) throws IOException { + try { + int responseCode = apiConnection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + String responseString = inputStreamToString(apiConnection.getInputStream()); + + // Try parsing the response as JSON + new JSONObject(responseString); + + JSONObject responseJson = new JSONObject(responseString); + JSONArray responses = responseJson.getJSONArray("response"); + + JSONObject responseObject = responses.getJSONObject(0); + String filename = responseObject.getString("filename"); + return filename; + } else { + logger.error("Error fetching latest build filename: HTTP response code {}", responseCode); + } + } catch (JSONException e) { + logger.warn("API response appears to be invalid JSON. Ignoring..."); + return null; + } catch (IOException e) { + logger.error("Error processing API response: {}", e.getMessage()); + } finally { + if (apiConnection != null) { + apiConnection.disconnect(); + } + } + + return null; + } + + private String inputStreamToString(InputStream inputStream) throws IOException { + StringBuilder responseString = new StringBuilder(); + Scanner scanner = new Scanner(inputStream); + while (scanner.hasNextLine()) { + responseString.append(scanner.nextLine()); + responseString.append("\n"); + } + scanner.close(); + + return responseString.toString(); + } + /** * Perform the downloading of the specified file * If a part is already downloaded, then the download resume from previous state diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 1db438fa82bdd7358cb948000500528c5599ec8b..b8e4c0105ae98620c33270ccb28de05c1c4fcf68 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -31,6 +31,7 @@ module ecorp.easy.installer { requires org.yaml.snakeyaml; requires org.slf4j; requires logback.classic; + requires org.json; opens ecorp.easy.installer to javafx.fxml; opens ecorp.easy.installer.controllers to javafx.fxml; opens ecorp.easy.installer.controllers.subcontrollers to javafx.fxml;