|
23 | 23 | import java.io.File; |
24 | 24 | import java.io.IOException; |
25 | 25 | import java.lang.reflect.Field; |
| 26 | +import java.nio.channels.IllegalSelectorException; |
26 | 27 | import java.nio.charset.CodingErrorAction; |
27 | 28 | import java.util.ArrayList; |
28 | 29 | import java.util.Date; |
| 30 | +import java.util.HashSet; |
29 | 31 | import java.util.List; |
30 | 32 | import java.util.Map; |
31 | 33 | import java.util.Scanner; |
| 34 | +import java.util.Set; |
| 35 | +import java.util.concurrent.atomic.AtomicInteger; |
32 | 36 |
|
| 37 | +import jakarta.servlet.ServletRequest; |
33 | 38 | import jakarta.servlet.http.HttpServletResponse; |
34 | 39 | import jakarta.servlet.jsp.JspException; |
35 | 40 | import jakarta.servlet.jsp.PageContext; |
@@ -738,6 +743,81 @@ public void setAttribute06(Object attribute06) { |
738 | 743 | } |
739 | 744 | } |
740 | 745 |
|
| 746 | + public static class TesterExceptionTag extends TagSupport { |
| 747 | + |
| 748 | + private static final long serialVersionUID = 1L; |
| 749 | + |
| 750 | + private static AtomicInteger counter = new AtomicInteger(0); |
| 751 | + |
| 752 | + private static Set<Integer> released = new HashSet<>(); |
| 753 | + |
| 754 | + private final int index; |
| 755 | + |
| 756 | + private String state = ""; |
| 757 | + |
| 758 | + public static void resetForNewTest() { |
| 759 | + counter.set(0); |
| 760 | + released.clear(); |
| 761 | + } |
| 762 | + |
| 763 | + public static boolean isReleased(int index) { |
| 764 | + return released.contains(Integer.valueOf(index)); |
| 765 | + } |
| 766 | + |
| 767 | + public TesterExceptionTag() { |
| 768 | + index = counter.incrementAndGet(); |
| 769 | + } |
| 770 | + |
| 771 | + @Override |
| 772 | + public int doStartTag() throws JspException { |
| 773 | + ServletRequest request = pageContext.getRequest(); |
| 774 | + boolean throwOnStart = Boolean.parseBoolean(request.getParameter("throwOnStart")); |
| 775 | + if (throwOnStart) { |
| 776 | + state += "lastStartFailed"; |
| 777 | + throw new IllegalSelectorException(); |
| 778 | + } else { |
| 779 | + try { |
| 780 | + if (!state.isBlank()) { |
| 781 | + pageContext.getOut().print(state); |
| 782 | + pageContext.getOut().print("-"); |
| 783 | + } |
| 784 | + pageContext.getOut().println("start-" + index); |
| 785 | + } catch (IOException ioe) { |
| 786 | + throw new JspException(ioe); |
| 787 | + } |
| 788 | + } |
| 789 | + return super.doStartTag(); |
| 790 | + } |
| 791 | + |
| 792 | + @Override |
| 793 | + public int doEndTag() throws JspException { |
| 794 | + ServletRequest request = pageContext.getRequest(); |
| 795 | + boolean throwOnEnd = Boolean.parseBoolean(request.getParameter("throwOnEnd")); |
| 796 | + if (throwOnEnd) { |
| 797 | + state += "lastEndFailed"; |
| 798 | + throw new IllegalSelectorException(); |
| 799 | + } else { |
| 800 | + try { |
| 801 | + if (!state.isBlank()) { |
| 802 | + pageContext.getOut().print(state); |
| 803 | + pageContext.getOut().print("-"); |
| 804 | + } |
| 805 | + pageContext.getOut().println("end-" + index); |
| 806 | + } catch (IOException ioe) { |
| 807 | + throw new JspException(ioe); |
| 808 | + } |
| 809 | + } |
| 810 | + return super.doEndTag(); |
| 811 | + } |
| 812 | + |
| 813 | + @Override |
| 814 | + public void release() { |
| 815 | + released.add(Integer.valueOf(index)); |
| 816 | + super.release(); |
| 817 | + } |
| 818 | + } |
| 819 | + |
| 820 | + |
741 | 821 | @Test |
742 | 822 | public void testLambdaScriptlets() throws Exception { |
743 | 823 | doTestJsp("lambda.jsp"); |
@@ -1181,4 +1261,62 @@ public void testNonstandardRemoves() throws Exception { |
1181 | 1261 | + "application value=null", body.toString()); |
1182 | 1262 | body.recycle(); |
1183 | 1263 | } |
| 1264 | + |
| 1265 | + @Test |
| 1266 | + public void testTagReuseException01() throws Exception { |
| 1267 | + TesterExceptionTag.resetForNewTest(); |
| 1268 | + // No exceptions. Check re-use. |
| 1269 | + doTestTagReuseException(null, "start-1\nend-1\n", HttpServletResponse.SC_OK); |
| 1270 | + Assert.assertFalse(TesterExceptionTag.isReleased(1)); |
| 1271 | + doTestTagReuseException(null, "start-1\nend-1\n", HttpServletResponse.SC_OK); |
| 1272 | + Assert.assertFalse(TesterExceptionTag.isReleased(1)); |
| 1273 | + } |
| 1274 | + |
| 1275 | + @Test |
| 1276 | + public void testTagReuseException02() throws Exception { |
| 1277 | + TesterExceptionTag.resetForNewTest(); |
| 1278 | + // Exception on doStartTag |
| 1279 | + doTestTagReuseException(null, "start-1\nend-1\n", HttpServletResponse.SC_OK); |
| 1280 | + Assert.assertFalse(TesterExceptionTag.isReleased(1)); |
| 1281 | + doTestTagReuseException("throwOnStart=true", null, HttpServletResponse.SC_INTERNAL_SERVER_ERROR); |
| 1282 | + Assert.assertTrue(TesterExceptionTag.isReleased(1)); |
| 1283 | + // Should use new instance |
| 1284 | + doTestTagReuseException(null, "start-2\nend-2\n", HttpServletResponse.SC_OK); |
| 1285 | + Assert.assertFalse(TesterExceptionTag.isReleased(2)); |
| 1286 | + doTestTagReuseException(null, "start-2\nend-2\n", HttpServletResponse.SC_OK); |
| 1287 | + Assert.assertFalse(TesterExceptionTag.isReleased(2)); |
| 1288 | + } |
| 1289 | + |
| 1290 | + @Test |
| 1291 | + public void testTagReuseException03() throws Exception { |
| 1292 | + TesterExceptionTag.resetForNewTest(); |
| 1293 | + // Exception on doEndTag |
| 1294 | + doTestTagReuseException(null, "start-1\nend-1\n", HttpServletResponse.SC_OK); |
| 1295 | + Assert.assertFalse(TesterExceptionTag.isReleased(1)); |
| 1296 | + doTestTagReuseException("throwOnEnd=true", null, HttpServletResponse.SC_INTERNAL_SERVER_ERROR); |
| 1297 | + Assert.assertTrue(TesterExceptionTag.isReleased(1)); |
| 1298 | + // Should use new instance |
| 1299 | + doTestTagReuseException(null, "start-2\nend-2\n", HttpServletResponse.SC_OK); |
| 1300 | + Assert.assertFalse(TesterExceptionTag.isReleased(2)); |
| 1301 | + doTestTagReuseException(null, "start-2\nend-2\n", HttpServletResponse.SC_OK); |
| 1302 | + Assert.assertFalse(TesterExceptionTag.isReleased(2)); |
| 1303 | + } |
| 1304 | + |
| 1305 | + private void doTestTagReuseException(String queryString, String expectedBody, int expectedStatus) throws Exception { |
| 1306 | + if (!getTomcatInstance().getServer().getState().isAvailable()) { |
| 1307 | + getTomcatInstanceTestWebapp(false, true); |
| 1308 | + } |
| 1309 | + |
| 1310 | + ByteChunk body = new ByteChunk(); |
| 1311 | + String uri = "/test/jsp/generator/reuse-exception.jsp"; |
| 1312 | + if (queryString != null) { |
| 1313 | + uri += "?" + queryString; |
| 1314 | + } |
| 1315 | + int rc = getUrl("http://localhost:" + getPort() + uri, body, null); |
| 1316 | + |
| 1317 | + Assert.assertEquals(expectedStatus, rc); |
| 1318 | + if (expectedBody != null) { |
| 1319 | + Assert.assertEquals("Wrong body", expectedBody, body.toString()); |
| 1320 | + } |
| 1321 | + } |
1184 | 1322 | } |
0 commit comments