diff --git a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/RecordFactory.java b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/RecordFactory.java index 3f828ffb..106eb137 100644 --- a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/RecordFactory.java +++ b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/RecordFactory.java @@ -41,7 +41,13 @@ public RecordFactory(RemoteRepositorySearchBackend backend) { /** * Creates {@link Record} on behalf of backend. Only {@code groupId} is mandatory, all the other values are optional (nullable). */ - public Record create(String groupId, String artifactId, String version, String classifier, String fileExtension) { + public Record create( + String groupId, + String artifactId, + String version, + String classifier, + String fileExtension, + Long lastUpdated) { requireNonNull(groupId); HashMap result = new HashMap<>(); mayPut(result, MAVEN.GROUP_ID, groupId); @@ -49,7 +55,7 @@ public Record create(String groupId, String artifactId, String version, String c mayPut(result, MAVEN.VERSION, version); mayPut(result, MAVEN.CLASSIFIER, classifier); mayPut(result, MAVEN.FILE_EXTENSION, fileExtension); - return new Record(backend.getBackendId(), backend.getRepositoryId(), null, null, result); + return new Record(backend.getBackendId(), backend.getRepositoryId(), null, lastUpdated, result); } private static void mayPut(Map result, Field fieldName, Object value) { diff --git a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/MavenCentralResponseExtractor.java b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/MavenCentralResponseExtractor.java index 132852fc..0e39f397 100644 --- a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/MavenCentralResponseExtractor.java +++ b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/MavenCentralResponseExtractor.java @@ -32,7 +32,7 @@ public class MavenCentralResponseExtractor extends ResponseExtractorSupport { /** * Extracts the "name" from {@code href} attribute. In case of Maven Central, the href - * attribute contains name in realative form as {@code "name/"} (followed by slash), if name denotes + * attribute contains name in relative form as {@code "name/"} (followed by slash), if name denotes * a directory. The trailing slash is removed by this method, if any. */ private String nameInHref(Element element) { @@ -52,7 +52,7 @@ public int populateG(Context context, Document document, RecordFactory recordFac for (Element element : contents.getElementsByTag("a")) { String name = nameInHref(element); if (accept(name)) { - page.add(recordFactory.create(context.getGroupId(), name, null, null, null)); + page.add(recordFactory.create(context.getGroupId(), name, null, null, null, null)); } } } diff --git a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/Nx2ResponseExtractor.java b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/Nx2ResponseExtractor.java index e44e4026..9e5eeb5d 100644 --- a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/Nx2ResponseExtractor.java +++ b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/Nx2ResponseExtractor.java @@ -51,7 +51,7 @@ public int populateG(Context context, Document document, RecordFactory recordFac for (Element element : elements) { String name = name(element); if (accept(name)) { - page.add(recordFactory.create(context.getGroupId(), name, null, null, null)); + page.add(recordFactory.create(context.getGroupId(), name, null, null, null, null)); } } return page.size(); diff --git a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/ResponseExtractorSupport.java b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/ResponseExtractorSupport.java index 9c717481..5006084e 100644 --- a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/ResponseExtractorSupport.java +++ b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/extractor/ResponseExtractorSupport.java @@ -71,7 +71,7 @@ public int populateGA(Context context, Document document, RecordFactory recordFa if (versions != null) { for (Element version : versions.getElementsByTag("version")) { page.add(recordFactory.create( - context.getGroupId(), context.getArtifactId(), version.text(), null, null)); + context.getGroupId(), context.getArtifactId(), version.text(), null, null, null)); } } } @@ -104,7 +104,12 @@ protected void populateGAVName(Context context, String name, RecordFactory recor ext = name; } page.add(recordFactory.create( - context.getGroupId(), context.getArtifactId(), context.getVersion(), classifier, ext)); + context.getGroupId(), + context.getArtifactId(), + context.getVersion(), + classifier, + ext, + null)); } } } diff --git a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/internal/RemoteRepositorySearchBackendImpl.java b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/internal/RemoteRepositorySearchBackendImpl.java index fffa3a3f..2938008b 100644 --- a/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/internal/RemoteRepositorySearchBackendImpl.java +++ b/search-backend-remoterepository/src/main/java/org/apache/maven/search/backend/remoterepository/internal/RemoteRepositorySearchBackendImpl.java @@ -23,8 +23,12 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Properties; @@ -189,12 +193,19 @@ public RemoteRepositorySearchResponse search(SearchRequest searchRequest) throws } } if (matches) { + String lastModifiedHeader = response.getHeaders().get("last-modified"); + Long lastModified = lastModifiedHeader == null + ? null + : ZonedDateTime.parse(lastModifiedHeader, RFC7231) + .toInstant() + .toEpochMilli(); page.add(recordFactory.create( context.getGroupId(), context.getArtifactId(), context.getVersion(), context.getClassifier(), - context.getFileExtension())); + context.getFileExtension(), + lastModified)); totalHits = 1; } } @@ -203,6 +214,10 @@ public RemoteRepositorySearchResponse search(SearchRequest searchRequest) throws return new RemoteRepositorySearchResponseImpl(searchRequest, totalHits, page, uri, document); } + private static final DateTimeFormatter RFC7231 = DateTimeFormatter.ofPattern( + "EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH) + .withZone(ZoneId.of("GMT")); + private static String readChecksum(InputStream inputStream) throws IOException { String checksum = ""; try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8), 512)) { diff --git a/search-backend-remoterepository/src/test/java/org/apache/maven/search/backend/remoterepository/internal/RemoteRepositorySearchBackendImplTest.java b/search-backend-remoterepository/src/test/java/org/apache/maven/search/backend/remoterepository/internal/RemoteRepositorySearchBackendImplTest.java index 3d7d08f7..5f156303 100644 --- a/search-backend-remoterepository/src/test/java/org/apache/maven/search/backend/remoterepository/internal/RemoteRepositorySearchBackendImplTest.java +++ b/search-backend-remoterepository/src/test/java/org/apache/maven/search/backend/remoterepository/internal/RemoteRepositorySearchBackendImplTest.java @@ -42,6 +42,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.notNullValue; /** * UT for 2 backends: Maven Central and RAO releases. This tests make use of the fact that RAO is used as "staging" @@ -172,6 +173,21 @@ public void gav() throws IOException { dumpPage(searchResponse); } + @Test + public void gave() throws IOException { + // LIST GAVCEs + SearchRequest searchRequest = new SearchRequest(BooleanQuery.and( + FieldQuery.fieldQuery(MAVEN.GROUP_ID, "org.apache.maven.plugins"), + FieldQuery.fieldQuery(MAVEN.ARTIFACT_ID, "maven-clean-plugin"), + FieldQuery.fieldQuery(MAVEN.VERSION, "3.1.0"), + FieldQuery.fieldQuery(MAVEN.FILE_EXTENSION, "jar"))); + RemoteRepositorySearchResponse searchResponse = backend.search(searchRequest); + assertThat(searchResponse.getTotalHits(), equalTo(1)); + assertThat(searchResponse.getPage().get(0).getLastUpdated(), notNullValue()); + System.out.println("TOTAL HITS: " + searchResponse.getTotalHits()); + dumpPage(searchResponse); + } + @Test public void gavWithTarGz() throws IOException { // LIST GAVCEs