| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.io.IOException; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.util.List; |
| import java.util.concurrent.Semaphore; |
| import java.util.concurrent.atomic.LongAdder; |
| import java.util.stream.Stream; |
| import org.apache.maven.search.api.Record; |
| import org.apache.maven.search.api.SearchRequest; |
| import org.apache.maven.search.backend.smo.SmoSearchBackend; |
| import org.apache.maven.search.backend.smo.SmoSearchBackendFactory; |
| import org.apache.maven.artifact.versioning.ComparableVersion; |
| |
| import static org.apache.maven.search.api.MAVEN.ARTIFACT_ID; |
| import static org.apache.maven.search.api.MAVEN.CLASSIFIER; |
| import static org.apache.maven.search.api.MAVEN.GROUP_ID; |
| import static org.apache.maven.search.api.MAVEN.VERSION; |
| import static org.apache.maven.search.api.request.BooleanQuery.and; |
| import static org.apache.maven.search.api.request.FieldQuery.fieldQuery; |
| |
| /** |
| * Scans for binaries-list files and checks if newer versions of the declared dependencies exist. |
| * |
| * dependencies: |
| * <pre>org.apache.maven.indexer:search-backend-smo</pre> |
| * <pre>org.apache.maven:maven-artifact</pre> |
| * |
| * @author mbien |
| */ |
| public class BinariesListUpdates { |
| |
| private static final LongAdder updates = new LongAdder(); |
| private static final LongAdder checks = new LongAdder(); |
| private static final LongAdder skips = new LongAdder(); |
| |
| // java --class-path "lib/*" BinariesListUpdates.java /path/to/netbeans/project |
| public static void main(String[] args) throws IOException, InterruptedException { |
| |
| if (args.length != 1 || Files.notExists(Path.of(args[0]).resolve("README.md"))) { |
| throw new IllegalArgumentException("path to netbeans folder expected"); |
| } |
| |
| Path path = Path.of(args[0]); |
| try (Stream<Path> dependencyFiles = Files.find(path, 10, (p, a) -> p.getFileName().toString().equals("binaries-list")); |
| SmoSearchBackend backend = SmoSearchBackendFactory.createDefault()) { |
| dependencyFiles.sorted().forEach(p -> { |
| try { |
| checkDependencies(p, backend); |
| } catch (IOException | InterruptedException ex) { |
| throw new RuntimeException(ex); |
| } |
| }); |
| } |
| |
| System.out.println("checked " + checks.sum() + " dependencies, found " + updates.sum() + " updates, skipped " + skips.sum() + "." ); |
| } |
| |
| private static void checkDependencies(Path path, SmoSearchBackend backend) throws IOException, InterruptedException { |
| System.out.println(path); |
| try (Stream<String> lines = Files.lines(path).parallel()) { |
| |
| // 321C614F85F1DEA6BB08C1817C60D53B7F3552FD org.fusesource.jansi:jansi:2.4.0 |
| lines.filter(l -> !l.startsWith("#")) |
| .filter(l -> l.length() > 40 && l.charAt(40) == ' ') |
| .map(l -> l.substring(40+1)) |
| .forEach(l -> { |
| |
| String[] comp = l.split("\\:"); |
| if (comp.length == 3 || comp.length == 4) { |
| String gid = comp[0].strip(); |
| String aid = comp[1].strip(); |
| String version = comp[2].strip(); |
| String classifier = comp.length == 4 ? comp[3].strip() : null; |
| try { |
| String gac; |
| String latest; |
| if (classifier == null) { |
| latest = queryLatestVersion(backend, gid, aid); |
| gac = String.join(":", gid, aid); |
| } else { |
| latest = queryLatestVersion(backend, gid, aid, classifier.split("@")[0]); |
| gac = String.join(":", gid, aid, classifier); |
| } |
| if (latest != null && !version.equals(latest)) { |
| System.out.printf(" %-50s %s -> %s\n", gac, version, latest); |
| updates.increment(); |
| } |
| } catch (IOException | InterruptedException ex) { |
| throw new RuntimeException(ex); |
| } |
| } else { |
| System.out.println(" skip: '"+l+"'"); |
| skips.increment(); |
| } |
| checks.increment(); |
| }); |
| } |
| System.out.println(); |
| } |
| |
| private static String queryLatestVersion(SmoSearchBackend backend, String gid, String aid) throws IOException, InterruptedException { |
| return queryLatestVersion(backend, new SearchRequest(and(fieldQuery(GROUP_ID, gid), fieldQuery(ARTIFACT_ID, aid)))); |
| } |
| |
| private static String queryLatestVersion(SmoSearchBackend backend, String gid, String aid, String classifier) throws IOException, InterruptedException { |
| return queryLatestVersion(backend, new SearchRequest(and(fieldQuery(GROUP_ID, gid), fieldQuery(ARTIFACT_ID, aid), fieldQuery(CLASSIFIER, classifier)))); |
| } |
| |
| // reduce concurrency level if needed |
| private final static Semaphore requests = new Semaphore(4); |
| |
| private static String queryLatestVersion(SmoSearchBackend backend, SearchRequest request) throws IOException, InterruptedException { |
| requests.acquire(); |
| try { |
| List<Record> results; |
| try { |
| results = backend.search(request).getPage(); |
| } catch (IOException ex) { |
| System.out.println("received exception: '" + ex.getMessage() + "', retry in 10s"); |
| Thread.sleep(10_000); |
| try { |
| results = backend.search(request).getPage(); |
| } catch(IOException ignore) { |
| throw ex; |
| } |
| } |
| return results.stream() |
| .map(r -> r.getValue(VERSION)) |
| .filter(v -> !v.contains("alpha") && !v.contains("beta")) |
| .filter(v -> !v.contains("M") && !v.contains("m") && !v.contains("B") && !v.contains("b") && !v.contains("ea") && !v.contains("RC")) |
| .limit(5) |
| .max((v1, v2) -> new ComparableVersion(v1).compareTo(new ComparableVersion(v2))) |
| .orElse(null); |
| } finally { |
| requests.release(); |
| } |
| } |
| |
| } |