diff --git a/pom.xml b/pom.xml index b1e63cdadc..a25f3bda2e 100644 --- a/pom.xml +++ b/pom.xml @@ -907,7 +907,7 @@ 1.7.30 1.2.3 - 3.0.1 + 3.1.0 2.1.1 4.5.3.Final 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-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-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/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();