Skip to content

Commit 0bd06d2

Browse files
committed
Merge branch 'feature/checker' into development
2 parents a2f97db + 4c372be commit 0bd06d2

35 files changed

+111
-135
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
### Client
88

9-
The `client` module contains an implementation of a Webmention client which can be used to notify a Webmention endpoint server.
9+
The `client` module contains an implementation of a Webmention client which can be used to notify a Webmention endpoint
10+
server.
1011

1112
```java
1213
import dev.rilling.webmention4j.client.WebmentionClient;
@@ -38,7 +39,8 @@ public final class WebmentionClientExample {
3839

3940
### Server
4041

41-
The `server` module contains an implementation of a Webmention endpoint servlet which can be used to listen to Webmentions and process them.
42+
The `server` module contains an implementation of a Webmention endpoint servlet which can be used to listen to
43+
Webmentions and process them.
4244

4345
```java
4446
import dev.rilling.webmention4j.common.Webmention;
@@ -59,7 +61,8 @@ The `example` module contains example CLI applications that can be executed.
5961

6062
#### Client CLI Example
6163

62-
Webmention client CLI sending Webmention for `http://localhost:8080/somethingelse` being mentioned on `http://localhost:8080/blogpost`:
64+
Webmention client CLI sending Webmention for `http://localhost:8080/somethingelse` being mentioned
65+
on `http://localhost:8080/blogpost`:
6366

