This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-engine.git
The following commit(s) were added to refs/heads/master by this push:
new 47c0c96 SLING-11829 : Response should be resetted before invoking
error filters
47c0c96 is described below
commit 47c0c965a49c81bc4725965896ed3db39cfff6ac
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Fri Apr 14 15:17:38 2023 +0200
SLING-11829 : Response should be resetted before invoking error filters
---
.../sling/engine/impl/DefaultErrorHandler.java | 44 +++------
.../engine/impl/SlingHttpServletResponseImpl.java | 2 +-
.../engine/impl/SlingRequestProcessorImpl.java | 7 +-
.../impl/filter/AbstractSlingFilterChain.java | 10 +-
.../sling/engine/impl/filter/ErrorFilterChain.java | 105 +++++++++++++++++++++
.../engine/impl/filter/ErrorFilterChainStatus.java | 49 ----------
.../impl/filter/ErrorFilterChainThrowable.java | 46 ---------
.../sling/engine/impl/DefaultErrorHandlerTest.java | 62 ------------
.../engine/impl/filter/ErrorFilterChainTest.java | 81 ++++++++++++++++
9 files changed, 209 insertions(+), 197 deletions(-)
diff --git
a/src/main/java/org/apache/sling/engine/impl/DefaultErrorHandler.java
b/src/main/java/org/apache/sling/engine/impl/DefaultErrorHandler.java
index bce50e6..fcc26fb 100644
--- a/src/main/java/org/apache/sling/engine/impl/DefaultErrorHandler.java
+++ b/src/main/java/org/apache/sling/engine/impl/DefaultErrorHandler.java
@@ -37,8 +37,9 @@ import org.slf4j.LoggerFactory;
/**
* The <code>DefaultErrorHandler</code> is used by the
- * {@link SlingRequestProcessorImpl} as long as no {@link ErrorHandler} service
- * is registered.
+ * {@link SlingRequestProcessorImpl} for error handling. It works
+ * in combination with the error filter chain. If a {@link ErrorHandler}
service
+ * is registered, the actual response generated is delegated to that service.
*/
public class DefaultErrorHandler implements ErrorHandler {
@@ -48,7 +49,7 @@ public class DefaultErrorHandler implements ErrorHandler {
private volatile String serverInfo = ProductInfoProvider.PRODUCT_NAME;
/** Use this if not null, and if that fails output a report about that
failure */
- private ErrorHandler delegate;
+ private volatile ErrorHandler delegate;
void setServerInfo(final String serverInfo) {
this.serverInfo = (serverInfo != null)
@@ -56,14 +57,10 @@ public class DefaultErrorHandler implements ErrorHandler {
: ProductInfoProvider.PRODUCT_NAME;
}
- public void setDelegate(ErrorHandler eh) {
+ public void setDelegate(final ErrorHandler eh) {
delegate = eh;
}
- public ErrorHandler getDelegate() {
- return delegate;
- }
-
private void delegateFailed(int originalStatus, String originalMessage,
Throwable t, HttpServletRequest request, HttpServletResponse response) throws
IOException {
// don't include Throwable in the response, gives too much information
final String m = "Error handler failed:" + t.getClass().getName();
@@ -76,6 +73,7 @@ public class DefaultErrorHandler implements ErrorHandler {
return;
}
// reset the response to clear headers and body
+ // the error filters are NOT called in this edge case
response.reset();
sendError(originalStatus, originalMessage, null, request, response);
}
@@ -99,20 +97,11 @@ public class DefaultErrorHandler implements ErrorHandler {
final SlingHttpServletRequest request,
final SlingHttpServletResponse response)
throws IOException {
- if (response.isCommitted()) {
- log.warn(
- "handleError: Response already committed; cannot send error "
- + status + " : " + message);
- return;
- }
- // reset the response to clear headers and body
- response.reset();
-
// If we have a delegate let it handle the error
if (delegate != null) {
try {
delegate.handleError(status, message, request, response);
- } catch(Exception e) {
+ } catch (final Exception e) {
delegateFailed(status, message, e, request, response);
}
return;
@@ -143,21 +132,12 @@ public class DefaultErrorHandler implements ErrorHandler {
final SlingHttpServletRequest request,
final SlingHttpServletResponse response)
throws IOException {
- if (response.isCommitted()) {
- log.warn(
- "handleError: Response already committed; cannot send error "
- + throwable.getMessage(), throwable);
- return;
- }
- // reset the response to clear headers and body
- response.reset();
-
final int status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
// If we have a delegate let it handle the error
if (delegate != null) {
try {
delegate.handleError(throwable, request, response);
- } catch(Exception e) {
+ } catch (final Exception e) {
delegateFailed(status, throwable.toString(), e, request,
response);
}
return;
@@ -185,8 +165,12 @@ public class DefaultErrorHandler implements ErrorHandler {
response.setContentType("text/html; charset=UTF-8");
final PrintWriter pw = response.getWriter();
- pw.println("<html><head><title>");
- pw.println(ResponseUtil.escapeXml(message));
+ pw.print("<html><head><title>");
+ if ( message == null ) {
+ pw.print("Internal error");
+ } else {
+ pw.print(ResponseUtil.escapeXml(message));
+ }
pw.println("</title></head><body><h1>");
if (throwable != null) {
pw.println(ResponseUtil.escapeXml(throwable.toString()));
diff --git
a/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java
b/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java
index e3b5531..d1712e4 100644
---
a/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java
+++
b/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java
@@ -170,7 +170,7 @@ public class SlingHttpServletResponseImpl extends
HttpServletResponseWrapper imp
public void sendError(int status, String message) throws IOException {
checkCommitted();
- SlingRequestProcessorImpl eh =
getRequestData().getSlingRequestProcessor();
+ final SlingRequestProcessorImpl eh =
getRequestData().getSlingRequestProcessor();
eh.handleError(status, message, requestData.getSlingRequest(), this);
}
diff --git
a/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
b/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
index 7cac8da..38fd705 100644
--- a/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
+++ b/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
@@ -53,8 +53,7 @@ import
org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.engine.SlingRequestProcessor;
import org.apache.sling.engine.impl.debug.RequestInfoProviderImpl;
-import org.apache.sling.engine.impl.filter.ErrorFilterChainStatus;
-import org.apache.sling.engine.impl.filter.ErrorFilterChainThrowable;
+import org.apache.sling.engine.impl.filter.ErrorFilterChain;
import org.apache.sling.engine.impl.filter.FilterHandle;
import org.apache.sling.engine.impl.filter.RequestSlingFilterChain;
import org.apache.sling.engine.impl.filter.ServletFilterManager;
@@ -410,7 +409,7 @@ public class SlingRequestProcessorImpl implements
SlingRequestProcessor {
final SlingHttpServletRequest request,
final SlingHttpServletResponse response) throws IOException {
final FilterHandle[] filters =
filterManager.getFilters(FilterChainType.ERROR);
- final FilterChain processor = new ErrorFilterChainStatus(filters,
errorHandler, status, message);
+ final FilterChain processor = new ErrorFilterChain(filters,
errorHandler, status, message);
this.handleError(processor, request, response);
}
@@ -418,7 +417,7 @@ public class SlingRequestProcessorImpl implements
SlingRequestProcessor {
final SlingHttpServletRequest request,
final SlingHttpServletResponse response) throws IOException {
final FilterHandle[] filters =
filterManager.getFilters(FilterChainType.ERROR);
- final FilterChain processor = new ErrorFilterChainThrowable(filters,
errorHandler, throwable);
+ final FilterChain processor = new ErrorFilterChain(filters,
errorHandler, throwable);
this.handleError(processor, request, response);
}
diff --git
a/src/main/java/org/apache/sling/engine/impl/filter/AbstractSlingFilterChain.java
b/src/main/java/org/apache/sling/engine/impl/filter/AbstractSlingFilterChain.java
index 90a0a0b..4926bd6 100644
---
a/src/main/java/org/apache/sling/engine/impl/filter/AbstractSlingFilterChain.java
+++
b/src/main/java/org/apache/sling/engine/impl/filter/AbstractSlingFilterChain.java
@@ -33,7 +33,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractSlingFilterChain implements FilterChain {
- private static final Logger LOG =
LoggerFactory.getLogger(AbstractSlingFilterChain.class);
+ protected static final Logger LOG =
LoggerFactory.getLogger(AbstractSlingFilterChain.class);
private FilterHandle[] filters;
@@ -105,7 +105,7 @@ public abstract class AbstractSlingFilterChain implements
FilterChain {
// ---------- internal helper
private void trackFilter(ServletRequest request, FilterHandle filter) {
- RequestData data = RequestData.getRequestData(request);
+ final RequestData data = RequestData.getRequestData(request);
if (data != null) {
RequestProgressTracker tracker = data.getRequestProgressTracker();
tracker.log("Calling filter: {0}",
@@ -115,9 +115,9 @@ public abstract class AbstractSlingFilterChain implements
FilterChain {
}
private void consolidateFilterTimings(ServletRequest request) {
- if (filters != null) {
- RequestData data = RequestData.getRequestData(request);
- RequestProgressTracker tracker = (data != null) ?
data.getRequestProgressTracker() : null;
+ if (filters.length > 0) {
+ final RequestData data = RequestData.getRequestData(request);
+ final RequestProgressTracker tracker = (data != null) ?
data.getRequestProgressTracker() : null;
for (int i = filters.length - 1; i > 0; i--) {
filters[i].trackTime(times[i] - times[i + 1]);
diff --git
a/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChain.java
b/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChain.java
new file mode 100644
index 0000000..57fd367
--- /dev/null
+++ b/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChain.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.engine.impl.filter;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.ErrorHandler;
+
+public class ErrorFilterChain extends AbstractSlingFilterChain {
+
+ private enum Mode {
+ THROWABLE,
+ STATUS
+ };
+
+ private final int status;
+
+ private final String message;
+
+ private final ErrorHandler errorHandler;
+
+ private final Throwable throwable;
+
+ private final Mode mode;
+
+ private boolean firstCall = true;
+
+ public ErrorFilterChain(final FilterHandle[] filters, final ErrorHandler
errorHandler, final int status, final String message) {
+ super(filters);
+ this.mode = Mode.STATUS;
+ this.status = status;
+ this.message = message;
+ this.errorHandler = errorHandler;
+ this.throwable = null;
+ }
+
+ public ErrorFilterChain(final FilterHandle[] filters, final ErrorHandler
errorHandler, final Throwable t) {
+ super(filters);
+ this.mode = Mode.THROWABLE;
+ this.status = 0;
+ this.message = null;
+ this.throwable = t;
+ this.errorHandler = errorHandler;
+ }
+
+ private static final String PREFIX = "handleError: Response already
committed; cannot send error ";
+
+ @Override
+ public void doFilter(final ServletRequest request, final ServletResponse
response) throws ServletException, IOException {
+ if ( firstCall ) {
+ firstCall = false;
+ // do nothing if response is already committed
+ if (response.isCommitted()) {
+ if ( this.mode == Mode.STATUS ) {
+ if ( message == null) {
+ LOG.warn(PREFIX.concat(String.valueOf(status)));
+ } else {
+
LOG.warn(PREFIX.concat(String.valueOf(status)).concat(" : ").concat(message));
+ }
+ } else {
+ if ( throwable.getMessage() != null ) {
+ LOG.warn(PREFIX.concat(throwable.getMessage()),
throwable);
+ } else {
+
LOG.warn(PREFIX.concat(throwable.getClass().getName()), throwable);
+ }
+ }
+ return;
+ }
+ // reset the response to clear headers and body
+ response.reset();
+ }
+ super.doFilter(request, response);
+ }
+
+ protected void render(final SlingHttpServletRequest request, final
SlingHttpServletResponse response)
+ throws IOException, ServletException {
+ if ( this.mode == Mode.STATUS ) {
+ this.errorHandler.handleError(this.status, this.message, request,
response);
+ } else {
+ this.errorHandler.handleError(this.throwable, request, response);
+ }
+ }
+}
diff --git
a/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChainStatus.java
b/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChainStatus.java
deleted file mode 100644
index dac58a4..0000000
---
a/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChainStatus.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sling.engine.impl.filter;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.servlets.ErrorHandler;
-
-
-public class ErrorFilterChainStatus extends AbstractSlingFilterChain {
-
- private final int status;
-
- private final String message;
-
- private final ErrorHandler errorHandler;
-
- public ErrorFilterChainStatus(final FilterHandle[] filters, final
ErrorHandler errorHandler, final int status, final String message) {
- super(filters);
- this.status = status;
- this.message = message;
- this.errorHandler = errorHandler;
- }
-
- protected void render(final SlingHttpServletRequest request,
- final SlingHttpServletResponse response) throws IOException,
ServletException {
- this.errorHandler.handleError(this.status, this.message, request,
response);
- }
-}
diff --git
a/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChainThrowable.java
b/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChainThrowable.java
deleted file mode 100644
index 52f7523..0000000
---
a/src/main/java/org/apache/sling/engine/impl/filter/ErrorFilterChainThrowable.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sling.engine.impl.filter;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.servlets.ErrorHandler;
-
-
-public class ErrorFilterChainThrowable extends AbstractSlingFilterChain {
-
- private final Throwable throwable;
-
- private final ErrorHandler errorHandler;
-
- public ErrorFilterChainThrowable(final FilterHandle[] filters, final
ErrorHandler errorHandler, final Throwable t) {
- super(filters);
- this.throwable = t;
- this.errorHandler = errorHandler;
- }
-
- protected void render(final SlingHttpServletRequest request,
- final SlingHttpServletResponse response) throws IOException,
ServletException {
- this.errorHandler.handleError(this.throwable, request, response);
- }
-}
diff --git
a/src/test/java/org/apache/sling/engine/impl/DefaultErrorHandlerTest.java
b/src/test/java/org/apache/sling/engine/impl/DefaultErrorHandlerTest.java
deleted file mode 100644
index 7974d07..0000000
--- a/src/test/java/org/apache/sling/engine/impl/DefaultErrorHandlerTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sling.engine.impl;
-
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-
-import java.io.IOException;
-
-import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.servlets.ErrorHandler;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-public class DefaultErrorHandlerTest {
-
- @Test public void testResponseCommitted() throws IOException {
- final DefaultErrorHandler handler = new DefaultErrorHandler();
- final ErrorHandler errorHandler = Mockito.mock(ErrorHandler.class);
- handler.setDelegate(errorHandler);
- final SlingHttpServletResponse response =
Mockito.mock(SlingHttpServletResponse.class);
- Mockito.when(response.isCommitted()).thenReturn(true);
-
- handler.handleError(new Exception(), null, response);
- handler.handleError(500, "message", null, response);
-
- Mockito.verify(errorHandler,
never()).handleError(any(Throwable.class), eq(null), eq(response));
- Mockito.verify(errorHandler, never()).handleError(anyInt(),
anyString(), eq(null), eq(response));
- }
-
- @Test public void testResponseNotCommitted() throws IOException {
- final DefaultErrorHandler handler = new DefaultErrorHandler();
- final ErrorHandler errorHandler = Mockito.mock(ErrorHandler.class);
- handler.setDelegate(errorHandler);
- final SlingHttpServletResponse response =
Mockito.mock(SlingHttpServletResponse.class);
- Mockito.when(response.isCommitted()).thenReturn(false);
-
- handler.handleError(new Exception(), null, response);
- Mockito.verify(errorHandler,
times(1)).handleError(any(Throwable.class), eq(null), eq(response));
- handler.handleError(500, "message", null, response);
- Mockito.verify(errorHandler, times(1)).handleError(anyInt(),
anyString(), eq(null), eq(response));
- }
-}
diff --git
a/src/test/java/org/apache/sling/engine/impl/filter/ErrorFilterChainTest.java
b/src/test/java/org/apache/sling/engine/impl/filter/ErrorFilterChainTest.java
new file mode 100644
index 0000000..3da3d3e
--- /dev/null
+++
b/src/test/java/org/apache/sling/engine/impl/filter/ErrorFilterChainTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.engine.impl.filter;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.ErrorHandler;
+import org.apache.sling.engine.impl.DefaultErrorHandler;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ * This class tests the error filter chain in combination with the
+ * {@link DefaultErrorHandler}.
+ */
+public class ErrorFilterChainTest {
+
+ @Test public void testResponseCommitted() throws IOException,
ServletException {
+ final DefaultErrorHandler handler = new DefaultErrorHandler();
+ final ErrorHandler errorHandler = Mockito.mock(ErrorHandler.class);
+ handler.setDelegate(errorHandler);
+
+ final SlingHttpServletRequest request =
Mockito.mock(SlingHttpServletRequest.class);
+ final SlingHttpServletResponse response =
Mockito.mock(SlingHttpServletResponse.class);
+ Mockito.when(response.isCommitted()).thenReturn(true);
+
+ final ErrorFilterChain chain1 = new ErrorFilterChain(new
FilterHandle[0], handler, new Exception());
+ chain1.doFilter(request, response);
+
+ final ErrorFilterChain chain2 = new ErrorFilterChain(new
FilterHandle[0], handler, 500, "message");
+ chain2.doFilter(request, response);
+
+ Mockito.verify(errorHandler,
never()).handleError(any(Throwable.class), eq(null), eq(response));
+ Mockito.verify(errorHandler, never()).handleError(anyInt(),
anyString(), eq(null), eq(response));
+ }
+
+ @Test public void testResponseNotCommitted() throws IOException,
ServletException {
+ final DefaultErrorHandler handler = new DefaultErrorHandler();
+ final ErrorHandler errorHandler = Mockito.mock(ErrorHandler.class);
+ handler.setDelegate(errorHandler);
+
+ final SlingHttpServletRequest request =
Mockito.mock(SlingHttpServletRequest.class);
+ final SlingHttpServletResponse response =
Mockito.mock(SlingHttpServletResponse.class);
+ Mockito.when(response.isCommitted()).thenReturn(false);
+
+ final ErrorFilterChain chain1 = new ErrorFilterChain(new
FilterHandle[0], handler, new Exception());
+ chain1.doFilter(request, response);
+ Mockito.verify(errorHandler,
times(1)).handleError(any(Throwable.class), eq(request), eq(response));
+
+ final ErrorFilterChain chain2 = new ErrorFilterChain(new
FilterHandle[0], handler, 500, "message");
+ chain2.doFilter(request, response);
+ Mockito.verify(errorHandler, times(1)).handleError(anyInt(),
anyString(), eq(request), eq(response));
+ }
+}