Skip to content

Commit e94b700

Browse files
Release/0.5.0 alpha.2 (#1)
* Update README.md to confirm other supported tags. * Fix a typo where EL inequality was checked with neq instead of ne. * Build out support for rudimentary preprocessing of inline scriptlets and JSP tags. * Handle edge case where logic:notEqual used as not-empty test.
1 parent 2bedecf commit e94b700

File tree

12 files changed

+323
-32
lines changed

12 files changed

+323
-32
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ A command-line tool which converts a variety of Struts 1.x tags to their JSTL or
2020
* html:text
2121
* html:textarea
2222
* logic:empty
23+
* logic:equal
2324
* logic:iterate
2425
* logic:notEmpty
26+
* logic:notEqual
2527
* logic:present
2628

2729
...and plenty more to come.

buildSrc/src/main/groovy/com.rombalabs.strutstospringtoolkit.java-common-conventions.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ plugins {
77
id 'java'
88
}
99

10-
version = '0.5'
10+
version = '0.5.0-alpha.2'
1111

1212
repositories {
1313
// Use Maven Central for resolving dependencies.

jspConverter/src/main/java/com/rombalabs/strutstospringtoolkit/jspconverter/App.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.rombalabs.strutstospringtoolkit.jspconverter;
22

3+
import com.rombalabs.strutstospringtoolkit.jspservices.PreProcessor;
34
import com.rombalabs.strutstospringtoolkit.jspservices.StrutsProcessor;
45
import org.apache.logging.log4j.LogManager;
56
import org.apache.logging.log4j.Logger;
@@ -31,7 +32,10 @@ public static void main(String[] args) {
3132
}
3233
}
3334

35+
var preProcessor = new PreProcessor();
3436
var strutsProcessor = new StrutsProcessor();
35-
strutsProcessor.processFile(args[0], rewriteInPlace);
37+
38+
var outputFile = preProcessor.processFile(args[0], rewriteInPlace);
39+
strutsProcessor.processFile(outputFile, true);
3640
}
3741
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.rombalabs.strutstospringtoolkit.jspservices;
2+
3+
public interface FileProcessor {
4+
String processFile(String filename, boolean rewrite);
5+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.rombalabs.strutstospringtoolkit.jspservices;
2+
3+
import com.rombalabs.strutstospringtoolkit.jspservices.transformers.PreprocessTransformer;
4+
import com.rombalabs.strutstospringtoolkit.jspservices.transformers.preprocessing.AttributeInlineLogicTagTransformer;
5+
import com.rombalabs.strutstospringtoolkit.jspservices.transformers.preprocessing.InlineBeanWriteTagTransformer;
6+
import com.rombalabs.strutstospringtoolkit.jspservices.transformers.preprocessing.InlineScriptletTransformer;
7+
import org.apache.commons.io.FileUtils;
8+
import org.apache.logging.log4j.LogManager;
9+
import org.apache.logging.log4j.Logger;
10+
11+
import java.io.*;
12+
import java.nio.file.CopyOption;
13+
import java.nio.file.StandardCopyOption;
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
17+
public class PreProcessor implements FileProcessor {
18+
19+
protected static final Logger logger = LogManager.getLogger();
20+
21+
private final List<PreprocessTransformer> transformers;
22+
23+
public PreProcessor() {
24+
transformers = new ArrayList<>();
25+
26+
// struts:bean transformers
27+
transformers.add(new InlineScriptletTransformer());
28+
transformers.add(new AttributeInlineLogicTagTransformer());
29+
transformers.add(new InlineBeanWriteTagTransformer());
30+
}
31+
32+
@Override
33+
public String processFile(String filename, boolean rewrite) {
34+
var outputPath = filename.replace(".jsp", "_converted.jsp");
35+
logger.info("Loading file " + filename);
36+
logger.info("Storing output in " + (rewrite ? "temporary " : "") + "location: " + outputPath);
37+
38+
try (var reader = new BufferedReader(new FileReader(filename))) {
39+
try (var writer = new BufferedWriter(new FileWriter(outputPath))) {
40+
String line;
41+
while ((line = reader.readLine()) != null) {
42+
var processedLine = processContent(line);
43+
writer.write(processedLine);
44+
writer.newLine();
45+
}
46+
}
47+
48+
if (rewrite) {
49+
File outputFile = new File(outputPath);
50+
FileUtils.copyFile(outputFile, new File(filename));
51+
FileUtils.delete(outputFile);
52+
outputPath = filename;
53+
}
54+
55+
} catch (IOException e) {
56+
logger.error("Failed to load file.", e);
57+
throw new RuntimeException(e);
58+
}
59+
60+
return outputPath;
61+
}
62+
63+
public String processContent(String content) {
64+
String result = content;
65+
for (PreprocessTransformer transformer : transformers) {
66+
result = transformer.processText(content);
67+
if (!result.contentEquals(content)) break;
68+
}
69+
70+
return result;
71+
}
72+
}

jspServices/src/main/java/com/rombalabs/strutstospringtoolkit/jspservices/StrutsProcessor.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
import java.util.ArrayList;
2727
import java.util.List;
2828

29-
public class StrutsProcessor {
29+
public class StrutsProcessor implements FileProcessor {
3030

31-
public static final Logger logger = LogManager.getLogger();
31+
protected static final Logger logger = LogManager.getLogger();
3232

3333
private final List<TagTransformer> transformers;
3434

@@ -51,7 +51,8 @@ public StrutsProcessor() {
5151
transformers.add(new IterateTagTransformer());
5252
}
5353

54-
public Document processFile(String filename, boolean rewrite) {
54+
@Override
55+
public String processFile(String filename, boolean rewrite) {
5556
String content;
5657
try {
5758
logger.info("Loading file " + filename);
@@ -63,9 +64,7 @@ public Document processFile(String filename, boolean rewrite) {
6364

6465
var result = processContent(content);
6566

66-
save(result, filename, rewrite);
67-
68-
return result;
67+
return save(result, filename, rewrite);
6968
}
7069

7170
public Document processContent(String content) {
@@ -103,7 +102,7 @@ private Element processElement(Element targetElement) {
103102
return targetElement;
104103
}
105104

106-
private void save(Document doc, String originalFileName, boolean rewrite)
105+
private String save(Document doc, String originalFileName, boolean rewrite)
107106
{
108107
try {
109108
if (!rewrite)
@@ -116,5 +115,7 @@ private void save(Document doc, String originalFileName, boolean rewrite)
116115
} catch (IOException e) {
117116
logger.fatal("Failed to save converted file...", e);
118117
}
118+
119+
return originalFileName;
119120
}
120121
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.rombalabs.strutstospringtoolkit.jspservices.transformers;
2+
3+
import org.jsoup.nodes.Element;
4+
5+
public interface PreprocessTransformer {
6+
String processText(String inputText);
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.rombalabs.strutstospringtoolkit.jspservices.transformers.preprocessing;
2+
3+
import com.rombalabs.strutstospringtoolkit.jspservices.transformers.PreprocessTransformer;
4+
import org.jsoup.Jsoup;
5+
import org.jsoup.nodes.Document;
6+
import org.jsoup.nodes.Element;
7+
import org.jsoup.parser.ParseSettings;
8+
import org.jsoup.parser.Parser;
9+
10+
import java.util.regex.Matcher;
11+
import java.util.regex.Pattern;
12+
13+
public class AttributeInlineLogicTagTransformer implements PreprocessTransformer {
14+
15+
Pattern attributeLogicTagPattern;
16+
17+
public AttributeInlineLogicTagTransformer() {
18+
// <logic:equal (\S+=["|']\S+['|"] ?)+>.*</logic:equal>
19+
attributeLogicTagPattern = Pattern.compile("<logic:equal (\\S+=[\"|']\\S+[\"|'](\\s+)?)+>.*</logic:equal>");
20+
}
21+
22+
@Override
23+
public String processText(String inputText) {
24+
String result = inputText;
25+
Matcher m = attributeLogicTagPattern.matcher(inputText);
26+
if (m.find()) {
27+
Parser parser = Parser.xmlParser();
28+
parser.settings(new ParseSettings(true, true)); // tag, attribute preserve case
29+
Document doc = Jsoup.parse(m.toMatchResult().group(),"", parser);
30+
31+
var elString = convertElement(doc.root().child(0), "");
32+
33+
result = m.replaceAll(elString);
34+
}
35+
36+
return result;
37+
}
38+
39+
protected String convertElement(Element element, String newTagName) {
40+
var name = element.attr("name");
41+
var property = element.attr("property");
42+
var value = element.attr("value");
43+
var content = element.text();
44+
45+
return createExpressionLanguageString(name, property, value, content);
46+
}
47+
48+
private static String createExpressionLanguageString(String name, String property, String value, String content) {
49+
var elString = name +
50+
(!name.isEmpty() && !property.isEmpty() ? "." : "") +
51+
property;
52+
53+
if (!value.contentEquals("true")) {
54+
elString = elString + " eq " + value;
55+
}
56+
57+
return " \\${" + elString + " ? '" + content + "' : ''}";
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.rombalabs.strutstospringtoolkit.jspservices.transformers.preprocessing;
2+
3+
import com.rombalabs.strutstospringtoolkit.jspservices.transformers.PreprocessTransformer;
4+
import org.jsoup.Jsoup;
5+
import org.jsoup.nodes.Document;
6+
import org.jsoup.nodes.Element;
7+
import org.jsoup.parser.ParseSettings;
8+
import org.jsoup.parser.Parser;
9+
10+
import java.util.regex.Matcher;
11+
import java.util.regex.Pattern;
12+
13+
public class InlineBeanWriteTagTransformer implements PreprocessTransformer {
14+
15+
Pattern beanWritePattern;
16+
17+
public InlineBeanWriteTagTransformer() {
18+
beanWritePattern = Pattern.compile("<bean:write\\s+(\\S+=['|\"]\\S+['|\"]' ?)+\\s+/>");
19+
}
20+
21+
@Override
22+
public String processText(String inputText) {
23+
String result = inputText;
24+
Matcher m = beanWritePattern.matcher(inputText);
25+
if (m.matches()) {
26+
Parser parser = Parser.xmlParser();
27+
parser.settings(new ParseSettings(true, true)); // tag, attribute preserve case
28+
Document doc = Jsoup.parse(m.toMatchResult().group(),"", parser);
29+
30+
result = convertElement(doc.root().child(0));
31+
}
32+
33+
return result;
34+
}
35+
36+
protected String convertElement(Element element) {
37+
var name = element.attr("name");
38+
var property = element.attr("property");
39+
var filter = ("true".equals(element.attr("filter")));
40+
41+
return createExpressionLanguageString(name, property, filter);
42+
}
43+
44+
private static String createExpressionLanguageString(String name, String property, boolean filter) {
45+
var elString = name +
46+
(!name.isEmpty() && !property.isEmpty() ? "." : "") +
47+
property;
48+
49+
if (filter) {
50+
elString = "fn:escapeXml(" + elString + ")";
51+
}
52+
53+
return "${" + elString + "}";
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.rombalabs.strutstospringtoolkit.jspservices.transformers.preprocessing;
2+
3+
import com.rombalabs.strutstospringtoolkit.jspservices.transformers.PreprocessTransformer;
4+
import org.apache.logging.log4j.LogManager;
5+
import org.apache.logging.log4j.Logger;
6+
7+
import java.util.regex.Matcher;
8+
import java.util.regex.Pattern;
9+
10+
public class InlineScriptletTransformer implements PreprocessTransformer {
11+
12+
protected static final Logger logger = LogManager.getLogger();
13+
14+
Pattern initialRequestPattern;
15+
Pattern requestAttributePattern;
16+
Pattern requestParameterPattern;
17+
Pattern requestParameterValuesPattern;
18+
Pattern requestHeaderPattern;
19+
Pattern requestHeaderValuesPattern;
20+
Pattern requestContextPathPattern;
21+
Pattern sessionAttributePattern;
22+
23+
public InlineScriptletTransformer() {
24+
initialRequestPattern = Pattern.compile("<%=(\\s+)?request\\.get\\S+\\((\\S+)?\\)(\\s+)?%>");
25+
requestAttributePattern = Pattern.compile("<%=(\\s+)?request\\.getAttribute\\(\"(\\S+)\"\\)(\\s+)?%>");
26+
requestParameterPattern = Pattern.compile("<%=(\\s+)?request\\.getParameter\\(\"(\\S+)\"\\)(\\s+)?%>");
27+
requestParameterValuesPattern = Pattern.compile("<%=(\\s+)?request\\.getParameterValues\\(\"(\\S+)\"\\)(\\s+)?%>");
28+
requestHeaderPattern = Pattern.compile("<%=(\\s+)?request\\.getHeader\\(\"(\\S+)\"\\)(\\s+)?%>");
29+
requestHeaderValuesPattern = Pattern.compile("<%=(\\s+)?request\\.getHeaderValues\\(\"(\\S+)\"\\)(\\s+)?%>");
30+
requestContextPathPattern = Pattern.compile("<%=(\\s+)?request\\.getContextPath\\(\\)(\\s+)?%>");
31+
32+
sessionAttributePattern = Pattern.compile("<%=(\\s+)?request\\.getSession\\(\\)\\.getAttribute\\(\"(\\S+)\"\\)(\\s+)?%>");
33+
}
34+
@Override
35+
public String processText(String inputText) {
36+
String result = inputText;
37+
Matcher m = initialRequestPattern.matcher(inputText);
38+
if (m.find()) {
39+
/*
40+
https://balusc.omnifaces.org/2011/09/communication-in-jsf-20.html#ImplicitELObjects
41+
#{requestScope}: the current request attribute map
42+
#{viewScope}: the current view attribute map
43+
#{sessionScope}: the current session attribute map
44+
#{param}: the current request parameter map
45+
#{paramValues}: the current request parameter values map
46+
#{header}: the current request header map
47+
#{headerValues}: the current request header values map
48+
#{cookie}: the current request cookie map
49+
*/
50+
51+
m = requestAttributePattern.matcher(inputText);
52+
result = m.replaceAll("\\${requestScope.$1}");
53+
54+
m = requestParameterPattern.matcher(result);
55+
result = m.replaceAll("\\${param.$1}");
56+
57+
m = requestParameterValuesPattern.matcher(result);
58+
result = m.replaceAll("\\${paramValues.$1}");
59+
60+
m = requestHeaderPattern.matcher(result);
61+
result = m.replaceAll("\\${header[$1]}");
62+
63+
m = requestHeaderValuesPattern.matcher(result);
64+
result = m.replaceAll("\\${headerValues[$1]}");
65+
66+
m = requestContextPathPattern.matcher(result);
67+
result = m.replaceAll("\\${pageContext.request.contextPath}");
68+
69+
m = sessionAttributePattern.matcher(result);
70+
result = m.replaceAll("\\${sessionScope[\1]}");
71+
}
72+
73+
return result;
74+
}
75+
}

0 commit comments

Comments
 (0)