6467
```shell
6568
java -cp webmention4j-example-*.jar dev.rilling.webmention4j.example.WebmentionClientExample --source https://example.com/somethingelse --target https://example.org/blogpost

client/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
<artifactId>slf4j-api</artifactId>
2525
</dependency>
2626
<dependency>
27-
<groupId>org.jetbrains</groupId>
28-
<artifactId>annotations</artifactId>
27+
<groupId>org.checkerframework</groupId>
28+
<artifactId>checker-qual</artifactId>
2929
</dependency>
3030

3131
<dependency>

client/src/main/java/dev/rilling/webmention4j/client/WebmentionClient.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
1212
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
1313
import org.apache.hc.client5.http.impl.classic.HttpClients;
14-
import org.jetbrains.annotations.NotNull;
1514

1615
import java.io.IOException;
1716
import java.net.URI;
@@ -41,14 +40,14 @@ public WebmentionClient() {
4140
*
4241
* @param config Custom configuration.
4342
*/
44-
public WebmentionClient(@NotNull Config config) {
43+
public WebmentionClient(Config config) {
4544
this(new Config(config), WebmentionClient::createDefaultHttpClient, new EndpointService(), new EndpointDiscoveryService(new HeaderLinkParser(), new HtmlLinkParser()));
4645
}
4746

48-
WebmentionClient(@NotNull Config config,
49-
@NotNull HttpClientFactory httpClientFactory,
50-
@NotNull EndpointService endpointService,
51-
@NotNull EndpointDiscoveryService endpointDiscoveryService) {
47+
WebmentionClient(Config config,
48+
HttpClientFactory httpClientFactory,
49+
EndpointService endpointService,
50+
EndpointDiscoveryService endpointDiscoveryService) {
5251
this.config = config;
5352
this.endpointDiscoveryService = endpointDiscoveryService;
5453
this.endpointService = endpointService;
@@ -61,7 +60,7 @@ public WebmentionClient(@NotNull Config config) {
6160
* @param target Page to check endpoint of.
6261
* @throws IOException if I/O fails.
6362
*/
64-
public boolean supportsWebmention(@NotNull URI target) throws IOException {
63+
public boolean supportsWebmention(URI target) throws IOException {
6564
try (CloseableHttpClient httpClient = httpClientFactory.create(true)) {
6665
return endpointDiscoveryService.discoverEndpoint(httpClient, target).isPresent();
6766
}
@@ -74,8 +73,8 @@ public boolean supportsWebmention(@NotNull URI target) throws IOException {
7473
* @return URL to use to monitor request status, if supported by the endpoint.
7574
* @throws IOException if I/O fails.
7675
*/
77-
@NotNull
78-
public Optional<URI> sendWebmention(@NotNull Webmention webmention) throws IOException {
76+
77+
public Optional<URI> sendWebmention(Webmention webmention) throws IOException {
7978
URI endpoint;
8079
try (CloseableHttpClient httpClient = httpClientFactory.create(true)) {
8180
// Spec: '3.1.2 Sender discovers receiver Webmention endpoint'

client/src/main/java/dev/rilling/webmention4j/client/internal/EndpointDiscoveryService.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import org.apache.hc.core5.http.ClassicHttpRequest;
1010
import org.apache.hc.core5.http.ClassicHttpResponse;
1111
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
12-
import org.jetbrains.annotations.NotNull;
1312
import org.slf4j.Logger;
1413
import org.slf4j.LoggerFactory;
1514

@@ -23,17 +22,17 @@
2322
public final class EndpointDiscoveryService {
2423
private static final Logger LOGGER = LoggerFactory.getLogger(EndpointDiscoveryService.class);
2524

26-
private final @NotNull HeaderLinkParser headerLinkParser;
27-
private final @NotNull HtmlLinkParser htmlLinkParser;
25+
private final HeaderLinkParser headerLinkParser;
26+
private final HtmlLinkParser htmlLinkParser;
2827

2928
/**
3029
* Constructor.
3130
*
3231
* @param headerLinkParser A {@link HeaderLinkParser}.
3332
* @param htmlLinkParser A {@link HtmlLinkParser}.
3433
*/
35-
public EndpointDiscoveryService(@NotNull HeaderLinkParser headerLinkParser,
36-
@NotNull HtmlLinkParser htmlLinkParser) {
34+
public EndpointDiscoveryService(HeaderLinkParser headerLinkParser,
35+
HtmlLinkParser htmlLinkParser) {
3736
this.headerLinkParser = headerLinkParser;
3837
this.htmlLinkParser = htmlLinkParser;
3938
}
@@ -49,8 +48,7 @@ public EndpointDiscoveryService(@NotNull HeaderLinkParser headerLinkParser,
4948
* @throws IOException if I/O fails.
5049
*/
5150
// Spec: https://www.w3.org/TR/webmention/#h-sender-discovers-receiver-webmention-endpoint
52-
@NotNull
53-
public Optional<URI> discoverEndpoint(@NotNull CloseableHttpClient httpClient, @NotNull URI target)
51+
public Optional<URI> discoverEndpoint(CloseableHttpClient httpClient, URI target)
5452
throws IOException {
5553
// We could make a HEAD request beforehand, but this is not required.
5654

client/src/main/java/dev/rilling/webmention4j/client/internal/EndpointService.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import org.apache.hc.core5.http.HttpStatus;
88
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
99
import org.apache.hc.core5.http.message.BasicNameValuePair;
10-
import org.jetbrains.annotations.NotNull;
1110
import org.slf4j.Logger;
1211
import org.slf4j.LoggerFactory;
1312

@@ -34,10 +33,9 @@ public final class EndpointService {
3433
* @throws IOException if I/O fails.
3534
*/
3635
// Spec: https://www.w3.org/TR/webmention/#h-sender-notifies-receiver
37-
@NotNull
38-
public Optional<URI> notifyEndpoint(@NotNull CloseableHttpClient httpClient,
39-
@NotNull URI endpoint,
40-
@NotNull Webmention webmention) throws IOException {
36+
public Optional<URI> notifyEndpoint(CloseableHttpClient httpClient,
37+
URI endpoint,
38+
Webmention webmention) throws IOException {
4139
/*
4240
* Spec:
4341
* 'The sender MUST post x-www-form-urlencoded source and target parameters to the Webmention endpoint,

client/src/main/java/dev/rilling/webmention4j/client/internal/link/HeaderLinkParser.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import org.apache.hc.core5.http.ClassicHttpResponse;
44
import org.apache.hc.core5.http.HttpHeaders;
5-
import org.jetbrains.annotations.NotNull;
65

76
import java.io.IOException;
87
import java.net.URI;
@@ -14,7 +13,7 @@
1413
*/
1514
public final class HeaderLinkParser implements LinkParser {
1615

17-
public @NotNull List<Link> parse(@NotNull URI location, @NotNull ClassicHttpResponse response)
16+
public List<Link> parse(URI location, ClassicHttpResponse response)
1817
throws IOException {
1918
try {
2019
return Arrays.stream(response.getHeaders(HttpHeaders.LINK))

client/src/main/java/dev/rilling/webmention4j/client/internal/link/HtmlLinkParser.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import dev.rilling.webmention4j.common.internal.HtmlUtils;
44
import org.apache.hc.core5.http.ClassicHttpResponse;
5-
import org.jetbrains.annotations.NotNull;
65
import org.jsoup.nodes.Document;
76
import org.jsoup.nodes.Element;
87
import org.jsoup.select.Elements;
@@ -21,7 +20,7 @@ public final class HtmlLinkParser implements LinkParser {
2120

2221
private static final LinkElementEvaluator LINK_ELEMENT_EVALUATOR = new LinkElementEvaluator();
2322

24-
public @NotNull List<Link> parse(@NotNull URI location, @NotNull ClassicHttpResponse response)
23+
public List<Link> parse(URI location, ClassicHttpResponse response)
2524
throws IOException {
2625
if (!HtmlUtils.isHtml(response) || response.getEntity() == null) {
2726
return List.of();
@@ -48,7 +47,7 @@ private static class LinkElementEvaluator extends Evaluator {
4847
private static final Set<String> LINK_ELEMENT_NAMES = Set.of("link", "a");
4948

5049
@Override
51-
public boolean matches(@NotNull Element root, @NotNull Element element) {
50+
public boolean matches(Element root, Element element) {
5251
return LINK_ELEMENT_NAMES.contains(element.normalName()) && element.hasAttr("href") &&
5352
element.hasAttr("rel");
5453
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package dev.rilling.webmention4j.client.internal.link;
22

3-
import org.jetbrains.annotations.NotNull;
4-
53
import java.net.URI;
64
import java.util.Set;
75

@@ -11,6 +9,6 @@
119
* <p>
1210
* The URL is always in the resolved, absolute form.
1311
*/
14-
public record Link(@NotNull URI uri, @NotNull Set<String> rel) {
12+
public record Link(URI uri, Set<String> rel) {
1513

1614
}

client/src/main/java/dev/rilling/webmention4j/client/internal/link/LinkParser.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package dev.rilling.webmention4j.client.internal.link;
22

33
import org.apache.hc.core5.http.ClassicHttpResponse;
4-
import org.jetbrains.annotations.NotNull;
54

65
import java.io.IOException;
76
import java.net.URI;
@@ -22,6 +21,6 @@ public interface LinkParser {
2221
* @return A list of link elements, ordered by their position in the response.
2322
* @throws IOException if parsing fails.
2423
*/
25-
@NotNull List<Link> parse(@NotNull URI location, @NotNull ClassicHttpResponse response) throws IOException;
24+
List<Link> parse(URI location, ClassicHttpResponse response) throws IOException;
2625

2726
}

client/src/main/java/dev/rilling/webmention4j/client/internal/link/LinkUtils.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import org.apache.hc.client5.http.utils.URIUtils;
44
import org.apache.hc.core5.net.URIBuilder;
5-
import org.jetbrains.annotations.NotNull;
6-
import org.jetbrains.annotations.Nullable;
5+
import org.checkerframework.checker.nullness.qual.Nullable;
76

87
import java.io.Serial;
98
import java.net.URI;
@@ -28,7 +27,7 @@ private LinkUtils() {
2827
* @throws LinkException if parsing fails
2928
*/
3029
// https://datatracker.ietf.org/doc/html/rfc8288#appendix-A.1
31-
public static @NotNull Link fromElement(@NotNull URI baseUri, @NotNull String href, @Nullable String rel) {
30+
public static Link fromElement(URI baseUri, String href, @Nullable String rel) {
3231
return createLink(baseUri, href, rel);
3332
}
3433

@@ -41,8 +40,8 @@ private LinkUtils() {
4140
* @throws LinkException if parsing fails
4241
*/
4342
// https://datatracker.ietf.org/doc/html/rfc8288#section-3
44-
public static @NotNull Link fromHeaderValue(
45-
@NotNull URI baseUri, @NotNull String headerValue) {
43+
public static Link fromHeaderValue(
44+
URI baseUri, String headerValue) {
4645
String normalizedHeaderValue = headerValue.trim();
4746

4847
if (!normalizedHeaderValue.startsWith("<")) {
@@ -60,7 +59,7 @@ private LinkUtils() {
6059
return createLink(baseUri, uri, rel);
6160
}
6261

63-
private static @Nullable String findRelParam(@NotNull String params) {
62+
private static @Nullable String findRelParam(String params) {
6463
final StringTokenizer st = new StringTokenizer(params, ";=\"", true);
6564
while (st.hasMoreTokens()) {
6665
checkToken(st, ";");
@@ -80,7 +79,7 @@ private LinkUtils() {
8079
return null;
8180
}
8281

83-
private static void checkToken(@NotNull StringTokenizer st, @NotNull String expected) {
82+
private static void checkToken(StringTokenizer st, String expected) {
8483
String token;
8584
do {
8685
token = st.nextToken().trim();
@@ -91,7 +90,7 @@ private static void checkToken(@NotNull StringTokenizer st, @NotNull String expe
9190
}
9291
}
9392

94-
private static @NotNull String nextNonEmptyToken(@NotNull StringTokenizer st) {
93+
private static String nextNonEmptyToken(StringTokenizer st) {
9594
String token;
9695
do {
9796
token = st.nextToken().trim();
@@ -101,7 +100,7 @@ private static void checkToken(@NotNull StringTokenizer st, @NotNull String expe
101100
}
102101

103102

104-
static @NotNull Link createLink(@NotNull URI baseUri, @NotNull String uri, @Nullable String rel) {
103+
static Link createLink(URI baseUri, String uri, @Nullable String rel) {
105104
Set<String> rels = rel != null ? Set.of(REL_SEPARATOR.split(rel)) : Set.of();
106105

107106
URI linkUri;
@@ -114,7 +113,7 @@ private static void checkToken(@NotNull StringTokenizer st, @NotNull String expe
114113
return new Link(linkUri, rels);
115114
}
116115

117-
private static URI resolveLinkUri(@NotNull URI baseUri, @NotNull String uri) throws URISyntaxException {
116+
private static URI resolveLinkUri(URI baseUri, String uri) throws URISyntaxException {
118117
URIBuilder uriBuilder = new URIBuilder(uri);
119118
if (uriBuilder.isAbsolute()) {
120119
return uriBuilder.optimize().build();

client/src/test/java/dev/rilling/webmention4j/client/WebmentionClientSpecIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class WebmentionClientSpecIT {
2727
@Test
2828
@DisplayName(
2929
"'During the discovery step, if the sender discovers the endpoint is localhost or a loopback IP address (127.0.0.0/8)," +
30-
" it SHOULD NOT send the Webmention to that endpoint.'")
30+
" it SHOULD NOT send the Webmention to that endpoint.'")
3131
void sendWebmentionLocalhost() {
3232
Config config = new Config();
3333
config.setAllowLocalhostEndpoint(false);
@@ -49,7 +49,7 @@ void sendWebmentionLocalhost() {
4949
@Test
5050
@DisplayName(
5151
"'During the discovery step, if the sender discovers the endpoint is localhost or a loopback IP address (127.0.0.0/8)," +
52-
" it SHOULD NOT send the Webmention to that endpoint.'")
52+
" it SHOULD NOT send the Webmention to that endpoint.'")
5353
void sendWebmentionLocalhostRedirect() {
5454
Config config = new Config();
5555
config.setAllowLocalhostEndpoint(false);

client/src/test/java/dev/rilling/webmention4j/client/internal/EndpointDiscoveryServiceSpecIT.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void usesLinkHeader() throws IOException {
6363

6464
@Test
6565
@DisplayName("'If the content type of the document is HTML, then the sender MUST look for an HTML <link> " +
66-
"[...] element with a rel value of webmention' (link element)")
66+
"[...] element with a rel value of webmention' (link element)")
6767
void usesLinkHtmlElement() throws IOException {
6868
TARGET_SERVER.stubFor(get("/post-by-aaron").willReturn(ok().withHeader(HttpHeaders.CONTENT_TYPE,
6969
ContentType.TEXT_HTML.toString()).withBody("""
@@ -84,7 +84,7 @@ void usesLinkHtmlElement() throws IOException {
8484

8585
@Test
8686
@DisplayName("'If the content type of the document is HTML, then the sender MUST look for an HTML [...] <a> " +
87-
"element with a rel value of webmention' (anchor element)")
87+
"element with a rel value of webmention' (anchor element)")
8888
void usesAnchorHtmlElement() throws IOException {
8989
TARGET_SERVER.stubFor(get("/post-by-aaron").willReturn(ok().withHeader(HttpHeaders.CONTENT_TYPE,
9090
ContentType.TEXT_HTML.toString()).withBody("""
@@ -131,7 +131,7 @@ void prioritizesHeader() throws IOException {
131131

132132
@Test
133133
@DisplayName("'If more than one of these is present, [...] takes precedence, followed by the first <link> " +
134-
"or <a> element in document order'")
134+
"or <a> element in document order'")
135135
void prioritizesFirstElement() throws IOException {
136136
TARGET_SERVER.stubFor(get("/post-by-aaron").willReturn(ok().withHeader(HttpHeaders.CONTENT_TYPE,
137137
ContentType.TEXT_HTML.toString()).withBody("""
@@ -155,7 +155,7 @@ void prioritizesFirstElement() throws IOException {
155155

156156
@Test
157157
@DisplayName("'The endpoint MAY be a relative URL, in which case the sender MUST resolve it relative to the " +
158-
"target URL' (header)")
158+
"target URL' (header)")
159159
void adaptsRelativeUriForHeader() throws IOException {
160160
TARGET_SERVER.stubFor(get("/blog/post-by-aaron").willReturn(ok().withHeader(HttpHeaders.LINK,
161161
"<../webmention-endpoint>; rel=\"webmention\"")));
@@ -169,7 +169,7 @@ void adaptsRelativeUriForHeader() throws IOException {
169169

170170
@Test
171171
@DisplayName("'The endpoint MAY be a relative URL, in which case the sender MUST resolve it relative to the " +
172-
"target URL' (element)")
172+
"target URL' (element)")
173173
void adaptsRelativeUriForElement() throws IOException {
174174
TARGET_SERVER.stubFor(get("/blog/post-by-aaron").willReturn(ok().withHeader(HttpHeaders.CONTENT_TYPE,
175175
ContentType.TEXT_HTML.toString()).withBody("""
@@ -190,7 +190,7 @@ void adaptsRelativeUriForElement() throws IOException {
190190

191191
@Test
192192
@DisplayName("'The endpoint MAY contain query string parameters, which MUST be preserved as query string " +
193-
"parameters' (header)")
193+
"parameters' (header)")
194194
void preservesQueryParamsForHeader() throws IOException {
195195
TARGET_SERVER.stubFor(get("/post-by-aaron").willReturn(ok().withHeader(HttpHeaders.LINK,
196196
"<http://aaronpk.example/webmention-endpoint?version=1>; rel=\"webmention\"")));
@@ -203,7 +203,7 @@ void preservesQueryParamsForHeader() throws IOException {
203203

204204
@Test
205205
@DisplayName("'The endpoint MAY contain query string parameters, which MUST be preserved as query string " +
206-
"parameters' (element)")
206+
"parameters' (element)")
207207
void preservesQueryParamsForElement() throws IOException {
208208
TARGET_SERVER.stubFor(get("/post-by-aaron").willReturn(ok().withHeader(HttpHeaders.CONTENT_TYPE,
209209
ContentType.TEXT_HTML.toString()).withBody("""

0 commit comments

Comments
 (0)