Skip to content

Commit 6ebc49f

Browse files
refactor(core): move StringUtil to text package, extend XSLT tran… (#2636)
* refactor(core): move `StringUtil` to `text` package, extend XSLT transformation support, and add tutorial examples * refactor(tutorials): improve XML to JSON XSLT transformation readability and output consistency * refactor(xslt): rename test class and improve error handling in XSLT transformations * refactor(xslt): simplify `transformMsg` method and clean up test code * refactor(xslt): fix case sensitivity in YAML file reference and remove unused test code * refactor(xslt): update YAML file references, fix typo in test method, and clarify beautifier comment * refactor(tutorials): change year type in XML to JSON transformation test to string for consistency --------- Co-authored-by: Christian Gördes <118011644+christiangoerdes@users.noreply.github.com>
1 parent 72b4f0c commit 6ebc49f

16 files changed

Lines changed: 275 additions & 164 deletions

File tree

core/src/main/java/com/predic8/membrane/core/interceptor/templating/AbstractTemplateInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import static com.predic8.membrane.core.interceptor.Outcome.ABORT;
3232
import static com.predic8.membrane.core.interceptor.Outcome.*;
3333
import static com.predic8.membrane.core.resolver.ResolverMap.*;
34-
import static com.predic8.membrane.core.util.StringUtil.*;
34+
import static com.predic8.membrane.core.util.text.StringUtil.*;
3535
import static java.nio.charset.StandardCharsets.*;
3636
import static org.apache.commons.text.StringEscapeUtils.*;
3737

core/src/main/java/com/predic8/membrane/core/interceptor/templating/TemplateInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import static com.predic8.membrane.core.interceptor.Outcome.*;
3232
import static com.predic8.membrane.core.lang.ScriptingUtils.*;
3333
import static com.predic8.membrane.core.util.FileUtil.*;
34-
import static com.predic8.membrane.core.util.StringUtil.addLineNumbers;
34+
import static com.predic8.membrane.core.util.text.StringUtil.addLineNumbers;
3535
import static java.nio.charset.StandardCharsets.*;
3636

3737
/**

core/src/main/java/com/predic8/membrane/core/interceptor/xml/Json2XmlInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import static com.predic8.membrane.core.http.MimeType.*;
2525
import static com.predic8.membrane.core.interceptor.Interceptor.Flow.*;
2626
import static com.predic8.membrane.core.interceptor.Outcome.*;
27-
import static com.predic8.membrane.core.util.StringUtil.*;
27+
import static com.predic8.membrane.core.util.text.StringUtil.*;
2828
import static java.nio.charset.StandardCharsets.*;
2929

3030
/**

core/src/main/java/com/predic8/membrane/core/interceptor/xslt/XSLTInterceptor.java

Lines changed: 93 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -19,111 +19,127 @@
1919
import com.predic8.membrane.core.interceptor.*;
2020
import com.predic8.membrane.core.multipart.*;
2121
import com.predic8.membrane.core.util.*;
22-
import com.predic8.membrane.core.util.text.*;
22+
import org.jetbrains.annotations.*;
2323
import org.slf4j.*;
2424

25+
import javax.xml.transform.*;
2526
import javax.xml.transform.stream.*;
2627
import java.util.*;
2728

2829
import static com.predic8.membrane.core.exceptions.ProblemDetails.*;
30+
import static com.predic8.membrane.core.interceptor.Interceptor.Flow.*;
2931
import static com.predic8.membrane.core.interceptor.Outcome.*;
32+
import static com.predic8.membrane.core.interceptor.Outcome.ABORT;
33+
import static com.predic8.membrane.core.util.text.StringUtil.*;
34+
import static com.predic8.membrane.core.util.text.TextUtil.*;
3035

3136
/**
3237
* @description <p>
33-
* The transform feature applies an XSLT transformation to the content in the body of a message. After the
34-
* transformation the body content is replaced with the result of the transformation.
35-
* </p>
38+
* The transform feature applies an XSLT transformation to the content in the body of a message. After the
39+
* transformation the body content is replaced with the result of the transformation.
40+
* </p>
3641
* @topic 2. Enterprise Integration Patterns
3742
*/
38-
@MCElement(name="transform")
43+
@MCElement(name = "transform")
3944
public class XSLTInterceptor extends AbstractInterceptor {
4045

41-
private static final Logger log = LoggerFactory.getLogger(XSLTInterceptor.class.getName());
46+
private static final Logger log = LoggerFactory.getLogger(XSLTInterceptor.class.getName());
4247

43-
private String xslt;
44-
private volatile XSLTTransformer xsltTransformer;
45-
private final XOPReconstitutor xopr = new XOPReconstitutor();
48+
private String xslt;
49+
private volatile XSLTTransformer xsltTransformer;
50+
private final XOPReconstitutor xopr = new XOPReconstitutor();
4651

47-
public XSLTInterceptor() {
48-
name = "xslt transformer";
49-
}
52+
public XSLTInterceptor() {
53+
name = "xslt transformer";
54+
}
5055

51-
@Override
52-
public Outcome handleRequest(Exchange exc) {
53-
try {
54-
transformMsg(exc.getRequest(), xslt, exc.getStringProperties());
55-
} catch (Exception e) {
56-
user(router.getConfiguration().isProduction(),getDisplayName())
57-
.detail("Error transforming request!")
58-
.exception(e)
59-
.buildAndSetResponse(exc);
60-
return ABORT;
61-
}
62-
return CONTINUE;
63-
}
56+
@Override
57+
public Outcome handleRequest(Exchange exc) {
58+
return handleInternal(exc, REQUEST);
59+
}
60+
61+
@Override
62+
public Outcome handleResponse(Exchange exc) {
63+
return handleInternal(exc, RESPONSE);
64+
}
65+
66+
private Outcome handleInternal(Exchange exc, Flow flow) {
67+
var msg = exc.getMessage(flow);
6468

65-
@Override
66-
public Outcome handleResponse(Exchange exc) {
6769
try {
68-
transformMsg(exc.getResponse(), xslt, exc.getStringProperties());
70+
transformMsg(msg, exc.getStringProperties());
71+
} catch (TransformerException e) {
72+
log.debug("", e);
73+
if (e.getMessage() != null && e.getMessage().contains("not allowed in prolog")) {
74+
user(router.getConfiguration().isProduction(), getDisplayName())
75+
.title("Content not allowed in prolog of XML input.")
76+
.detail("Check for extra characters before the XML declaration <?xml ... ?>")
77+
.internal("offendingInput", truncateAfter(msg.getBodyAsStringDecoded() + "...", 50))
78+
.buildAndSetResponse(exc);
79+
return ABORT;
80+
}
81+
return createErrorResponse(exc,e,flow);
6982
} catch (Exception e) {
70-
log.error("Error transforming response!", e);
71-
user(router.getConfiguration().isProduction(),getDisplayName())
72-
.detail("Error transforming response!")
73-
.exception(e)
74-
.buildAndSetResponse(exc);
75-
return ABORT;
83+
log.info("", e);
84+
return createErrorResponse(exc,e,flow);
7685
}
7786
return CONTINUE;
78-
}
79-
80-
private void transformMsg(Message msg, String ss, Map<String, String> parameter) throws Exception {
81-
if (msg.isBodyEmpty())
82-
return;
83-
msg.setBodyContent(xsltTransformer.transform(
84-
new StreamSource(xopr.reconstituteIfNecessary(msg)), parameter));
85-
}
86-
87-
@Override
88-
public void init() {
89-
super.init();
87+
}
88+
89+
private @NotNull Outcome createErrorResponse(Exchange exc, Exception e, Flow flow) {
90+
user(router.getConfiguration().isProduction(), getDisplayName())
91+
.detail("Error transforming message!")
92+
.exception(e)
93+
.internal("flow", flow.toString())
94+
.buildAndSetResponse(exc);
95+
return ABORT;
96+
}
97+
98+
private void transformMsg(Message msg, Map<String, String> parameter) throws Exception {
99+
if (msg.isBodyEmpty())
100+
return;
101+
msg.setBodyContent(xsltTransformer.transform(
102+
new StreamSource(xopr.reconstituteIfNecessary(msg)), parameter));
103+
}
104+
105+
@Override
106+
public void init() {
107+
super.init();
90108
try {
91109
xsltTransformer = new XSLTTransformer(xslt, router, getConcurrency());
92110
} catch (Exception e) {
93-
log.debug("",e);
111+
log.debug("",e);
94112
throw new ConfigurationException("Could not create XSLT transformer",e);
113+
95114
}
96115
}
97116

98-
private static int getConcurrency() {
99-
return Runtime.getRuntime().availableProcessors() * 2;
100-
}
101-
102-
public String getXslt() {
103-
return xslt;
104-
}
105-
106-
/**
107-
* @description Location of the XSLT stylesheet that will be applied to request and response.
108-
* @example strip.xslt
109-
*/
110-
@MCAttribute
111-
public void setXslt(String xslt) {
112-
this.xslt = xslt;
113-
this.xsltTransformer = null;
114-
}
115-
116-
@Override
117-
public String getShortDescription() {
118-
return "Applies an XSLT transformation.";
119-
}
120-
121-
@Override
122-
public String getLongDescription() {
123-
return TextUtil.removeFinalChar(getShortDescription()) +
124-
" using the stylesheet at " +
125-
TextUtil.linkURL(xslt) +
126-
" .";
127-
}
117+
private static int getConcurrency() {
118+
return Runtime.getRuntime().availableProcessors() * 2;
119+
}
120+
121+
public String getXslt() {
122+
return xslt;
123+
}
124+
125+
/**
126+
* @description Location of the XSLT stylesheet that will be applied to request and response.
127+
* @example strip.xslt
128+
*/
129+
@MCAttribute
130+
public void setXslt(String xslt) {
131+
this.xslt = xslt;
132+
this.xsltTransformer = null;
133+
}
134+
135+
@Override
136+
public String getShortDescription() {
137+
return "Applies an XSLT transformation.";
138+
}
139+
140+
@Override
141+
public String getLongDescription() {
142+
return "%s using the stylesheet at %s .".formatted(removeFinalChar(getShortDescription()), linkURL(xslt));
143+
}
128144

129145
}

core/src/main/java/com/predic8/membrane/core/lang/jsonpath/JsonpathExchangeExpression.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import java.io.*;
2929
import java.util.*;
3030

31-
import static com.predic8.membrane.core.util.StringUtil.*;
31+
import static com.predic8.membrane.core.util.text.StringUtil.*;
3232
import static java.lang.Boolean.*;
3333
import static java.nio.charset.StandardCharsets.*;
3434

core/src/main/java/com/predic8/membrane/core/openapi/serviceproxy/APIProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
import static com.predic8.membrane.core.lang.ExchangeExpression.Language.SPEL;
4040
import static com.predic8.membrane.core.lang.ExchangeExpression.expression;
41-
import static com.predic8.membrane.core.util.StringUtil.maskNonPrintableCharacters;
41+
import static com.predic8.membrane.core.util.text.StringUtil.maskNonPrintableCharacters;
4242

4343
/**
4444
* @description The api proxy extends the serviceProxy with API related functions like OpenAPI support and path parameters.

core/src/main/java/com/predic8/membrane/core/transport/http/HttpServerHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
import static com.predic8.membrane.core.transport.http.ByteStreamLogging.wrapConnectionOutputStream;
3636
import static com.predic8.membrane.core.transport.http.HttpServerHandler.RequestProcessingResult.*;
3737
import static com.predic8.membrane.core.transport.http.HttpServerThreadFactory.DEFAULT_THREAD_NAME;
38-
import static com.predic8.membrane.core.util.StringUtil.maskNonPrintableCharacters;
39-
import static com.predic8.membrane.core.util.StringUtil.truncateAfter;
38+
import static com.predic8.membrane.core.util.text.StringUtil.maskNonPrintableCharacters;
39+
import static com.predic8.membrane.core.util.text.StringUtil.truncateAfter;
4040
import static java.lang.Thread.currentThread;
4141

4242
public class HttpServerHandler extends AbstractHttpHandler implements Runnable, TwoWayStreaming {

core/src/main/java/com/predic8/membrane/core/util/text/StringUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
See the License for the specific language governing permissions and
1313
limitations under the License. */
1414

15-
package com.predic8.membrane.core.util;
15+
package com.predic8.membrane.core.util.text;
1616

1717
import java.util.*;
1818

0 commit comments

Comments
 (0)