Skip to content

Commit f43171e

Browse files
authored
SolrJ: simplify ResponseParser.getContentType processing (#4528)
ResponseParser.getContentType must now return a Set, statically defined. Enforced by RP's constructor.
1 parent 55cd95d commit f43171e

12 files changed

Lines changed: 68 additions & 123 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
title: >
2+
Simplify SolrJ ResponseParser.getContentType processing. getContentType must now return a Set.
3+
type: other
4+
authors:
5+
- name: David Smiley
6+
links:
7+
- name: PR#4528
8+
url: https://github.com/apache/solr/pull/4528

solr/core/src/test/org/apache/solr/search/TestSmileRequest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.io.IOException;
2020
import java.io.InputStream;
21-
import java.util.Collection;
2221
import java.util.Map;
2322
import java.util.Set;
2423
import org.apache.solr.JSONTestUtil;
@@ -106,9 +105,12 @@ public NamedList<Object> processResponse(InputStream body, String encoding) thro
106105
return new NamedList(m);
107106
}
108107

108+
private static final Set<String> CONTENT_TYPES =
109+
Set.of("application/x-jackson-smile", "application/octet-stream");
110+
109111
@Override
110-
public Collection<String> getContentTypes() {
111-
return Set.of("application/x-jackson-smile", "application/octet-stream");
112+
public Set<String> getContentTypes() {
113+
return CONTENT_TYPES;
112114
}
113115
}
114116
}

solr/solrj-jetty/src/java/org/apache/solr/client/solrj/jetty/HttpJettySolrClient.java

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import java.util.Collection;
2727
import java.util.Iterator;
2828
import java.util.List;
29-
import java.util.Locale;
3029
import java.util.Map;
3130
import java.util.concurrent.CancellationException;
3231
import java.util.concurrent.CompletableFuture;
@@ -37,7 +36,6 @@
3736
import java.util.concurrent.Semaphore;
3837
import java.util.concurrent.TimeUnit;
3938
import java.util.concurrent.TimeoutException;
40-
import java.util.stream.Collectors;
4139
import org.apache.solr.client.api.util.SolrVersion;
4240
import org.apache.solr.client.solrj.SolrClient;
4341
import org.apache.solr.client.solrj.SolrRequest;
@@ -161,7 +159,6 @@ protected HttpJettySolrClient(String serverBaseUrl, Builder builder) {
161159
this.listenerFactory = new ArrayList<>(0);
162160
}
163161

164-
updateDefaultMimeTypeForParser();
165162
this.idleTimeoutMillis = builder.getIdleTimeoutMillis();
166163

