This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/master by this push:
new 9484496 Add extended option to trimSpaces
9484496 is described below
commit 94844961e76ccee6fcfb829dfeb842beaa5ea8ab
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Mar 16 17:47:23 2021 +0000
Add extended option to trimSpaces
---
java/org/apache/jasper/Options.java | 7 ++-
java/org/apache/jasper/TrimSpacesOption.java | 3 +-
java/org/apache/jasper/compiler/Compiler.java | 8 +++-
java/org/apache/jasper/compiler/Generator.java | 22 +++++++++
.../compiler/NewlineReductionServletWriter.java | 54 ++++++++++++++++++++++
test/org/apache/jasper/compiler/TestGenerator.java | 52 ++++++++++++++++++++-
test/webapp/jsp/trim-spaces-extended.jsp | 49 ++++++++++++++++++++
webapps/docs/changelog.xml | 7 +++
webapps/docs/jasper-howto.xml | 11 +++--
9 files changed, 204 insertions(+), 9 deletions(-)
diff --git a/java/org/apache/jasper/Options.java
b/java/org/apache/jasper/Options.java
index 19f3947..5f8d6da 100644
--- a/java/org/apache/jasper/Options.java
+++ b/java/org/apache/jasper/Options.java
@@ -101,8 +101,11 @@ public interface Options {
* @return {@link TrimSpacesOption#TRUE} to remove template text that
* consists only of whitespace from the output completely,
* {@link TrimSpacesOption#SINGLE} to replace such template text
- * with a single space or {@link TrimSpacesOption#FALSE} to leave
- * such template text unchanged
+ * with a single space, {@link TrimSpacesOption#FALSE} to leave
+ * such template text unchanged or {@link
TrimSpacesOption#EXTENDED}
+ * to remove template text that consists only of whitespace and to
+ * replace any sequence of whitespace and new lines within template
+ * text with a single new line.
*/
public TrimSpacesOption getTrimSpaces();
diff --git a/java/org/apache/jasper/TrimSpacesOption.java
b/java/org/apache/jasper/TrimSpacesOption.java
index faf7476..2890aa3 100644
--- a/java/org/apache/jasper/TrimSpacesOption.java
+++ b/java/org/apache/jasper/TrimSpacesOption.java
@@ -19,5 +19,6 @@ package org.apache.jasper;
public enum TrimSpacesOption {
FALSE,
TRUE,
- SINGLE
+ SINGLE,
+ EXTENDED
}
diff --git a/java/org/apache/jasper/compiler/Compiler.java
b/java/org/apache/jasper/compiler/Compiler.java
index 2d5cda8..e2a2fcd 100644
--- a/java/org/apache/jasper/compiler/Compiler.java
+++ b/java/org/apache/jasper/compiler/Compiler.java
@@ -32,6 +32,7 @@ import java.util.Map.Entry;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
import org.apache.jasper.Options;
+import org.apache.jasper.TrimSpacesOption;
import org.apache.jasper.servlet.JspServletWrapper;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
@@ -316,7 +317,12 @@ public abstract class Compiler {
javaEncoding);
}
- writer = new ServletWriter(new PrintWriter(osw));
+ if ((ctxt!=null) &&
ctxt.getOptions().getTrimSpaces().equals(TrimSpacesOption.EXTENDED)) {
+ writer = new NewlineReductionServletWriter(new PrintWriter(osw));
+ } else {
+ writer = new ServletWriter(new PrintWriter(osw));
+ }
+
ctxt.setWriter(writer);
return writer;
}
diff --git a/java/org/apache/jasper/compiler/Generator.java
b/java/org/apache/jasper/compiler/Generator.java
index efd5485..8d0af63 100644
--- a/java/org/apache/jasper/compiler/Generator.java
+++ b/java/org/apache/jasper/compiler/Generator.java
@@ -40,6 +40,8 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.TimeZone;
import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import jakarta.el.MethodExpression;
import jakarta.el.ValueExpression;
@@ -52,6 +54,7 @@ import org.apache.el.util.JreCompat;
import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
+import org.apache.jasper.TrimSpacesOption;
import org.apache.jasper.compiler.Node.NamedAttribute;
import org.apache.jasper.runtime.JspRuntimeLibrary;
import org.xml.sax.Attributes;
@@ -81,6 +84,10 @@ class Generator {
private static final Class<?>[] OBJECT_CLASS = { Object.class };
+ private static final Pattern PRE_TAG_PATTERN =
Pattern.compile("(?s).*(<pre>|</pre>).*");
+
+ private static final Pattern BLANK_LINE_PATTERN =
Pattern.compile("(\\s*(\\n|\\r)+\\s*)");
+
private final ServletWriter out;
private final ArrayList<GenBuffer> methodsBuffered;
@@ -2097,6 +2104,21 @@ class Generator {
public void visit(Node.TemplateText n) throws JasperException {
String text = n.getText();
+ // If the extended option is being used attempt to minimize the
+ // frequency of regex operations.
+ if ((ctxt != null) &&
ctxt.getOptions().getTrimSpaces().equals(TrimSpacesOption.EXTENDED) &&
+ text.contains("\n")) {
+ // Ensure there are no <pre> or </pre> tags embedded in this
+ // text - if there are, we want to NOT modify the whitespace.
+ Matcher preMatcher = PRE_TAG_PATTERN.matcher(text);
+ if (!preMatcher.matches()) {
+ Matcher matcher = BLANK_LINE_PATTERN.matcher(text);
+ String revisedText = matcher.replaceAll("\n");
+ // Leading and trailing whitespace can be trimmed so remove
+ // it here as the regex won't remove it.
+ text = revisedText.trim();
+ }
+ }
int textSize = text.length();
if (textSize == 0) {
diff --git a/java/org/apache/jasper/compiler/NewlineReductionServletWriter.java
b/java/org/apache/jasper/compiler/NewlineReductionServletWriter.java
new file mode 100644
index 0000000..ed6fbfe
--- /dev/null
+++ b/java/org/apache/jasper/compiler/NewlineReductionServletWriter.java
@@ -0,0 +1,54 @@
+/*
+ * 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.jasper.compiler;
+
+import java.io.PrintWriter;
+
+/**
+ * This class filters duplicate newlines instructions from the compiler output,
+ * and therefore from the runtime JSP. The duplicates typically happen because
+ * the compiler has multiple branches that write them, but they operate
+ * independently and don't realize that the previous output was identical.
+ *
+ * Removing these lines makes the JSP more efficient by executing fewer
+ * operations during runtime.
+ */
+public class NewlineReductionServletWriter extends ServletWriter {
+
+ private static final String NEWLINE_WRITE_TEXT = "out.write('\\n');";
+
+ private boolean lastWriteWasNewline;
+
+ public NewlineReductionServletWriter(PrintWriter writer) {
+ super(writer);
+ }
+
+ @Override
+ public void printil(String s) {
+ if (s.equals(NEWLINE_WRITE_TEXT)) {
+ if (lastWriteWasNewline) {
+ // do nothing
+ return;
+ } else {
+ lastWriteWasNewline = true;
+ }
+ } else {
+ lastWriteWasNewline = false;
+ }
+ super.printil(s);
+ }
+}
\ No newline at end of file
diff --git a/test/org/apache/jasper/compiler/TestGenerator.java
b/test/org/apache/jasper/compiler/TestGenerator.java
index e5cfc71..5bda4a3 100644
--- a/test/org/apache/jasper/compiler/TestGenerator.java
+++ b/test/org/apache/jasper/compiler/TestGenerator.java
@@ -17,8 +17,10 @@
package org.apache.jasper.compiler;
+import java.io.File;
import java.io.IOException;
import java.util.Date;
+import java.util.Scanner;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.jsp.JspException;
@@ -30,8 +32,12 @@ import jakarta.servlet.jsp.tagext.VariableInfo;
import org.junit.Assert;
import org.junit.Test;
+import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.jasper.servlet.JasperInitializer;
import org.apache.tomcat.util.buf.ByteChunk;
public class TestGenerator extends TomcatBaseTest {
@@ -212,7 +218,7 @@ public class TestGenerator extends TomcatBaseTest {
response.contains("[1:attribute1: '', attribute2: '']"));
Assert.assertTrue(response,
response.contains("[2:attribute1: '', attribute2: '']"));
- }
+ }
public static class Bug56529 extends TagSupport {
@@ -285,4 +291,48 @@ public class TestGenerator extends TomcatBaseTest {
System.out.println(result);
assertEcho(result, "ASYNC");
}
+
+ @Test
+ public void testTrimSpacesExtended01() throws Exception {
+ doTestTrimSpacesExtended(false);
+ }
+
+ @Test
+ public void testTrimSpacesExtended02() throws Exception {
+ doTestTrimSpacesExtended(true);
+ }
+
+ private void doTestTrimSpacesExtended(boolean removeBlankLines) throws
Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ File appDir = new File("test/webapp");
+ Context ctxt = tomcat.addContext("", appDir.getAbsolutePath());
+ ctxt.addServletContainerInitializer(new JasperInitializer(), null);
+
+ Tomcat.initWebappDefaults(ctxt);
+ Wrapper w = (Wrapper) ctxt.findChild("jsp");
+ if (removeBlankLines) {
+ w.addInitParameter("trimSpaces", "extended");
+ }
+
+ tomcat.start();
+
+ ByteChunk res = getUrl("http://localhost:" + getPort() +
"/jsp/trim-spaces-extended.jsp");
+
+ String result = res.toString();
+ Scanner scanner = new Scanner(result);
+ int blankLineCount = 0;
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ if (line.length() == 0) {
+ blankLineCount++;
+ }
+ }
+ if (!removeBlankLines && blankLineCount == 0) {
+ Assert.fail("TrimSpaceOptions.EXTENDED not configured but balnk
lines have been removed");
+ } else if (removeBlankLines && blankLineCount > 0) {
+ Assert.fail("TrimSpaceOptions.EXTENDED does not allow the line to
be just a new line character");
+ }
+ scanner.close();
+ }
}
diff --git a/test/webapp/jsp/trim-spaces-extended.jsp
b/test/webapp/jsp/trim-spaces-extended.jsp
new file mode 100644
index 0000000..817f44f
--- /dev/null
+++ b/test/webapp/jsp/trim-spaces-extended.jsp
@@ -0,0 +1,49 @@
+<%--
+ 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.
+--%>
+<!doctype html>
+<html>
+<head>
+ <title>Apache Tomcat JSP White Space Trim Optimisation
Configuration</title>
+</head>
+<body>
+
+
+
+<h4>Apache Tomcat JSP white space trim test page</h4>
+<p>If the value of init param jspWhiteSpaceTrimming is set to true, the
compiler
+trims all the excess white spaces and empty line characters from the JSP files
+and thus reduces build size.</p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 1e15ba2..b857721 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -142,6 +142,13 @@
the list of OSGi exported packages for the Jasper embedded JAR. Patch
provided by Sokratis Zappis. (markt)
</fix>
+ <add>
+ Add a new option for the <code>trimSpaces</code> configuration.
+ <code>extended</code> will attempt to remove leading and trailing
+ whitespace from template text and collapse sequences of whitespace and
+ newlines within template text into a single new line. Based on a pull
+ request by kamnani. (markt)
+ </add>
</changelog>
</subsection>
</section>
diff --git a/webapps/docs/jasper-howto.xml b/webapps/docs/jasper-howto.xml
index 9ad677b..0806be8 100644
--- a/webapps/docs/jasper-howto.xml
+++ b/webapps/docs/jasper-howto.xml
@@ -193,10 +193,13 @@ debugging be suppressed? <code>true</code> or
<code>false</code>, default
<li><strong>trimSpaces</strong> - Should template text that consists entirely
of
whitespace be removed from the output (<code>true</code>), replaced with a
-single space (<code>single</code>) or left unchanged (<code>false</code>)? Note
-that if a JSP page or tag file specifies a
<code>trimDirectiveWhitespaces</code>
-value of <code>true</code>, that will take precedence over this configuration
-setting for that page/tag. Default <code>false</code>.</li>
+single space (<code>single</code>) or left unchanged (<code>false</code>)?
+Alternatively, the <code>extended</code> option will remove leading and
trailing
+whitespace from template text and collapse sequences of whitespace and newlines
+within the template text to a single new line. Note that if a JSP page or tag
+file specifies a <code>trimDirectiveWhitespaces</code> value of
+<code>true</code>, that will take precedence over this configuration setting
for
+that page/tag. Default <code>false</code>.</li>
<li><strong>xpoweredBy</strong> - Determines whether X-Powered-By response
header is added by generated servlet. <code>true</code> or <code>false</code>,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]