diff --git a/.gitignore b/.gitignore index bb7da614..167e3ba9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ build/ ### Maven template ### Eclipse template .gradle +gradle.properties tmp/ # Eclipse Core # External tool builders @@ -25,4 +26,5 @@ tmp/ /bin/ /.nb-gradle/ /target -out/ \ No newline at end of file +out/ +.DS_Store diff --git a/README.md b/README.md index bfd6f3c8..c17b41d7 100644 --- a/README.md +++ b/README.md @@ -38,14 +38,18 @@ using maven: In ``: ```xml - com.github.briandilley.jsonrpc4j jsonrpc4j - 1.5.3 + 1.6 +``` + +or with gradle: +```groovy + implementation('com.github.briandilley.jsonrpc4j:jsonrpc4j:1.6') ``` If you want to just download the projects output JAR and it's dependencies you can diff --git a/build.gradle b/build.gradle index 7f313de0..0ade14d7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,22 +1,45 @@ +buildscript { + + ext { + set("jacksonVersion", "2.10.2") + set("springVersion", "4.3.26.RELEASE") + set("springBotVersion", "1.4.7.RELEASE") + set("jettyVersion", "9.4.0.RC3") + set("slf4jVersion", "1.7.30") + } + + repositories { + gradlePluginPortal() + mavenCentral() + jcenter() + maven { url "https://plugins.gradle.org/m2/" } + } + + dependencies { + classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.5.3" + classpath("com.adarshr:gradle-test-logger-plugin:1.6.0") + } +} + plugins { - id 'java' - id 'nebula.optional-base' version '3.1.0' - id 'nebula.provided-base' version '3.1.0' - id 'findbugs' - id 'pmd' - id 'jacoco' - id 'nebula.info' version '3.4.1' - id 'com.github.ben-manes.versions' version '0.13.0' - id 'osgi' - id 'maven-publish' - id 'nebula.nebula-javadoc-jar' version '2.2.2' - id 'nebula.nebula-source-jar' version '2.2.2' - id 'com.jfrog.bintray' version '1.7.3' + id('jacoco') +} + +repositories { + mavenLocal() + gradlePluginPortal() + mavenCentral() + jcenter() } -description = 'This project aims to provide the facility to easily implement JSON-RPC for the java programming language.' -version = '1.5.3-2' -group = 'com.github.briandilley.jsonrpc4j' +apply plugin: "java" +apply plugin: "com.adarshr.test-logger" + +group = "com.github.briandilley.jsonrpc4j" +version = "1.6" +description = """ +This project aims to provide the facility to easily implement JSON-RPC for the java programming language. +""" sourceCompatibility = 1.8 targetCompatibility = 1.8 @@ -25,57 +48,77 @@ compileJava { options.encoding = 'UTF-8' options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" } + +ext { + releaseVersion = !version.toString().endsWith('-SNAPSHOT') +} + test { - maxParallelForks 5 + testLogging { + exceptionFormat = "FULL" + showExceptions = true + showStackTraces = true + showCauses = true + } + maxParallelForks = 1 + forkEvery = 1 + maxHeapSize = "2g" + finalizedBy jacocoTestReport } -compileTestJava { - options.encoding = 'UTF-8' - options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" + +jacoco { + toolVersion = "0.8.5" } -apply plugin: "maven" +jacocoTestReport { + dependsOn test + reports { + xml.enabled true + csv.enabled true + html.enabled true + } +} -repositories { - mavenLocal() - mavenCentral() +java { + registerFeature('servletSupport') { + usingSourceSet(sourceSets.main) + } + registerFeature('springSupport') { + usingSourceSet(sourceSets.main) + } } dependencies { - ext { - jacksonVersion = '2.10.2' - springVersion = '4.3.26.RELEASE' - springBotVersion = '1.4.7.RELEASE' - jettyVersion = '9.4.0.RC3' - slf4jVersion = '1.7.30' - } - compile 'net.iharder:base64:2.3.9' - compile "org.slf4j:slf4j-api:${slf4jVersion}" - provided 'javax.portlet:portlet-api:2.0' - provided 'javax.servlet:javax.servlet-api:3.1.0' + implementation 'net.iharder:base64:2.3.9' + implementation "org.slf4j:slf4j-api:${slf4jVersion}" + + + servletSupportImplementation 'javax.portlet:portlet-api:3.0.1' + servletSupportImplementation 'javax.servlet:javax.servlet-api:4.0.1' - compile "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" - compile "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" - compile "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}" + implementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" + implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" + implementation "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}" - compile "org.springframework:spring-core:${springVersion}", optional - compile "org.springframework:spring-context:${springVersion}", optional - compile "org.springframework:spring-web:${springVersion}", optional - compile "org.springframework:spring-webmvc:${springVersion}", optional + springSupportImplementation "org.springframework:spring-core:${springVersion}" + springSupportImplementation "org.springframework:spring-context:${springVersion}" + springSupportImplementation "org.springframework:spring-web:${springVersion}" + springSupportImplementation "org.springframework:spring-webmvc:${springVersion}" - compile 'commons-codec:commons-codec:1.10', optional - compile 'org.apache.httpcomponents:httpcore-nio:4.4.5', optional + implementation 'commons-codec:commons-codec:1.10' + implementation 'org.apache.httpcomponents:httpcore-nio:4.4.5' - testCompile 'junit:junit:4.12' - testCompile 'org.easymock:easymock:3.4' - testCompile("org.springframework.boot:spring-boot-starter-web:${springBotVersion}") { + testImplementation 'junit:junit:4.12' + testImplementation 'org.easymock:easymock:3.4' + testImplementation("org.springframework.boot:spring-boot-starter-web:${springBotVersion}") { exclude module: 'logback-classic' } - testCompile "org.springframework.boot:spring-boot-starter-test:${springBotVersion}" - testCompile("org.eclipse.jetty:jetty-server:${jettyVersion}") { + testImplementation "org.springframework.boot:spring-boot-starter-test:${springBotVersion}" + testImplementation("org.eclipse.jetty:jetty-server:${jettyVersion}") { exclude module: 'javax.servlet' } - testCompile("org.eclipse.jetty:jetty-servlet:${jettyVersion}") { + testImplementation("org.eclipse.jetty:jetty-servlet:${jettyVersion}") { exclude module: 'org.eclipse.jetty.orbit' } testRuntime 'org.apache.logging.log4j:log4j-slf4j-impl:2.7' @@ -83,101 +126,19 @@ dependencies { } -jar { - manifest { - instruction 'Import-Package', - 'org.aopalliance.intercept;resolution:="optional"', - 'org.apache.http.*;resolution:="optional"', - 'org.springframework.*;resolution:="optional"', - 'org.apache.commons.logging;resolution:="optional"', - 'javax.portlet;resolution:="optional"', - 'javax.servlet*;version=0.0.0', - '*' - } -} - -jacoco { - toolVersion = '0.7.6.201602180812' - reportsDir = file("$buildDir/customJacocoReportDir") -} -jacocoTestReport { - reports { - xml.enabled false - csv.enabled false - html.destination "${buildDir}/jacocoHtml" - } +task documentationJar(type: Jar) { + archiveClassifier.set("javadoc") + from javadoc } - -publishing { - publications { - release(MavenPublication) { - from components.java - artifact tasks.javadocJar - artifact tasks.sourceJar - pom.withXml { - def root = asNode() - root.appendNode('name', project.name) - root.appendNode('description', project.description) - def pomProperties = root.appendNode('properties') - pomProperties.appendNode('release_Manifest_Version', '1.0') - pomProperties.appendNode('release_Implementation_Title', "${project.group}:${project.name}:${project.version}") - pomProperties.appendNode('release_Implementation_Version', project.version) - pomProperties.appendNode('release_Build_Date', new Date().format('yyyy-MM-dd_HH:mm:ss')) - pomProperties.appendNode('release_Created_By', "${System.getProperty('java.runtime.version')} (${System.getProperty('java.vm.specification.vendor')})") - pomProperties.appendNode('release_Build_Java_Version', System.getProperty('java.version')) - pomProperties.appendNode('release_X_Compile_Target_JDK', project.targetCompatibility) - pomProperties.appendNode('release_X_Compile_Source_JDK', project.sourceCompatibility) - root.appendNode('url', 'https://github.com/briandilley/jsonrpc4j') - root.appendNode('scm').appendNode('url', 'https://github.com/briandilley/jsonrpc4j.git') - def devs = root.appendNode('developers') - def bernat = devs.appendNode('developer') - bernat.appendNode('id', 'gaborbernat') - bernat.appendNode('name', 'Bernát Gábor') - bernat.appendNode('email', 'bernat@primeransk.net') - def slipper = devs.appendNode('developer') - slipper.appendNode('id', 'mslipper') - slipper.appendNode('name', 'Matthew Slipper') - slipper.appendNode('email', 'me@matthewslipper.com') - def apache = root.appendNode('licenses').appendNode('license') - apache.appendNode('name', 'The MIT License') - apache.appendNode('url', 'https://opensource.org/licenses/MIT') - apache.appendNode('distribution', 'repo') - } - } - } +task sourcesJar(type: Jar) { + archiveClassifier.set("sources") + from sourceSets.main.allSource } -bintray { - user = project.hasProperty('user') ? project.property('user') : 'not_set' - key = project.hasProperty('key') ? project.property('key') : 'not_set' - dryRun = false - publish = true - pkg { - repo = 'maven' - name = 'com.github.briandilley.jsonrpc4j:jsonrpc4j' - desc = project.description - licenses = ['MIT'] - publications = ['release'] - websiteUrl = 'https://briandilley.github.io/jsonrpc4j' - issueTrackerUrl = 'https://github.com/briandilley/jsonrpc4j/issues' - vcsUrl = 'git@github.com:briandilley/jsonrpc4j.git' - githubRepo = 'briandilley/jsonrpc' - githubReleaseNotesFile = 'README.md' - labels = ['json', 'rpc', 'java'] - publicDownloadNumbers = true - version { - gpg { - sign = true - } - name = project.version - vcsTag = project.version - released = new Date() - } - } +artifacts { + archives documentationJar, sourcesJar } -bintrayUpload { - dependsOn "publishToMavenLocal" -} +apply from: 'publishing.gradle' diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 158fe8c2..28861d27 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0d4b85e5..ed188de9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Feb 17 20:25:46 GMT+03:00 2017 +#Mon Oct 07 19:30:35 PDT 2019 +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +zipStoreBase=GRADLE_USER_HOME diff --git a/pom.gradle b/pom.gradle new file mode 100644 index 00000000..cdaaefd5 --- /dev/null +++ b/pom.gradle @@ -0,0 +1,47 @@ +allprojects { project -> + publishing { + publications { + jsonrpc4j { + pom { + name = rootProject.name.capitalize() + (project.parent ? " ($shortName)" : '') + description = project.description + url = 'https://github.com/briandilley/jsonrpc4j' + issueManagement { + system = 'GitHub' + url = 'https://github.com/briandilley/jsonrpc4j/issues' + } + ciManagement { + system = 'Github Actions' + url = 'https://github.com/briandilley/jsonrpc4j/actions' + } + inceptionYear = '2013' + developers { + developer { + id = 'briandilley' + name = 'Brian Dilley' + email = 'brian.dilley@gmail.com.com' + url = 'https://github.com/briandilley' + timezone = 'America/Los_Angeles' + } + } + licenses { + license { + name = 'The MIT License (MIT)' + url = 'https://github.com/briandilley/jsonrpc4j/blob/develop/LICENSE' + distribution = 'repo' + comments = 'A business-friendly OSS license' + } + } + scm { + connection = 'scm:git:https://github.com/briandilley/jsonrpc4j.git' + developerConnection = 'git@github.com:briandilley/jsonrpc4j.git' + url = 'https://github.com/briandilley/jsonrpc4j' + } + distributionManagement { + downloadUrl = 'https://github.com/briandilley/jsonrpc4j/releases' + } + } + } + } + } +} diff --git a/publishing.gradle b/publishing.gradle new file mode 100644 index 00000000..2f7998bd --- /dev/null +++ b/publishing.gradle @@ -0,0 +1,129 @@ +import io.codearte.gradle.nexus.BaseStagingTask +import io.codearte.gradle.nexus.NexusStagingPlugin + +import javax.naming.ConfigurationException + +buildscript { + repositories { + gradlePluginPortal() + } + dependencies { + classpath 'io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.11.0' + classpath 'gradle.plugin.net.wooga.gradle:atlas-github:1.0.1' + classpath 'net.researchgate:gradle-release:2.7.0' + classpath 'org.ajoberstar:grgit:2.3.0' + classpath 'org.kohsuke:github-api:1.93' + } +} + +ext { + it.'signing.secretKeyRingFile' = project.findProperty('jsonrpc4j.signing.secretKeyRingFile') ?: + project.findProperty('signing.secretKeyRingFile') + it.'signing.password' = project.findProperty('jsonrpc4j.signing.password') ?: + project.findProperty('signing.password') + it.'signing.keyId' = project.findProperty('jsonrpc4j.signing.keyId') ?: + project.findProperty('signing.keyId') + sonatypeUsername = project.findProperty('jsonrpc4j.sonatype.username') ?: + project.findProperty('sonatype.username') + sonatypePassword = project.findProperty('jsonrpc4j.sonatype.password') ?: + project.findProperty('sonatype.password') + sonatypeStagingProfileId = project.findProperty('jsonrpc4j.sonatype.stagingProfileId') ?: + project.findProperty('sonatype.stagingProfileId') + it.'github.token' = project.findProperty('jsonrpc4j.github.token') ?: + project.findProperty('github.token') +} + +allprojects { + apply plugin: 'maven-publish' + + publishing { + repositories { + maven { + name 'sonatype' + if (releaseVersion) { + url 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' + } else { + url 'https://oss.sonatype.org/content/repositories/snapshots/' + } + credentials { + username sonatypeUsername + password sonatypePassword + } + } + } + } + + tasks.withType(PublishToMavenRepository) { + doFirst { + if (!sonatypeUsername) { + throw new ConfigurationException( + 'Please set the Sonatype username with project property "sonatype.username" ' + + 'or "jsonrpc4j.sonatype.username". If both are set, the latter will be effective.') + } + if (!sonatypePassword) { + throw new ConfigurationException( + 'Please set the Sonatype password with project property "sonatype.password" ' + + 'or "jsonrpc4j.sonatype.password". If both are set, the latter will be effective.') + } + } + } +} + +publishing { + publications { + jsonrpc4j(MavenPublication) { + from components.java + artifact documentationJar + artifact sourcesJar + } + } +} + +apply from: 'pom.gradle' + +allprojects { + apply plugin: 'signing' + + signing { + required { + // signing is required if this is a release version and the artifacts are to be published + releaseVersion && tasks.withType(PublishToMavenRepository).find { + gradle.taskGraph.hasTask it + } + } + sign publishing.publications + } +} + +apply plugin: NexusStagingPlugin +// remove superfluous tasks from NexusStagingPlugin +//tasks.removeAll([promoteRepository, closeAndPromoteRepository, getStagingProfile]) + +nexusStaging { + stagingProfileId sonatypeStagingProfileId + username sonatypeUsername + password sonatypePassword +} + +// make sure the staging tasks are run after any publishing tasks if both are to be run +tasks.withType(BaseStagingTask) { + mustRunAfter allprojects.tasks*.withType(PublishToMavenRepository) + + doFirst { + if (!sonatypeStagingProfileId) { + throw new ConfigurationException( + 'Please set the Sonatype staging profile id with project property "sonatype.stagingProfileId" ' + + 'or "jsonrpc4j.sonatype.stagingProfileId". If both are set, the latter will be effective.') + } + if (!sonatypeUsername) { + throw new ConfigurationException( + 'Please set the Sonatype username with project property "sonatype.username" ' + + 'or "jsonrpc4j.sonatype.username". If both are set, the latter will be effective.') + } + if (!sonatypePassword) { + throw new ConfigurationException( + 'Please set the Sonatype password with project property "sonatype.password" ' + + 'or "jsonrpc4j.sonatype.password". If both are set, the latter will be effective.') + } + } +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..11f90800 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'jsonrpc4j' diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java index 0d19a075..aa1db675 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java @@ -79,7 +79,7 @@ public class JsonRpcBasicServer { private boolean shouldLogInvocationErrors = true; private List interceptorList = new ArrayList<>(); private ExecutorService batchExecutorService = null; - private long parallelBatchProcessingTimeout; + private long parallelBatchProcessingTimeout = Long.MAX_VALUE; /** * Creates the server with the given {@link ObjectMapper} delegating @@ -281,7 +281,8 @@ protected Class[] getHandlerInterfaces(final String serviceName) { * @param node the {@link JsonNode} * @return the {@link JsonResponse} instance */ - protected JsonResponse handleJsonNodeRequest(final JsonNode node) { + protected JsonResponse handleJsonNodeRequest(final JsonNode node) + throws JsonParseException, JsonMappingException { if (node.isArray()) { return handleArray((ArrayNode) node); } @@ -321,7 +322,12 @@ private JsonResponse getBatchResponseSequentially(ArrayNode node) { JsonResponse response = new JsonResponse(); for (int i = 0; i < node.size(); i++) { - JsonResponse nodeResult = handleJsonNodeRequest(node.get(i)); + JsonResponse nodeResult; + try { + nodeResult = handleJsonNodeRequest(node.get(i)); + } catch(Exception e) { + nodeResult = createResponseError(VERSION, NULL, JsonError.PARSE_ERROR); + } handleRethrowException(response, nodeResult); batchResult.add(nodeResult.getResponse()); if (isError(nodeResult)) { @@ -409,7 +415,8 @@ private boolean isError(JsonResponse result) { * @param node the {@link JsonNode} * @return the {@link JsonResponse} instance */ - private JsonResponse handleObject(final ObjectNode node) { + private JsonResponse handleObject(final ObjectNode node) + throws JsonParseException, JsonMappingException { logger.debug("Request: {}", node); if (!isValidRequest(node)) { diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcMultiServer.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcMultiServer.java index 58589dd8..44796eb9 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcMultiServer.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcMultiServer.java @@ -52,13 +52,7 @@ public JsonRpcMultiServer() { } public JsonRpcMultiServer(ObjectMapper mapper) { - super(mapper, null); - this.handlerMap = new HashMap<>(); - this.interfaceMap = new HashMap<>(); - } - - public JsonRpcMultiServer(ObjectMapper mapper, boolean gzipResponses) { - super(mapper, null, null, gzipResponses); + super(mapper); this.handlerMap = new HashMap<>(); this.interfaceMap = new HashMap<>(); } diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java index 21f441fe..1a45d209 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java @@ -25,24 +25,8 @@ public class JsonRpcServer extends JsonRpcBasicServer { private static final Logger logger = LoggerFactory.getLogger(JsonRpcServer.class); private static final String GZIP = "gzip"; - protected final boolean gzipResponses; private String contentType = JSONRPC_CONTENT_TYPE; - /** - * Creates the server with the given {@link ObjectMapper} delegating - * all calls to the given {@code handler} {@link Object} but only - * methods available on the {@code remoteInterface}. - * - * @param mapper the {@link ObjectMapper} - * @param handler the {@code handler} - * @param remoteInterface the interface - * @param gzipResponses whether gzip the response that is sent to the client. - */ - public JsonRpcServer(ObjectMapper mapper, Object handler, Class remoteInterface, boolean gzipResponses) { - super(mapper, handler, remoteInterface); - this.gzipResponses = gzipResponses; - } - /** * Creates the server with the given {@link ObjectMapper} delegating * all calls to the given {@code handler} {@link Object} but only @@ -54,7 +38,6 @@ public JsonRpcServer(ObjectMapper mapper, Object handler, Class remoteInterfa */ public JsonRpcServer(ObjectMapper mapper, Object handler, Class remoteInterface) { super(mapper, handler, remoteInterface); - this.gzipResponses = false; } /** @@ -66,7 +49,6 @@ public JsonRpcServer(ObjectMapper mapper, Object handler, Class remoteInterfa */ public JsonRpcServer(ObjectMapper mapper, Object handler) { super(mapper, handler, null); - this.gzipResponses = false; } /** @@ -79,7 +61,6 @@ public JsonRpcServer(ObjectMapper mapper, Object handler) { */ public JsonRpcServer(Object handler, Class remoteInterface) { super(new ObjectMapper(), handler, remoteInterface); - this.gzipResponses = false; } /** @@ -90,7 +71,6 @@ public JsonRpcServer(Object handler, Class remoteInterface) { */ public JsonRpcServer(Object handler) { super(new ObjectMapper(), handler, null); - this.gzipResponses = false; } /** @@ -162,7 +142,7 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr private InputStream getRequestStream(HttpServletRequest request) throws IOException { InputStream input; if (request.getMethod().equals("POST")) { - input = createInputStream(request.getInputStream(), request.getHeader(CONTENT_ENCODING)); + input = request.getInputStream(); } else if (request.getMethod().equals("GET")) { input = createInputStream(request); } else { @@ -172,31 +152,7 @@ private InputStream getRequestStream(HttpServletRequest request) throws IOExcept } private int handleRequest0(InputStream input, OutputStream output, String contentEncoding, HttpServletResponse response, ByteArrayOutputStream byteOutput) throws IOException { - int result; - - boolean canGzipResponse = contentEncoding != null && contentEncoding.contains(GZIP); - // Use gzip if client's accept-encoding is set to gzip and gzipResponses is enabled. - if (gzipResponses && canGzipResponse) { - response.addHeader(CONTENT_ENCODING, GZIP); - try (GZIPOutputStream gos = new GZIPOutputStream(byteOutput)) { - result = handleRequest(input, gos); - } - } else { - result = handleRequest(input, byteOutput); - } - - return result; - } - - private static InputStream createInputStream(InputStream inputStream, String contentEncoding) throws IOException { - InputStream input; - if (contentEncoding != null && GZIP.equalsIgnoreCase(contentEncoding)) { - input = new GZIPInputStream(inputStream); - } else { - input = inputStream; - } - - return input; + return handleRequest(input, byteOutput); } private static InputStream createInputStream(HttpServletRequest request) throws IOException { diff --git a/src/main/java/com/googlecode/jsonrpc4j/ReadContext.java b/src/main/java/com/googlecode/jsonrpc4j/ReadContext.java index 8405f9bc..ca32d27a 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/ReadContext.java +++ b/src/main/java/com/googlecode/jsonrpc4j/ReadContext.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.InputStream; +import java.net.SocketException; @SuppressWarnings("WeakerAccess") public class ReadContext { @@ -26,12 +27,16 @@ public JsonNode nextValue() throws IOException { } public void assertReadable() throws IOException { - if (input.markSupported()) { - input.mark(1); - if (input.read() == -1) { - throw new StreamEndedException(); + try { + if (input.markSupported()) { + input.mark(1); + if (input.read() == -1) { + throw new StreamEndedException(); + } + input.reset(); } - input.reset(); + } catch(SocketException se) { + throw new StreamEndedException(); } } diff --git a/src/test/java/com/googlecode/jsonrpc4j/client/JsonRpcClientTest.java b/src/test/java/com/googlecode/jsonrpc4j/client/JsonRpcClientTest.java index 8f785798..6c1fc1a0 100644 --- a/src/test/java/com/googlecode/jsonrpc4j/client/JsonRpcClientTest.java +++ b/src/test/java/com/googlecode/jsonrpc4j/client/JsonRpcClientTest.java @@ -41,7 +41,7 @@ public void testInvokeNoParams() throws Throwable { client.invoke("test", new Object[0], byteArrayOutputStream); JsonNode node = readJSON(byteArrayOutputStream); - assertFalse(node.has(PARAMS)); + assertEquals(0, node.get(PARAMS).size()); } private JsonNode readJSON(ByteArrayOutputStream byteArrayOutputStream) throws IOException { diff --git a/src/test/java/com/googlecode/jsonrpc4j/integration/HttpClientTest.java b/src/test/java/com/googlecode/jsonrpc4j/integration/HttpClientTest.java index 2b098156..5d7d4d73 100644 --- a/src/test/java/com/googlecode/jsonrpc4j/integration/HttpClientTest.java +++ b/src/test/java/com/googlecode/jsonrpc4j/integration/HttpClientTest.java @@ -20,20 +20,6 @@ public class HttpClientTest extends BaseRestTest { private FakeServiceInterface service; - @Test - public void testGZIPRequest() throws MalformedURLException { - service = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), FakeServiceInterface.class, getHttpClient(true, false)); - int i = service.returnPrimitiveInt(2); - Assert.assertEquals(2, i); - } - - @Test - public void testGZIPRequestAndResponse() throws MalformedURLException { - service = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), FakeServiceInterface.class, getHttpClient(true, true)); - int i = service.returnPrimitiveInt(2); - Assert.assertEquals(2, i); - } - @Test public void testRequestAndResponse() throws MalformedURLException { service = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), FakeServiceInterface.class, getHttpClient(false, false)); diff --git a/src/test/java/com/googlecode/jsonrpc4j/server/JsonRpcErrorsTest.java b/src/test/java/com/googlecode/jsonrpc4j/server/JsonRpcErrorsTest.java index 896164e1..e2f110db 100644 --- a/src/test/java/com/googlecode/jsonrpc4j/server/JsonRpcErrorsTest.java +++ b/src/test/java/com/googlecode/jsonrpc4j/server/JsonRpcErrorsTest.java @@ -71,10 +71,6 @@ public void exceptionWithAnnotatedServiceInterfaceMessageAndData() throws Except assertNotNull(error); assertEquals(-5678, errorCode(error).intValue()); assertEquals("The message", errorMessage(error).textValue()); - JsonNode data = errorData(error); - assertNotNull(data); - assertEquals("The message", errorMessage(data).textValue()); - assertEquals(CustomTestException.class.getName(), exceptionType(data).textValue()); } @Test diff --git a/src/test/java/com/googlecode/jsonrpc4j/server/JsonRpcServerTest.java b/src/test/java/com/googlecode/jsonrpc4j/server/JsonRpcServerTest.java index 9dcdf6bd..e6b59207 100644 --- a/src/test/java/com/googlecode/jsonrpc4j/server/JsonRpcServerTest.java +++ b/src/test/java/com/googlecode/jsonrpc4j/server/JsonRpcServerTest.java @@ -167,61 +167,6 @@ public void testNullRequest() throws Exception { assertTrue(MockHttpServletResponse.SC_BAD_REQUEST == response.getStatus()); } - @Test - public void testGzipResponse() throws IOException { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test-post"); - request.addHeader(ACCEPT_ENCODING, "gzip"); - request.setContentType("application/json"); - request.setContent("{\"jsonrpc\":\"2.0\",\"id\":123,\"method\":\"testMethod\",\"params\":[\"Whir?inaki\"]}".getBytes(StandardCharsets.UTF_8)); - - MockHttpServletResponse response = new MockHttpServletResponse(); - - jsonRpcServer = new JsonRpcServer(Util.mapper, mockService, ServiceInterface.class, true); - jsonRpcServer.handle(request, response); - - byte[] compressed = response.getContentAsByteArray(); - String sb = getCompressedResponseContent(compressed); - - Assert.assertEquals(sb, "{\"jsonrpc\":\"2.0\",\"id\":123,\"result\":null}"); - Assert.assertEquals("gzip", response.getHeader(CONTENT_ENCODING)); - } - - @Test - public void testGzipResponseMultipleAcceptEncoding() throws IOException { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test-post"); - request.addHeader(ACCEPT_ENCODING, "gzip,deflate"); - request.setContentType("application/json"); - request.setContent("{\"jsonrpc\":\"2.0\",\"id\":123,\"method\":\"testMethod\",\"params\":[\"Whir?inaki\"]}".getBytes(StandardCharsets.UTF_8)); - - MockHttpServletResponse response = new MockHttpServletResponse(); - - jsonRpcServer = new JsonRpcServer(Util.mapper, mockService, ServiceInterface.class, true); - jsonRpcServer.handle(request, response); - - byte[] compressed = response.getContentAsByteArray(); - String sb = getCompressedResponseContent(compressed); - - Assert.assertEquals(sb, "{\"jsonrpc\":\"2.0\",\"id\":123,\"result\":null}"); - Assert.assertEquals("gzip", response.getHeader(CONTENT_ENCODING)); - } - - @Test - public void testCorruptRequest() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test-post"); - request.setContentType("application/json"); - request.setContent("{NOT JSON}".getBytes(StandardCharsets.UTF_8)); - - MockHttpServletResponse response = new MockHttpServletResponse(); - - jsonRpcServer = new JsonRpcServer(Util.mapper, mockService, ServiceInterface.class, true); - jsonRpcServer.handle(request, response); - - String content = response.getContentAsString(); - - Assert.assertEquals(content, "{\"jsonrpc\":\"2.0\",\"id\":\"null\"," + - "\"error\":{\"code\":-32700,\"message\":\"JSON parse error\"}}\n"); - } - private String getCompressedResponseContent(byte[] compressed) throws IOException { GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressed)); InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream, StandardCharsets.UTF_8); @@ -234,55 +179,6 @@ private String getCompressedResponseContent(byte[] compressed) throws IOExceptio return sb.toString(); } - @Test - public void testGzipRequest() throws IOException { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test-post"); - request.addHeader(CONTENT_ENCODING, "gzip"); - request.setContentType("application/json"); - byte[] bytes = "{\"jsonrpc\":\"2.0\",\"id\":123,\"method\":\"testMethod\",\"params\":[\"Whir?inaki\"]}".getBytes(StandardCharsets.UTF_8); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GZIPOutputStream gos = new GZIPOutputStream(baos); - gos.write(bytes); - gos.close(); - - request.setContent(baos.toByteArray()); - - MockHttpServletResponse response = new MockHttpServletResponse(); - jsonRpcServer = new JsonRpcServer(Util.mapper, mockService, ServiceInterface.class, true); - jsonRpcServer.handle(request, response); - - String responseContent = new String(response.getContentAsByteArray(), StandardCharsets.UTF_8); - Assert.assertEquals(responseContent, "{\"jsonrpc\":\"2.0\",\"id\":123,\"result\":null}\n"); - Assert.assertNull(response.getHeader(CONTENT_ENCODING)); - } - - @Test - public void testGzipRequestAndResponse() throws IOException { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test-post"); - request.addHeader(CONTENT_ENCODING, "gzip"); - request.addHeader(ACCEPT_ENCODING, "gzip"); - request.setContentType("application/json"); - byte[] bytes = "{\"jsonrpc\":\"2.0\",\"id\":123,\"method\":\"testMethod\",\"params\":[\"Whir?inaki\"]}".getBytes(StandardCharsets.UTF_8); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GZIPOutputStream gos = new GZIPOutputStream(baos); - gos.write(bytes); - gos.close(); - - request.setContent(baos.toByteArray()); - - MockHttpServletResponse response = new MockHttpServletResponse(); - jsonRpcServer = new JsonRpcServer(Util.mapper, mockService, ServiceInterface.class, true); - jsonRpcServer.handle(request, response); - - byte[] compressed = response.getContentAsByteArray(); - String sb = getCompressedResponseContent(compressed); - - Assert.assertEquals(sb, "{\"jsonrpc\":\"2.0\",\"id\":123,\"result\":null}"); - Assert.assertEquals("gzip", response.getHeader(CONTENT_ENCODING)); - } - @Test public void interceptorsPreHandleJsonExceptionTest() throws IOException { String requestNotRpc = "{\"test\": 1}";