167164
try {
@@ -807,31 +804,6 @@ protected boolean isFollowRedirects() {
807804
return httpClient.isFollowRedirects();
808805
}
809806

810-
@Override
811-
protected boolean processorAcceptsMimeType(
812-
Collection<String> processorSupportedContentTypes, String mimeType) {
813-
814-
return processorSupportedContentTypes.stream()
815-
.map(ct -> MimeTypes.getContentTypeWithoutCharset(ct).trim())
816-
.anyMatch(mimeType::equalsIgnoreCase);
817-
}
818-
819-
@Override
820-
protected void updateDefaultMimeTypeForParser() {
821-
defaultParserMimeTypes =
822-
parser.getContentTypes().stream()
823-
.map(ct -> MimeTypes.getContentTypeWithoutCharset(ct).trim().toLowerCase(Locale.ROOT))
824-
.collect(Collectors.toSet());
825-
}
826-
827-
@Override
828-
protected String allProcessorSupportedContentTypesCommaDelimited(
829-
Collection<String> processorSupportedContentTypes) {
830-
return processorSupportedContentTypes.stream()
831-
.map(ct -> MimeTypes.getContentTypeWithoutCharset(ct).trim().toLowerCase(Locale.ROOT))
832-
.collect(Collectors.joining(", "));
833-
}
834-
835807
/**
836808
* An HttpJettySolrClient that doesn't close or cleanup any resources
837809
*

solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpJdkSolrClient.java

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import java.util.HashMap;
3838
import java.util.Locale;
3939
import java.util.Map;
40-
import java.util.Objects;
4140
import java.util.concurrent.BlockingQueue;
4241
import java.util.concurrent.CompletableFuture;
4342
import java.util.concurrent.ExecutorService;
@@ -46,7 +45,6 @@
4645
import java.util.concurrent.TimeUnit;
4746
import java.util.regex.Matcher;
4847
import java.util.regex.Pattern;
49-
import java.util.stream.Collectors;
5048
import javax.net.ssl.SSLContext;
5149
import org.apache.solr.client.api.util.SolrVersion;
5250
import org.apache.solr.client.solrj.SolrRequest;
@@ -139,7 +137,6 @@ protected HttpJdkSolrClient(String serverBaseUrl, HttpJdkSolrClient.Builder buil
139137
ProxySelector.of(new InetSocketAddress(builder.getProxyHost(), builder.getProxyPort())));
140138
}
141139
this.httpClient = b.build();
142-
updateDefaultMimeTypeForParser();
143140

144141
assert ObjectReleaseTracker.track(this);
145142
}
@@ -537,36 +534,6 @@ protected boolean isFollowRedirects() {
537534
return httpClient.followRedirects() != HttpClient.Redirect.NEVER;
538535
}
539536

540-
@Override
541-
protected boolean processorAcceptsMimeType(
542-
Collection<String> processorSupportedContentTypes, String mimeType) {
543-
return processorSupportedContentTypes.stream()
544-
.map(this::contentTypeToMimeType)
545-
.filter(Objects::nonNull)
546-
.map(String::trim)
547-
.anyMatch(mimeType::equalsIgnoreCase);
548-
}
549-
550-
@Override
551-
protected void updateDefaultMimeTypeForParser() {
552-
defaultParserMimeTypes =
553-
parser.getContentTypes().stream()
554-
.map(this::contentTypeToMimeType)
555-
.filter(Objects::nonNull)
556-
.map(s -> s.toLowerCase(Locale.ROOT).trim())
557-
.collect(Collectors.toSet());
558-
}
559-
560-
@Override
561-
protected String allProcessorSupportedContentTypesCommaDelimited(
562-
Collection<String> processorSupportedContentTypes) {
563-
return processorSupportedContentTypes.stream()
564-
.map(this::contentTypeToMimeType)
565-
.filter(Objects::nonNull)
566-
.map(s -> s.toLowerCase(Locale.ROOT).trim())
567-
.collect(Collectors.joining(", "));
568-
}
569-
570537
@Override
571538
protected BuilderBase<?, ?> toBuilder(String baseUrl) {
572539
return new HttpJdkSolrClient.Builder(baseUrl).withHttpClient(this);

solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.nio.charset.StandardCharsets;
2828
import java.util.Base64;
2929
import java.util.Collection;
30+
import java.util.Locale;
3031
import java.util.Objects;
3132
import java.util.Set;
3233
import java.util.concurrent.CompletableFuture;
@@ -72,11 +73,8 @@ public abstract class HttpSolrClient extends SolrClient {
7273

7374
protected RequestWriter requestWriter = new JavaBinRequestWriter();
7475

75-
// updating parser instance needs to go via the setter to ensure update of defaultParserMimeTypes
7676
protected ResponseParser parser = new JavaBinResponseParser();
7777

78-
protected Set<String> defaultParserMimeTypes;
79-
8078
protected final String basicAuthAuthorizationStr;
8179

8280
protected HttpSolrClient(String serverBaseUrl, BuilderBase<?, ?> builder) {
@@ -266,12 +264,6 @@ protected boolean wantStream(final ResponseParser processor) {
266264
return processor == null || processor instanceof InputStreamResponseParser;
267265
}
268266

269-
protected abstract boolean processorAcceptsMimeType(
270-
Collection<String> processorSupportedContentTypes, String mimeType);
271-
272-
protected abstract String allProcessorSupportedContentTypesCommaDelimited(
273-
Collection<String> processorSupportedContentTypes);
274-
275267
/**
276268
* Validates that the content type in the response can be processed by the Response Parser. Throws
277269
* a {@code RemoteSolrException} if not.
@@ -283,19 +275,15 @@ private void checkContentType(
283275
String encoding,
284276
int httpStatus,
285277
String urlExceptionMessage) {
286-
if (mimeType == null
287-
|| (processor == this.parser && defaultParserMimeTypes.contains(mimeType))) {
288-
// Shortcut the default scenario
278+
if (mimeType == null) {
289279
return;
290280
}
291281
final Collection<String> processorSupportedContentTypes = processor.getContentTypes();
292282
if (!processorSupportedContentTypes.isEmpty()) {
293-
boolean processorAcceptsMimeType =
294-
processorAcceptsMimeType(processorSupportedContentTypes, mimeType);
295-
if (!processorAcceptsMimeType) {
283+
final String normalizedMimeType = mimeType.toLowerCase(Locale.ROOT).trim();
284+
if (!processorSupportedContentTypes.contains(normalizedMimeType)) {
296285
// unexpected mime type
297-
final String allSupportedTypes =
298-
allProcessorSupportedContentTypesCommaDelimited(processorSupportedContentTypes);
286+
final String allSupportedTypes = String.join(", ", processorSupportedContentTypes);
299287
String prefix =
300288
"Expected mime type in [" + allSupportedTypes + "] but got " + mimeType + ". ";
301289
String exceptionEncoding = encoding != null ? encoding : FALLBACK_CHARSET.name();
@@ -322,11 +310,8 @@ protected static String basicAuthCredentialsToAuthorizationString(String user, S
322310

323311
protected void setParser(ResponseParser parser) {
324312
this.parser = parser;
325-
updateDefaultMimeTypeForParser();
326313
}
327314

328-
protected abstract void updateDefaultMimeTypeForParser();
329-
330315
/**
331316
* Executes a SolrRequest using the provided URL to temporarily override any "base URL" currently
332317
* used by this client

solr/solrj/src/java/org/apache/solr/client/solrj/response/JavaBinResponseParser.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.io.IOException;
2020
import java.io.InputStream;
21-
import java.util.Collection;
2221
import java.util.Set;
2322
import org.apache.solr.common.util.JavaBinCodec;
2423
import org.apache.solr.common.util.NamedList;
@@ -52,8 +51,11 @@ protected JavaBinCodec createCodec() {
5251
return new JavaBinCodec(null, stringCache);
5352
}
5453

54+
private static final Set<String> CONTENT_TYPES =
55+
Set.of(JAVABIN_CONTENT_TYPE, JAVABIN_CONTENT_TYPE_V2);
56+
5557
@Override
56-
public Collection<String> getContentTypes() {
57-
return Set.of(JAVABIN_CONTENT_TYPE, JAVABIN_CONTENT_TYPE_V2);
58+
public Set<String> getContentTypes() {
59+
return CONTENT_TYPES;
5860
}
5961
}

solr/solrj/src/java/org/apache/solr/client/solrj/response/ResponseParser.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.io.IOException;
2020
import java.io.InputStream;
2121
import java.util.Collection;
22+
import java.util.Locale;
23+
import java.util.Set;
2224
import org.apache.solr.common.util.NamedList;
2325

2426
/**
@@ -28,17 +30,40 @@
2830
*/
2931
public abstract class ResponseParser {
3032

33+
protected ResponseParser() {
34+
assert validateContentTypes();
35+
}
36+
37+
private boolean validateContentTypes() {
38+
Collection<String> contentTypes = getContentTypes();
39+
assert contentTypes == getContentTypes()
40+
: getClass().getName() + ".getContentTypes() must return the same instance on every call";
41+
for (String ct : contentTypes) {
42+
assert !ct.contains(";") && ct.equals(ct.toLowerCase(Locale.ROOT))
43+
: getClass().getName()
44+
+ ".getContentTypes() must return lowercase MIME types without semicolons, got: "
45+
+ ct;
46+
}
47+
return true;
48+
}
49+
3150
/** The writer type placed onto the request as the {@code wt} param. */
3251
public abstract String getWriterType(); // for example: wt=XML, JSON, etc
3352

3453
public abstract NamedList<Object> processResponse(InputStream body, String encoding)
3554
throws IOException;
3655

3756
/**
38-
* A well-behaved ResponseParser will return the content-types it supports.
57+
* Returns the MIME types this parser supports. Return an empty set to disable. Implementations
58+
* must:
59+
*
60+
* <ul>
61+
* <li>Returns the same instance (same reference on every call).
62+
* <li>Use only lowercase MIME types without charset or other parameters (no semicolons)
63+
* <li>
64+
* </ul>
3965
*
40-
* @return the content-type values that this parser is capable of parsing. Never null. Empty means
41-
* no enforcement.
66+
* @return the MIME types that this parser is capable of parsing. Never null.
4267
*/
43-
public abstract Collection<String> getContentTypes();
68+
public abstract Set<String> getContentTypes();
4469
}

solr/solrj/src/java/org/apache/solr/client/solrj/response/XMLResponseParser.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,11 @@ public String getWriterType() {
8080
return "xml";
8181
}
8282

83+
private static final Set<String> CONTENT_TYPES = Set.of("application/xml");
84+
8385
@Override
8486
public Set<String> getContentTypes() {
85-
return Set.of(XML_CONTENT_TYPE);
87+
return CONTENT_TYPES;
8688
}
8789

8890
public NamedList<Object> processResponse(Reader in) {

solr/solrj/src/java/org/apache/solr/client/solrj/response/json/JacksonDataBindResponseParser.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@
2020
import java.io.IOException;
2121
import java.io.InputStream;
2222
import java.io.InputStreamReader;
23-
import java.util.Collection;
24-
import java.util.List;
2523
import java.util.Map;
24+
import java.util.Set;
2625
import org.apache.solr.client.api.model.SolrJerseyResponse;
2726
import org.apache.solr.client.solrj.request.json.JacksonContentWriter;
2827
import org.apache.solr.client.solrj.response.ResponseParser;
@@ -47,9 +46,11 @@ public String getWriterType() {
4746
return "json";
4847
}
4948

49+
private static final Set<String> CONTENT_TYPES = Set.of("application/json");
50+
5051
@Override
51-
public Collection<String> getContentTypes() {
52-
return List.of("application/json");
52+
public Set<String> getContentTypes() {
53+
return CONTENT_TYPES;
5354
}
5455

5556
// TODO it'd be nice if the ResponseParser could receive the mime type so it can parse

solr/solrj/src/java/org/apache/solr/client/solrj/response/json/JsonMapResponseParser.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.io.IOException;
2121
import java.io.InputStream;
2222
import java.io.InputStreamReader;
23-
import java.util.Collection;
2423
import java.util.Map;
2524
import java.util.Set;
2625
import org.apache.solr.client.solrj.response.ResponseParser;
@@ -55,8 +54,10 @@ public NamedList<Object> processResponse(InputStream body, String encoding) thro
5554
return list;
5655
}
5756

57+
private static final Set<String> CONTENT_TYPES = Set.of("application/json");
58+
5859
@Override
59-
public Collection<String> getContentTypes() {
60-
return Set.of("application/json");
60+
public Set<String> getContentTypes() {
61+
return CONTENT_TYPES;
6162
}
6263
}

0 commit comments

Comments
 (0)