Skip to content

Commit 05ce039

Browse files
authored
Merge pull request #308 from cyb3r4nt/jsonrpc4j-issue-306
#306: Add support for newer jakarta.servlet.http API into JsonRpcServer
2 parents f35fc2a + 8e0beff commit 05ce039

File tree

2 files changed

+177
-23
lines changed

2 files changed

+177
-23
lines changed

build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ dependencies {
9595
// TODO: remove deprecated portlet-api when support is removed from the code
9696
servletSupportImplementation 'javax.portlet:portlet-api:3.0.1'
9797
servletSupportImplementation 'javax.servlet:javax.servlet-api:4.0.1'
98+
// TODO: Jakarta EE 9 and jakarta.servlet-api 5.x are still compatible with Java SE 8,
99+
// update jakarta.servlet-api to version 6+ when JDK baseline is increased to 11+
100+
servletSupportImplementation 'jakarta.servlet:jakarta.servlet-api:5.0.0'
98101

99102
implementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}"
100103
implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"

src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java

Lines changed: 174 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,14 @@
1313
import java.io.IOException;
1414
import java.io.InputStream;
1515
import java.io.OutputStream;
16-
import java.util.zip.GZIPInputStream;
17-
import java.util.zip.GZIPOutputStream;
1816

1917
/**
2018
* A JSON-RPC request server reads JSON-RPC requests from an input stream and writes responses to an output stream.
2119
* Supports handler and servlet requests.
2220
*/
23-
@SuppressWarnings("unused")
2421
public class JsonRpcServer extends JsonRpcBasicServer {
2522
private static final Logger logger = LoggerFactory.getLogger(JsonRpcServer.class);
2623

27-
private static final String GZIP = "gzip";
2824
private String contentType = JSONRPC_CONTENT_TYPE;
2925

3026
/**
@@ -92,6 +88,8 @@ public void handle(ResourceRequest request, ResourceResponse response) throws IO
9288
OutputStream output = response.getPortletOutputStream();
9389
handleRequest(input, output);
9490
// fix to not flush within handleRequest() but outside so http status code can be set
91+
// TODO: this logic may be changed to use handleCommon() method,
92+
// HTTP status code may be provided by the HttpStatusCodeProvider extension
9593
output.flush();
9694
}
9795

@@ -117,50 +115,74 @@ private static InputStream createInputStream(ResourceRequest request) throws IOE
117115
* @throws IOException on error
118116
*/
119117
public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException {
120-
logger.debug("Handling HttpServletRequest {}", request);
118+
handleCommon(
119+
new JavaxHttpServletRequest(request),
120+
new JavaxHttpServletResponse(response)
121+
);
122+
}
123+
124+
/**
125+
* Handles a servlet request.
126+
*
127+
* @param request the {@link jakarta.servlet.http.HttpServletRequest}
128+
* @param response the {@link jakarta.servlet.http.HttpServletResponse}
129+
* @throws IOException on error
130+
*/
131+
public void handle(
132+
jakarta.servlet.http.HttpServletRequest request,
133+
jakarta.servlet.http.HttpServletResponse response
134+
) throws IOException {
135+
handleCommon(
136+
new JakartaHttpServletRequest(request),
137+
new JakartaHttpServletResponse(response)
138+
);
139+
}
140+
141+
private void handleCommon(CommonHttpServletRequest request, CommonHttpServletResponse response) throws IOException {
142+
logger.debug("Handling HttpServletRequest {}", request.unwrap());
121143
response.setContentType(contentType);
122144
OutputStream output = response.getOutputStream();
123145
InputStream input = getRequestStream(request);
124146
int result = ErrorResolver.JsonError.PARSE_ERROR.code;
125-
int contentLength = 0;
147+
126148
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
127149
try {
128-
String acceptEncoding = request.getHeader(ACCEPT_ENCODING);
129-
result = handleRequest0(input, output, acceptEncoding, response, byteOutput);
130-
131-
contentLength = byteOutput.size();
150+
result = handleRequest(input, byteOutput);
132151
} catch (Throwable t) {
133-
if (StreamEndedException.class.isInstance(t)) {
152+
if (t instanceof StreamEndedException) {
134153
logger.debug("Bad request: empty contents!");
135154
} else {
136155
logger.error(t.getMessage(), t);
137156
}
138157
}
139-
int httpStatusCode = httpStatusCodeProvider == null ? DefaultHttpStatusCodeProvider.INSTANCE.getHttpStatusCode(result)
140-
: httpStatusCodeProvider.getHttpStatusCode(result);
141-
response.setStatus(httpStatusCode);
142-
response.setContentLength(contentLength);
158+
159+
response.setStatus(resolveHttpStatusCode(result));
160+
response.setContentLength(byteOutput.size());
143161
byteOutput.writeTo(output);
144162
output.flush();
145163
}
146164

147-
private InputStream getRequestStream(HttpServletRequest request) throws IOException {
165+
private int resolveHttpStatusCode(int result) {
166+
if (this.httpStatusCodeProvider != null) {
167+
return this.httpStatusCodeProvider.getHttpStatusCode(result);
168+
} else {
169+
return DefaultHttpStatusCodeProvider.INSTANCE.getHttpStatusCode(result);
170+
}
171+
}
172+
173+
private InputStream getRequestStream(CommonHttpServletRequest request) throws IOException {
148174
InputStream input;
149-
if (request.getMethod().equals("POST")) {
175+
if ("POST".equals(request.getMethod())) {
150176
input = request.getInputStream();
151-
} else if (request.getMethod().equals("GET")) {
177+
} else if ("GET".equals(request.getMethod())) {
152178
input = createInputStream(request);
153179
} else {
154180
throw new IOException("Invalid request method, only POST and GET is supported");
155181
}
156182
return input;
157183
}
158184

159-
private int handleRequest0(InputStream input, OutputStream output, String contentEncoding, HttpServletResponse response, ByteArrayOutputStream byteOutput) throws IOException {
160-
return handleRequest(input, byteOutput);
161-
}
162-
163-
private static InputStream createInputStream(HttpServletRequest request) throws IOException {
185+
private static InputStream createInputStream(CommonHttpServletRequest request) throws IOException {
164186
String method = request.getParameter(METHOD);
165187
String id = request.getParameter(ID);
166188
String params = request.getParameter(PARAMS);
@@ -175,4 +197,133 @@ public void setContentType(String contentType) {
175197
this.contentType = contentType;
176198
}
177199

200+
private interface CommonHttpServletRequest {
201+
Object unwrap();
202+
InputStream getInputStream() throws IOException;
203+
String getMethod();
204+
String getParameter(String name);
205+
}
206+
207+
private static class JavaxHttpServletRequest implements CommonHttpServletRequest {
208+
209+
private final HttpServletRequest request;
210+
211+
private JavaxHttpServletRequest(HttpServletRequest request) {
212+
this.request = request;
213+
}
214+
215+
@Override
216+
public Object unwrap() {
217+
return this.request;
218+
}
219+
220+
@Override
221+
public InputStream getInputStream() throws IOException {
222+
return this.request.getInputStream();
223+
}
224+
225+
@Override
226+
public String getMethod() {
227+
return this.request.getMethod();
228+
}
229+
230+
@Override
231+
public String getParameter(String name) {
232+
return this.request.getParameter(name);
233+
}
234+
}
235+
236+
private static class JakartaHttpServletRequest implements CommonHttpServletRequest {
237+
238+
private final jakarta.servlet.http.HttpServletRequest request;
239+
240+
private JakartaHttpServletRequest(jakarta.servlet.http.HttpServletRequest request) {
241+
this.request = request;
242+
}
243+
244+
@Override
245+
public Object unwrap() {
246+
return this.request;
247+
}
248+
249+
@Override
250+
public InputStream getInputStream() throws IOException {
251+
return this.request.getInputStream();
252+
}
253+
254+
@Override
255+
public String getMethod() {
256+
return this.request.getMethod();
257+
}
258+
259+
@Override
260+
public String getParameter(String name) {
261+
return this.request.getParameter(name);
262+
}
263+
}
264+
265+
private interface CommonHttpServletResponse {
266+
void setContentType(String type);
267+
void setStatus(int sc);
268+
void setContentLength(int len);
269+
OutputStream getOutputStream() throws IOException;
270+
}
271+
272+
private static class JavaxHttpServletResponse implements CommonHttpServletResponse {
273+
274+
private final HttpServletResponse response;
275+
276+
private JavaxHttpServletResponse(HttpServletResponse response) {
277+
this.response = response;
278+
}
279+
280+
@Override
281+
public void setContentType(String type) {
282+
this.response.setContentType(type);
283+
}
284+
285+
@Override
286+
public void setStatus(int sc) {
287+
this.response.setStatus(sc);
288+
}
289+
290+
@Override
291+
public void setContentLength(int len) {
292+
this.response.setContentLength(len);
293+
}
294+
295+
@Override
296+
public OutputStream getOutputStream() throws IOException {
297+
return this.response.getOutputStream();
298+
}
299+
}
300+
301+
private static class JakartaHttpServletResponse implements CommonHttpServletResponse {
302+
303+
private final jakarta.servlet.http.HttpServletResponse response;
304+
305+
private JakartaHttpServletResponse(jakarta.servlet.http.HttpServletResponse response) {
306+
this.response = response;
307+
}
308+
309+
@Override
310+
public void setContentType(String type) {
311+
this.response.setContentType(type);
312+
}
313+
314+
@Override
315+
public void setStatus(int sc) {
316+
this.response.setStatus(sc);
317+
}
318+
319+
@Override
320+
public void setContentLength(int len) {
321+
this.response.setContentLength(len);
322+
}
323+
324+
@Override
325+
public OutputStream getOutputStream() throws IOException {
326+
return this.response.getOutputStream();
327+
}
328+
}
178329
}

0 commit comments

Comments
 (0)