Merge branch 'main' into ci
This commit is contained in:
		
						commit
						b045e98978
					
				| @ -8,6 +8,11 @@ version '1.0-SNAPSHOT' | ||||
| 
 | ||||
| mainClassName = 'fr.packageviewer.Main' | ||||
| 
 | ||||
| java { | ||||
|     sourceCompatibility = JavaVersion.VERSION_13 | ||||
|     targetCompatibility = JavaVersion.VERSION_13 | ||||
| } | ||||
| 
 | ||||
| jar{ | ||||
|     manifest { | ||||
|         attributes( | ||||
|  | ||||
| @ -1,118 +0,0 @@ | ||||
| package fr.packageviewer.ArchParser; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.net.URI; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import java.net.http.*; | ||||
| import org.json.*; | ||||
| 
 | ||||
| public class ArchParser { | ||||
| 
 | ||||
| /** | ||||
|  * Will return the String json of the package from the Arch Linux API | ||||
|  * @param packageName the package name to get the json from | ||||
|  * @return json of the package | ||||
|   */ | ||||
|     public String getPackageFromAPI(String packageName){ | ||||
|         // create a new http client | ||||
|         HttpClient client = HttpClient.newHttpClient(); | ||||
|         // and create its url | ||||
|         HttpRequest request = HttpRequest.newBuilder(URI.create("https://archlinux.org/packages/search/json/?name="+packageName)).build(); | ||||
|         // send its url and return the string given | ||||
|         try { | ||||
|             return client.send(request, HttpResponse.BodyHandlers.ofString()).body(); | ||||
|         } catch (IOException|InterruptedException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         // if there's an error, return an empty string | ||||
|         return ""; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Search for a package and return a list of packages | ||||
|  * @param packageName the package name to search | ||||
|  * @return | ||||
|  */ | ||||
|     public List<SearchedPackage> searchPackage(String packageName){ | ||||
|         HttpClient client = HttpClient.newHttpClient(); | ||||
|         HttpRequest request = HttpRequest.newBuilder() | ||||
|                 .uri(URI.create("https://archlinux.org/packages/search/json/?q="+packageName)) | ||||
|                 .build(); | ||||
| 
 | ||||
|         HttpResponse<String> response; | ||||
|         try{ | ||||
|             response = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||
|         }catch(IOException|InterruptedException e){ | ||||
|             e.printStackTrace(); | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         JSONObject json = new JSONObject(response.body()); | ||||
| 
 | ||||
|         List<SearchedPackage> searchedPackagesList = new ArrayList<>(); | ||||
| 
 | ||||
|         // iterate for every package in the list | ||||
|         for (Object searchResultObj : json.getJSONArray("results")) { | ||||
|             // convert object into String | ||||
|             JSONObject searchResultJson = (JSONObject) searchResultObj; | ||||
|             // add package into to list | ||||
|             searchedPackagesList.add(new SearchedPackage( | ||||
|                 searchResultJson.getString("pkgname"), | ||||
|                 searchResultJson.getString("pkgver"), | ||||
|                 searchResultJson.getString("repo"), | ||||
|                 searchResultJson.getString("pkgdesc") | ||||
|             )); | ||||
|         } | ||||
| 
 | ||||
|         return searchedPackagesList; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Will generate a dependencies tree of depth 'depth' given the package name | ||||
|      * @param packageName the package name to search | ||||
|      * @param depth depth to search dependencies | ||||
|      * @return new Package | ||||
|      */ | ||||
|     public Package getPackageTree(String packageName, int depth){ | ||||
|         String name, version, repo, description; | ||||
|         List<Package> deps = new ArrayList<>(); | ||||
| 
 | ||||
|         // parse the json | ||||
|         JSONObject json = new JSONObject(getPackageFromAPI(packageName)); | ||||
| 
 | ||||
|         JSONArray resultsArrayJson = json.getJSONArray("results"); | ||||
|         if(resultsArrayJson.length()==0){ | ||||
|             // unknown package, probably an abstract dependency | ||||
|             return null; | ||||
|         } | ||||
|         JSONObject resultJson = json.getJSONArray("results").getJSONObject(0); | ||||
| 
 | ||||
|         // get infos except dependencies | ||||
|         name = resultJson.getString("pkgname"); | ||||
|         version = resultJson.getString("pkgver"); | ||||
|         repo = resultJson.getString("repo"); | ||||
|         description = resultJson.getString("pkgdesc"); | ||||
| 
 | ||||
|         // if we're at the maximum depth, return the package without its dependencies | ||||
|         if(depth==0){ | ||||
|             return new Package(name, version, repo, description, Collections.emptyList()); | ||||
|         } else { | ||||
|             // iterate for every package in the list | ||||
|             for (Object depPackageNameObj : resultJson.getJSONArray("depends")) { | ||||
|                 // convert object into String | ||||
|                 String depPackageName = (String) depPackageNameObj; | ||||
|                 // add package into Package List | ||||
|                 deps.add(getPackageTree(depPackageName, depth - 1)); | ||||
|             } | ||||
| 
 | ||||
|             // TODO this doesn't seem clean | ||||
|             return new Package(name, version, repo, description, deps); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| package fr.packageviewer.ArchParser; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class Package extends SearchedPackage { | ||||
|     List<Package> deps; | ||||
| 
 | ||||
|     public Package(String name, String version, String repo, String description, List<Package> deps) { | ||||
|         super(name, version, repo, description); | ||||
|         this.deps = deps; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,16 +0,0 @@ | ||||
| package fr.packageviewer.ArchParser; | ||||
| 
 | ||||
| public class SearchedPackage { | ||||
|     String name; | ||||
|     String version; | ||||
|     String repo; | ||||
|     String description; | ||||
| 
 | ||||
|     public SearchedPackage(String name, String version, String repo, String desciption) { | ||||
|         this.name = name; | ||||
|         this.version = version; | ||||
|         this.repo = repo; | ||||
|         this.description = desciption; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,153 @@ | ||||
| package fr.packageviewer.distribution; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.net.URI; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import java.net.http.*; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| import java.util.concurrent.ExecutionException; | ||||
| import java.util.logging.Logger; | ||||
| 
 | ||||
| import fr.packageviewer.LoggerManager; | ||||
| import fr.packageviewer.pack.Package; | ||||
| import fr.packageviewer.pack.SearchedPackage; | ||||
| import org.json.*; | ||||
| 
 | ||||
| public class ArchDistribution implements Distribution { | ||||
| 
 | ||||
|     private static final Logger logger = LoggerManager.getLogger("ArchParser"); | ||||
| 
 | ||||
| /** | ||||
|  * Will return the String json of the package from the Arch Linux API | ||||
|  * @param packageName the package name to get the json from | ||||
|  * @return json of the package | ||||
|   */ | ||||
|     public CompletableFuture<HttpResponse<String>> getPackageFromAPI(String packageName) { | ||||
|         // create a new http client | ||||
|         HttpClient client = HttpClient.newHttpClient(); | ||||
|         // and create its url | ||||
|         HttpRequest request = HttpRequest.newBuilder(URI.create("https://archlinux.org/packages/search/json/?name="+packageName)).build(); | ||||
|         // send its url and return the string given | ||||
|         return client.sendAsync(request, HttpResponse.BodyHandlers.ofString()); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Search for a package and return a list of packages | ||||
|  * @param packageName the package name to search | ||||
|  * @return | ||||
|  */ | ||||
|     public List<SearchedPackage> searchPackage(String packageName){ | ||||
|         HttpClient client = HttpClient.newHttpClient(); | ||||
|         HttpRequest request = HttpRequest.newBuilder() | ||||
|                 .uri(URI.create("https://archlinux.org/packages/search/json/?q="+packageName)) | ||||
|                 .build(); | ||||
| 
 | ||||
|         HttpResponse<String> response; | ||||
|         try{ | ||||
|             response = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||
|         }catch(IOException|InterruptedException e){ | ||||
|             e.printStackTrace(); | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         JSONObject json = new JSONObject(response.body()); | ||||
| 
 | ||||
|         List<SearchedPackage> searchedPackagesList = new ArrayList<>(); | ||||
| 
 | ||||
|         // iterate for every package in the list | ||||
|         for (Object searchResultObj : json.getJSONArray("results")) { | ||||
|             // convert object into String | ||||
|             JSONObject searchResultJson = (JSONObject) searchResultObj; | ||||
|             // add package into to list | ||||
|             searchedPackagesList.add(new SearchedPackage( | ||||
|                 searchResultJson.getString("pkgname"), | ||||
|                 searchResultJson.getString("pkgver"), | ||||
|                 searchResultJson.getString("repo"), | ||||
|                 searchResultJson.getString("pkgdesc") | ||||
|             )); | ||||
|         } | ||||
| 
 | ||||
|         return searchedPackagesList; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Will generate a dependencies tree of depth 'depth' given the package name | ||||
|      * @param packageName the package name to search | ||||
|      * @param depth depth to search dependencies | ||||
|      * @return new Package | ||||
|      */ | ||||
|     public CompletableFuture<Package> getPackageTree(String packageName, int depth) { | ||||
| 
 | ||||
|         // parse the json | ||||
|         var futurePackage = new CompletableFuture<Package>(); | ||||
| 
 | ||||
|         logger.fine("Querying package %s from API... (depth=%s)".formatted(packageName, depth)); | ||||
| 
 | ||||
|         CompletableFuture<HttpResponse<String>> futureRequest; | ||||
|         try{ | ||||
|             futureRequest = getPackageFromAPI(packageName); | ||||
|         }catch(IllegalArgumentException e){ | ||||
|             logger.warning("Caught exception for package %s :\n%s".formatted(packageName, e)); | ||||
|             return CompletableFuture.completedFuture(null); | ||||
|         } | ||||
|         futureRequest.thenAccept(result->{ | ||||
|             List<Package> deps = new ArrayList<>(); | ||||
|             String name, version, repo, description; | ||||
| 
 | ||||
|             JSONObject json = new JSONObject(result.body()); | ||||
| 
 | ||||
|             JSONArray resultsArrayJson = json.getJSONArray("results"); | ||||
|             if(resultsArrayJson.length()==0){ | ||||
|                 // unknown package, probably an abstract dependency | ||||
|                 logger.fine("Completing callback INVALID for package %s (depth=%s)".formatted(packageName, depth)); | ||||
|                 futurePackage.complete(null); | ||||
|             } | ||||
|             JSONObject resultJson = json.getJSONArray("results").getJSONObject(0); | ||||
| 
 | ||||
|             // get infos except dependencies | ||||
|             name = resultJson.getString("pkgname"); | ||||
|             version = resultJson.getString("pkgver"); | ||||
|             repo = resultJson.getString("repo"); | ||||
|             description = resultJson.getString("pkgdesc"); | ||||
| 
 | ||||
|             // if we're at the maximum depth, return the package without its dependencies | ||||
|             if(depth==0){ | ||||
|                 logger.fine("Completing callback NODEP for package %s (depth=%s)".formatted(packageName, depth)); | ||||
|                 futurePackage.complete(new Package(name, version, repo, description, Collections.emptyList())); | ||||
|             } else { | ||||
|                 // iterate for every package in the list | ||||
|                 List<CompletableFuture<Package>> futureDeps = new ArrayList<>(); | ||||
|                 for (Object depPackageNameObj : resultJson.getJSONArray("depends")) { | ||||
|                     // convert object into String | ||||
|                     String depPackageName = (String) depPackageNameObj; | ||||
|                     // add package into Package List | ||||
|                     futureDeps.add(getPackageTree(depPackageName, depth - 1)); | ||||
|                 } | ||||
|                 for(CompletableFuture<Package> future : futureDeps){ | ||||
|                     try { | ||||
|                         deps.add(future.get()); | ||||
|                     } catch (InterruptedException | ExecutionException e) { | ||||
|                         throw new RuntimeException(e); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // TODO this doesn't seem clean | ||||
|                 logger.fine("Completing callback DEPS for package %s (depth=%s)".formatted(packageName, depth)); | ||||
|                 futurePackage.complete(new Package(name, version, repo, description, deps)); | ||||
|             } | ||||
|         }).exceptionally((e2->{ | ||||
|             logger.warning("Error while fetching package %s (depth=%s) from the API : \n%s".formatted(packageName, depth, e2)); | ||||
|             e2.printStackTrace(); | ||||
|             futurePackage.complete(null); | ||||
|             return null; | ||||
|         })); | ||||
| 
 | ||||
|         return futurePackage; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,12 @@ | ||||
| package fr.packageviewer.distribution; | ||||
| 
 | ||||
| import fr.packageviewer.pack.Package; | ||||
| import fr.packageviewer.pack.SearchedPackage; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| 
 | ||||
| public interface Distribution { | ||||
| 	List<SearchedPackage> searchPackage(String packageName); | ||||
| 	CompletableFuture<Package> getPackageTree(String packageName, int depth); | ||||
| } | ||||
							
								
								
									
										21
									
								
								src/main/java/fr/packageviewer/pack/Package.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/main/java/fr/packageviewer/pack/Package.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| package fr.packageviewer.pack; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class Package extends SearchedPackage { | ||||
|     private final List<Package> deps; | ||||
| 
 | ||||
|     public List<Package> getDeps() { | ||||
|         return deps; | ||||
|     } | ||||
| 
 | ||||
|     public Package(String name, String version, String repo, String description, List<Package> deps) { | ||||
|         super(name, version, repo, description); | ||||
|         this.deps = deps; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "Package{SearchedPackage{%s},deps=%s}".formatted(super.toString(), deps); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										36
									
								
								src/main/java/fr/packageviewer/pack/SearchedPackage.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/main/java/fr/packageviewer/pack/SearchedPackage.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| package fr.packageviewer.pack; | ||||
| 
 | ||||
| public class SearchedPackage { | ||||
|     private final String name; | ||||
|     private final String version; | ||||
|     private final String repo; | ||||
|     private final String description; | ||||
| 
 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public String getVersion() { | ||||
|         return version; | ||||
|     } | ||||
| 
 | ||||
|     public String getRepo() { | ||||
|         return repo; | ||||
|     } | ||||
| 
 | ||||
|     public String getDescription() { | ||||
|         return description; | ||||
|     } | ||||
| 
 | ||||
|     public SearchedPackage(String name, String version, String repo, String desciption) { | ||||
|         this.name = name; | ||||
|         this.version = version; | ||||
|         this.repo = repo; | ||||
|         this.description = desciption; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "SearchedPackage{name=%s,version=%s,repo=%s,description=%s}".formatted(name, version, repo, description); | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user