diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3f3a45a602..1628d676d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Detect renamed files in git and hg diffs ([#1157](https://github.com/scm-manager/scm-manager/pull/1157))
+### Fixed
+- Resolved conflicting dependencies for scm-webapp ([#1159](https://github.com/scm-manager/scm-manager/pull/1159))
+
## [2.0.0-rc8] - 2020-05-08
### Added
- Add iconStyle + onClick option and story shot for icon component ([#1100](https://github.com/scm-manager/scm-manager/pull/1100))
diff --git a/Jenkinsfile b/Jenkinsfile
index 7b0e8e9f08..53819fc228 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -206,6 +206,7 @@ Maven setupMavenBuild() {
def logConf = "scm-webapp/src/main/resources/logback.ci.xml"
mvn.additionalArgs += " -Dlogback.configurationFile=${logConf}"
mvn.additionalArgs += " -Dscm-it.logbackConfiguration=${logConf}"
+ mvn.additionalArgs += " -Dsonar.coverage.exclusions=**/*.test.ts,**/*.test.tsx,**/*.stories.tsx"
if (isMainBranch() || isReleaseBranch()) {
// Release starts javadoc, which takes very long, so do only for certain branches
diff --git a/pom.xml b/pom.xml
index b1e63cdadc..9eed838b68 100644
--- a/pom.xml
+++ b/pom.xml
@@ -241,6 +241,16 @@
org.jboss.resteasy
resteasy-core
${resteasy.version}
+
+
+ org.jboss.spec.javax.ws.rs
+ jboss-jaxrs-api_2.1_spec
+
+
+ org.jboss.spec.javax.xml.bind
+ jboss-jaxb-api_2.3_spec
+
+
@@ -253,6 +263,12 @@
org.jboss.resteasy
resteasy-jaxb-provider
${resteasy.version}
+
+
+ org.jboss.spec.javax.xml.bind
+ jboss-jaxb-api_2.3_spec
+
+
@@ -267,6 +283,30 @@
${resteasy.version}
+
+ org.jboss.resteasy
+ resteasy-client-api
+ ${resteasy.version}
+
+
+ org.jboss.spec.javax.ws.rs
+ jboss-jaxrs-api_2.1_spec
+
+
+
+
+
+ org.jboss.resteasy
+ resteasy-client
+ ${resteasy.version}
+
+
+ org.jboss.spec.javax.ws.rs
+ jboss-jaxrs-api_2.1_spec
+
+
+
+
org.jboss.resteasy
resteasy-guice
@@ -277,6 +317,12 @@
org.jboss.resteasy
resteasy-servlet-initializer
${resteasy.version}
+
+
+ org.jboss.spec.javax.ws.rs
+ jboss-jaxrs-api_2.1_spec
+
+
@@ -437,8 +489,8 @@
- javax.xml.bind
- jaxb-api
+ jakarta.xml.bind
+ jakarta.xml.bind-api
${jaxb.version}
@@ -448,12 +500,6 @@
${jaxb.version}
-
- javax.activation
- activation
- 1.1.1
-
-
@@ -901,20 +947,20 @@
2.28.2
- 1.3
+ 2.1
5.6.2
1.7.30
1.2.3
- 3.0.1
+ 3.1.0
2.1.1
4.5.3.Final
1.19.4
2.11.0
4.2.3
- 2.3.1
+ 2.3.2
6.1.4.Final
diff --git a/scm-core/pom.xml b/scm-core/pom.xml
index 5ba07696a4..7d78979d96 100644
--- a/scm-core/pom.xml
+++ b/scm-core/pom.xml
@@ -173,8 +173,8 @@
- javax.xml.bind
- jaxb-api
+ jakarta.xml.bind
+ jakarta.xml.bind-api
@@ -182,11 +182,6 @@
jaxb-runtime
-
- javax.activation
- activation
-
-
diff --git a/scm-core/src/main/java/sonia/scm/filter/GZipResponseStream.java b/scm-core/src/main/java/sonia/scm/filter/GZipResponseStream.java
index e99ccf9b80..2693fdf3b0 100644
--- a/scm-core/src/main/java/sonia/scm/filter/GZipResponseStream.java
+++ b/scm-core/src/main/java/sonia/scm/filter/GZipResponseStream.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.filter;
//~--- non-JDK imports --------------------------------------------------------
@@ -39,6 +39,7 @@ import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
/**
@@ -245,6 +246,20 @@ public class GZipResponseStream extends ServletOutputStream
return closed;
}
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+ try {
+ writeListener.onWritePossible();
+ } catch (IOException e) {
+ logger.debug("could not call writeListener.onWritePossible()", e);
+ }
+ }
+
//~--- fields ---------------------------------------------------------------
/** Field description */
diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletRequest.java b/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletRequest.java
index 04f725d4ed..e674d1d2e2 100644
--- a/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletRequest.java
+++ b/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletRequest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.web.filter;
//~--- non-JDK imports --------------------------------------------------------
@@ -36,6 +36,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
@@ -197,6 +198,25 @@ public class BufferedHttpServletRequest extends HttpServletRequestWrapper
return bais.read(buf, off, len);
}
+ @Override
+ public boolean isFinished() {
+ return bais.available() == 0;
+ }
+
+ @Override
+ public boolean isReady() {
+ return bais.available() > 0;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ try {
+ readListener.onDataAvailable();
+ } catch (IOException e) {
+ logger.debug("could not call readListener.onDataAvailable()", e);
+ }
+ }
+
//~--- fields -------------------------------------------------------------
/** Field description */
diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletResponse.java b/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletResponse.java
index 5d647659e5..0d13ed752f 100644
--- a/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletResponse.java
+++ b/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletResponse.java
@@ -21,11 +21,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.web.filter;
//~--- JDK imports ------------------------------------------------------------
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
@@ -37,6 +40,7 @@ import java.util.Map;
import java.util.Set;
import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
@@ -48,6 +52,8 @@ import javax.servlet.http.HttpServletResponseWrapper;
public class BufferedHttpServletResponse extends HttpServletResponseWrapper
{
+ private static final Logger LOG = LoggerFactory.getLogger(BufferedHttpServletResponse.class);
+
/**
* Constructs ...
*
@@ -445,6 +451,20 @@ public class BufferedHttpServletResponse extends HttpServletResponseWrapper
baos.write(param);
}
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+ try {
+ writeListener.onWritePossible();
+ } catch (IOException e) {
+ LOG.debug("could not call writeListener.onWritePossible()", e);
+ }
+ }
+
//~--- fields -------------------------------------------------------------
/** Field description */
diff --git a/scm-it/pom.xml b/scm-it/pom.xml
index 146a7b33b2..bf9b4e6d78 100644
--- a/scm-it/pom.xml
+++ b/scm-it/pom.xml
@@ -102,7 +102,7 @@
io.rest-assured
rest-assured
- 3.1.0
+ 4.3.0
test
diff --git a/scm-it/src/test/java/sonia/scm/it/RoleITCase.java b/scm-it/src/test/java/sonia/scm/it/RoleITCase.java
index e6b8ad5932..21f4c391ee 100644
--- a/scm-it/src/test/java/sonia/scm/it/RoleITCase.java
+++ b/scm-it/src/test/java/sonia/scm/it/RoleITCase.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.it;
import org.apache.http.HttpStatus;
@@ -66,7 +66,7 @@ public class RoleITCase {
given(VndMediaType.REPOSITORY_ROLE)
.when()
- .content("{" +
+ .body("{" +
"\"name\": \"" + ROLE_NAME + "\"," +
"\"verbs\": [\"read\",\"permissionRead\"]" +
"}")
@@ -84,7 +84,7 @@ public class RoleITCase {
given(VndMediaType.REPOSITORY_PERMISSION)
.when()
- .content("{\n" +
+ .body("{\n" +
"\t\"role\": \"" + ROLE_NAME + "\",\n" +
"\t\"name\": \"" + USER + "\",\n" +
"\t\"groupPermission\": false\n" +
diff --git a/scm-it/src/test/java/sonia/scm/it/utils/TestData.java b/scm-it/src/test/java/sonia/scm/it/utils/TestData.java
index 0df93cc2bd..14265c0052 100644
--- a/scm-it/src/test/java/sonia/scm/it/utils/TestData.java
+++ b/scm-it/src/test/java/sonia/scm/it/utils/TestData.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.it.utils;
import io.restassured.response.ValidatableResponse;
@@ -86,7 +86,7 @@ public class TestData {
String admin = isAdmin ? "true" : "false";
given(VndMediaType.USER)
.when()
- .content(new StringBuilder()
+ .body(new StringBuilder()
.append(" {\n")
.append(" \"active\": true,\n")
.append(" \"admin\": ").append(admin).append(",\n")
@@ -124,7 +124,7 @@ public class TestData {
LOG.info("create group with group name: {} and description {}", groupName, desc);
given(VndMediaType.GROUP)
.when()
- .content(getGroupJson(groupName,desc))
+ .body(getGroupJson(groupName,desc))
.post(getGroupsUrl())
.then()
.statusCode(HttpStatus.SC_CREATED)
@@ -136,7 +136,7 @@ public class TestData {
LOG.info("create permission with name {} and verbs {} using the endpoint: {}", username, verbs, defaultPermissionUrl);
given(VndMediaType.REPOSITORY_PERMISSION)
.when()
- .content("{\n" +
+ .body("{\n" +
"\t\"verbs\": " + verbs.stream().collect(Collectors.joining("\",\"", "[\"", "\"]")) + ",\n" +
"\t\"name\": \"" + username + "\",\n" +
"\t\"groupPermission\": false\n" +
diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java
index a3f3895770..486cffde8c 100644
--- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java
+++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.web;
import org.junit.Test;
@@ -33,6 +33,7 @@ import sonia.scm.repository.spi.ScmProviderHttpServlet;
import sonia.scm.util.HttpUtil;
import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
@@ -47,40 +48,40 @@ import static org.mockito.Mockito.when;
/**
* Unit tests for {@link GitPermissionFilter}.
- *
+ *
* Created by omilke on 19.05.2017.
*/
@RunWith(MockitoJUnitRunner.class)
public class GitPermissionFilterTest {
private final GitPermissionFilter permissionFilter = new GitPermissionFilter(new ScmConfiguration(), mock(ScmProviderHttpServlet.class));
-
+
@Mock
private HttpServletResponse response;
-
+
@Test
public void testIsWriteRequest() {
HttpServletRequest request = mockRequestWithMethodAndRequestURI("POST", "/scm/git/fanzy-project/git-receive-pack");
assertThat(permissionFilter.isWriteRequest(request), is(true));
-
+
request = mockRequestWithMethodAndRequestURI("GET", "/scm/git/fanzy-project/info/refs?service=git-receive-pack");
assertThat(permissionFilter.isWriteRequest(request), is(true));
-
+
request = mockRequestWithMethodAndRequestURI("GET", "/scm/git/fanzy-project/info/refs?service=some-other-service");
assertThat(permissionFilter.isWriteRequest(request), is(false));
-
+
request = mockRequestWithMethodAndRequestURI(
- "PUT",
+ "PUT",
"/scm/git/git-lfs-demo.git/info/lfs/objects/8fcebeb5698230685f92028e560f8f1683ebc15ec82a620ffad5c12a3c19bdec"
);
assertThat(permissionFilter.isWriteRequest(request), is(true));
-
+
request = mockRequestWithMethodAndRequestURI(
- "GET",
+ "GET",
"/scm/git/git-lfs-demo.git/info/lfs/objects/8fcebeb5698230685f92028e560f8f1683ebc15ec82a620ffad5c12a3c19bdec"
);
assertThat(permissionFilter.isWriteRequest(request), is(false));
-
+
request = mockRequestWithMethodAndRequestURI("POST", "/scm/git/git-lfs-demo.git/info/lfs/objects/batch");
assertThat(permissionFilter.isWriteRequest(request), is(false));
}
@@ -97,45 +98,45 @@ public class GitPermissionFilterTest {
@Test
public void testSendNotEnoughPrivilegesErrorAsBrowser() throws IOException {
HttpServletRequest request = mockGitReceivePackServiceRequest();
-
+
permissionFilter.sendNotEnoughPrivilegesError(request, response);
-
+
verify(response).sendError(HttpServletResponse.SC_FORBIDDEN);
}
-
+
@Test
public void testSendNotEnoughPrivilegesErrorAsGitClient() throws IOException {
verifySendNotEnoughPrivilegesErrorAsGitClient("git/2.9.3");
}
-
+
@Test
public void testSendNotEnoughPrivilegesErrorAsJGitClient() throws IOException {
verifySendNotEnoughPrivilegesErrorAsGitClient("JGit/4.2");
}
-
+
private void verifySendNotEnoughPrivilegesErrorAsGitClient(String userAgent) throws IOException {
HttpServletRequest request = mockGitReceivePackServiceRequest();
when(request.getHeader(HttpUtil.HEADER_USERAGENT)).thenReturn(userAgent);
-
+
CapturingServletOutputStream stream = new CapturingServletOutputStream();
when(response.getOutputStream()).thenReturn(stream);
-
+
permissionFilter.sendNotEnoughPrivilegesError(request, response);
-
+
verify(response).setStatus(HttpServletResponse.SC_OK);
- assertThat(stream.toString(), containsString("privileges"));
+ assertThat(stream.toString(), containsString("privileges"));
}
-
+
private HttpServletRequest mockGitReceivePackServiceRequest() {
HttpServletRequest request = mockRequestWithMethodAndRequestURI("GET", "/git/info/refs");
when(request.getParameter("service")).thenReturn("git-receive-pack");
return request;
}
-
+
private static class CapturingServletOutputStream extends ServletOutputStream {
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
+
@Override
public void write(int b) throws IOException {
baos.write(b);
@@ -145,11 +146,21 @@ public class GitPermissionFilterTest {
public void close() throws IOException {
baos.close();
}
-
+
@Override
public String toString() {
return baos.toString();
}
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+
+ }
}
-
+
}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletInputStream.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletInputStream.java
index 9262836d85..1f435703df 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletInputStream.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletInputStream.java
@@ -21,11 +21,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.web;
import com.google.common.base.Preconditions;
+import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -76,4 +77,19 @@ public class HgServletInputStream extends ServletInputStream {
public void close() throws IOException {
original.close();
}
+
+ @Override
+ public boolean isFinished() {
+ return original.isFinished();
+ }
+
+ @Override
+ public boolean isReady() {
+ return original.isReady();
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ original.setReadListener(readListener);
+ }
}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/HgServletInputStreamTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/HgServletInputStreamTest.java
index b1c2ed60cd..1f06ede4c1 100644
--- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/HgServletInputStreamTest.java
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/HgServletInputStreamTest.java
@@ -21,13 +21,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.web;
import com.google.common.base.Charsets;
import com.google.common.io.ByteStreams;
import org.junit.Test;
+import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -69,6 +70,20 @@ public class HgServletInputStreamTest {
public int read() {
return input.read();
}
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ }
}
}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/WireProtocolTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/WireProtocolTest.java
index 80f4094d48..29bd1b41a2 100644
--- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/WireProtocolTest.java
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/WireProtocolTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.web;
import com.google.common.base.Charsets;
@@ -31,6 +31,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
+import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
@@ -181,6 +182,19 @@ public class WireProtocolTest {
return input.read();
}
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ }
}
}
diff --git a/scm-plugins/scm-legacy-plugin/pom.xml b/scm-plugins/scm-legacy-plugin/pom.xml
index 46bc9d99f2..0010f81b11 100644
--- a/scm-plugins/scm-legacy-plugin/pom.xml
+++ b/scm-plugins/scm-legacy-plugin/pom.xml
@@ -36,9 +36,9 @@
Support migrated repository urls and v1 passwords
2.0.0-SNAPSHOT
smp
-
+
-
+
@@ -48,13 +48,6 @@
provided
-
- javax.ws.rs
- jsr311-api
- 1.1.1
- compile
-
-
diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml
index bf5fa38c28..ff4e93594d 100644
--- a/scm-webapp/pom.xml
+++ b/scm-webapp/pom.xml
@@ -146,6 +146,12 @@
${jackson.version}
+
+ javax.ws.rs
+ javax.ws.rs-api
+
+
+
@@ -197,21 +203,15 @@
- org.glassfish
- javax.el
- 3.0.1-b11
-
-
-
- javax.xml.bind
- jaxb-api
- 2.3.1
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ ${jaxb.version}
org.glassfish.jaxb
jaxb-runtime
- 2.3.0
+ ${jaxb.version}
@@ -438,13 +438,6 @@
-
- commons-logging
- commons-logging
- 1.1.3
- provided
-
-
org.projectlombok
lombok
@@ -654,6 +647,20 @@
+
+ org.basepom.maven
+ duplicate-finder-maven-plugin
+ 1.3.0
+
+ false
+ false
+ false
+ false
+ true
+ true
+ false
+
+
scm-webapp
diff --git a/scm-webapp/src/main/java/sonia/scm/api/InvalidFormatExceptionMapper.java b/scm-webapp/src/main/java/sonia/scm/api/InvalidFormatExceptionMapper.java
new file mode 100644
index 0000000000..97dd96a23a
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/api/InvalidFormatExceptionMapper.java
@@ -0,0 +1,59 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package sonia.scm.api;
+
+import com.fasterxml.jackson.databind.exc.InvalidFormatException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import sonia.scm.api.v2.resources.ErrorDto;
+import sonia.scm.web.VndMediaType;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import java.util.Collections;
+
+@Provider
+public class InvalidFormatExceptionMapper implements ExceptionMapper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(InvalidFormatExceptionMapper.class);
+
+ private static final String ERROR_CODE = "2qRyyaVcJ1";
+
+ @Override
+ public Response toResponse(InvalidFormatException exception) {
+ LOG.trace("got invalid format in json: {}", exception.getMessage());
+ ErrorDto errorDto = new ErrorDto();
+ errorDto.setMessage("invalid format in json content: " + exception.getMessage());
+ errorDto.setContext(Collections.emptyList());
+ errorDto.setErrorCode(ERROR_CODE);
+ errorDto.setTransactionId(MDC.get("transaction_id"));
+ return Response.status(Response.Status.BAD_REQUEST)
+ .entity(errorDto)
+ .type(VndMediaType.ERROR_TYPE)
+ .build();
+ }
+}
diff --git a/scm-webapp/src/main/resources/locales/de/plugins.json b/scm-webapp/src/main/resources/locales/de/plugins.json
index 8c5c88e0f8..314dac3de4 100644
--- a/scm-webapp/src/main/resources/locales/de/plugins.json
+++ b/scm-webapp/src/main/resources/locales/de/plugins.json
@@ -215,6 +215,10 @@
"8nRuFzjss1": {
"displayName": "Fehler beim Löschen falscher Downloads",
"description": "Ein fehlerhaft heruntergeladenes Plugin konnte nicht gelöscht werden. Bitte prüfen Sie die Server Logs und löschen die Datei manuell."
+ },
+ "2qRyyaVcJ1": {
+ "displayName": "Ungültig formatiertes Element",
+ "description": "Die Eingabe beinhaltete unfültige Formate. Bitte prüfen Sie die Server Logs für genauere Informationen."
}
},
"namespaceStrategies": {
diff --git a/scm-webapp/src/main/resources/locales/en/plugins.json b/scm-webapp/src/main/resources/locales/en/plugins.json
index 998e796bac..fba82da650 100644
--- a/scm-webapp/src/main/resources/locales/en/plugins.json
+++ b/scm-webapp/src/main/resources/locales/en/plugins.json
@@ -215,6 +215,10 @@
"8nRuFzjss1": {
"displayName": "Error while cleaning up failed plugin",
"description": "A failed plugin download could not be removed correctly. Please check the server log and remove the plugin manually."
+ },
+ "2qRyyaVcJ1": {
+ "displayName": "Invalid format in element",
+ "description": "The input had some invalid formats. Please check the server log for further information."
}
},
"namespaceStrategies": {
diff --git a/scm-webapp/src/test/java/sonia/scm/ProxyPushStateDispatcherTest.java b/scm-webapp/src/test/java/sonia/scm/ProxyPushStateDispatcherTest.java
index 3fbbfafdcd..422edb2ce5 100644
--- a/scm-webapp/src/test/java/sonia/scm/ProxyPushStateDispatcherTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/ProxyPushStateDispatcherTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm;
import com.google.common.base.Charsets;
@@ -33,16 +33,23 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
+import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.net.HttpURLConnection;
-import java.util.*;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;
@@ -173,7 +180,7 @@ public class ProxyPushStateDispatcherTest {
private class DevServletInputStream extends ServletInputStream {
- private InputStream inputStream;
+ private ByteArrayInputStream inputStream;
private DevServletInputStream(String content) {
inputStream = new ByteArrayInputStream(content.getBytes(Charsets.UTF_8));
@@ -183,6 +190,20 @@ public class ProxyPushStateDispatcherTest {
public int read() throws IOException {
return inputStream.read();
}
+
+ @Override
+ public boolean isReady() {
+ return inputStream.available() > 0;
+ }
+
+ @Override
+ public boolean isFinished() {
+ return inputStream.available() == 0;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+ }
}
private class DevServletOutputStream extends ServletOutputStream {
@@ -193,6 +214,15 @@ public class ProxyPushStateDispatcherTest {
public void write(int b) {
stream.write(b);
}
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+ }
}
}
diff --git a/scm-webapp/src/test/java/sonia/scm/WebResourceServletTest.java b/scm-webapp/src/test/java/sonia/scm/WebResourceServletTest.java
index 8364a53000..21727e56b3 100644
--- a/scm-webapp/src/test/java/sonia/scm/WebResourceServletTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/WebResourceServletTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm;
import com.google.common.base.Charsets;
@@ -37,6 +37,7 @@ import sonia.scm.plugin.PluginLoader;
import sonia.scm.plugin.UberWebResourceLoader;
import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
@@ -152,6 +153,15 @@ public class WebResourceServletTest {
public void write(int b) {
buffer.write(b);
}
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+ }
}
}
diff --git a/scm-webapp/src/test/java/sonia/scm/api/InvalidFormatExceptionMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/InvalidFormatExceptionMapperTest.java
new file mode 100644
index 0000000000..c06da77c92
--- /dev/null
+++ b/scm-webapp/src/test/java/sonia/scm/api/InvalidFormatExceptionMapperTest.java
@@ -0,0 +1,74 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package sonia.scm.api;
+
+import org.jboss.resteasy.mock.MockDispatcherFactory;
+import org.jboss.resteasy.mock.MockHttpRequest;
+import org.jboss.resteasy.mock.MockHttpResponse;
+import org.jboss.resteasy.spi.Dispatcher;
+import org.junit.jupiter.api.Test;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class InvalidFormatExceptionMapperTest {
+
+ @Test
+ void shouldMapInvalidFormatExceptionDueToInvalidEnum() throws URISyntaxException, UnsupportedEncodingException {
+ Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
+ dispatcher.getRegistry().addSingletonResource(new SimpleResource());
+ dispatcher.getProviderFactory().registerProvider(InvalidFormatExceptionMapper.class);
+
+ MockHttpRequest request = MockHttpRequest
+ .post("/")
+ .contentType("application/json")
+ .content("{\"e\": \"NONE\"}".getBytes());
+ MockHttpResponse response = new MockHttpResponse();
+
+ dispatcher.invoke(request, response);
+
+ assertThat(response.getStatus()).isEqualTo(400);
+ assertThat(response.getContentAsString()).contains("2qRyyaVcJ1");
+ }
+
+ @Path("/")
+ static class SimpleResource {
+ @POST
+ public void post(ObjectWithEnum o) {
+ }
+ }
+
+ static class ObjectWithEnum {
+ public Enum e;
+ }
+
+ enum Enum {
+ ONE, TWO
+ }
+}
diff --git a/scm-webapp/src/test/java/sonia/scm/lifecycle/RestartServletTest.java b/scm-webapp/src/test/java/sonia/scm/lifecycle/RestartServletTest.java
index 324f43dcb7..eeae7c697a 100644
--- a/scm-webapp/src/test/java/sonia/scm/lifecycle/RestartServletTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/lifecycle/RestartServletTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
+
package sonia.scm.lifecycle;
import com.github.legman.Subscribe;
@@ -34,6 +34,7 @@ import sonia.scm.Stage;
import sonia.scm.event.ScmEventBus;
import sonia.scm.event.ScmTestEventBus;
+import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -128,6 +129,21 @@ public class RestartServletTest {
private ServletInputStream createServletInputStream(final InputStream inputStream) {
return new ServletInputStream() {
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+
+ }
+
@Override
public int read() throws IOException {
return inputStream.read();