Skip to content

Commit

Permalink
jooby-apt: Java strings not escaped properly in mvc source code gener…
Browse files Browse the repository at this point in the history
…ation.

- fix #3455
- shade commons-text + use automatic-module-name
  • Loading branch information
jknack committed Jun 22, 2024
1 parent b015958 commit 8d57c4b
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 31 deletions.
54 changes: 37 additions & 17 deletions modules/jooby-apt/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.12.0</version>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>com.google.testing.compile</groupId>
Expand Down Expand Up @@ -110,33 +116,47 @@
</plugin>

<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<version>${moditec.version}</version>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>generate-module-info</id>
<id>fat-jar</id>
<phase>package</phase>
<goals>
<goal>add-module-info</goal>
<goal>shade</goal>
</goals>
<configuration>
<overwriteExistingFiles>true</overwriteExistingFiles>
<failOnWarning>false</failOnWarning>
<module>
<moduleInfo>
<name>io.jooby.apt</name>
<exports>
!io.jooby.internal.*;
*;
</exports>
</moduleInfo>
</module>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>org.apache.commons:commons-text</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>org.apache.commons:commons-text</artifact>
<includes>
<include>org/apache/commons/text/**</include>
</includes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>org.apache.commons.text</pattern>
<shadedPattern>${shaded.package}.commonstext</shadedPattern>
</relocation>
</relocations>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Automatic-Module-Name>io.jooby.apt</Automatic-Module-Name>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/
package io.jooby.internal.apt;

import static org.apache.commons.text.StringEscapeUtils.ESCAPE_JAVA;

import java.util.List;
import java.util.stream.Stream;

Expand All @@ -22,7 +24,7 @@ public static String of(CharSequence... sequence) {
}

public static CharSequence string(CharSequence value) {
return "\"" + value + "\"";
return "\"" + ESCAPE_JAVA.translate(value) + "\"";
}

public static CharSequence clazz(boolean kt) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public List<String> generateMapping(boolean kt) {
block.add(statement(indent(2), ".setExecutorKey(", string(dispatch), ")")));
/* attributes */
attributeGenerator
.toSourceCode(this, indent(2))
.toSourceCode(this, 2)
.ifPresent(
attributes -> block.add(statement(indent(2), ".setAttributes(", attributes, ")")));
/* returnType */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package io.jooby.internal.apt;

import static io.jooby.apt.JoobyProcessor.Options.SKIP_ATTRIBUTE_ANNOTATIONS;
import static io.jooby.internal.apt.CodeBlock.indent;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
Expand Down Expand Up @@ -53,16 +54,16 @@ public RouteAttributesGenerator(MvcContext context) {
this.skip = Options.stringListOpt(environment, SKIP_ATTRIBUTE_ANNOTATIONS);
}

public Optional<String> toSourceCode(MvcRoute route, String indent) {
public Optional<String> toSourceCode(MvcRoute route, int indent) {
var attributes = annotationMap(route.getMethod());
if (attributes.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(toSourceCode(annotationMap(route.getMethod()), indent));
return Optional.of(toSourceCode(annotationMap(route.getMethod()), indent + 6));
}
}

private String toSourceCode(Map<String, Object> attributes, String indent) {
private String toSourceCode(Map<String, Object> attributes, int indent) {
var buffer = new StringBuilder();
var separator = ",\n";
var pairPrefix = "";
Expand All @@ -75,26 +76,25 @@ private String toSourceCode(Map<String, Object> attributes, String indent) {
factoryMethod = "ofEntries";
}
buffer.append("java.util.Map.").append(factoryMethod).append("(\n");
var lineIndent = indent + " ";
for (var e : attributes.entrySet()) {
buffer.append(lineIndent);
buffer.append(indent(indent + 4));
buffer.append(pairPrefix);
buffer.append("\"").append(e.getKey()).append("\"").append(", ");
buffer.append(valueToSourceCode(e.getValue(), lineIndent));
buffer.append(CodeBlock.string(e.getKey())).append(", ");
buffer.append(valueToSourceCode(e.getValue(), indent + 4));
buffer.append(pairSuffix).append(separator);
}
buffer.setLength(buffer.length() - separator.length());
buffer.append(")");
return buffer.toString();
}

private Object valueToSourceCode(Object value, String indent) {
private Object valueToSourceCode(Object value, int indent) {
if (value instanceof String) {
return "\"" + value + "\"";
return CodeBlock.string((String) value);
} else if (value instanceof Character) {
return "'" + value + "'";
} else if (value instanceof Map attributeMap) {
return "\n " + indent + toSourceCode(attributeMap, indent + " ");
return "\n " + indent(indent) + toSourceCode(attributeMap, indent + 1);
} else if (value instanceof List list) {
return valueToSourceCode(list, indent);
} else if (value instanceof EnumValue enumValue) {
Expand All @@ -116,7 +116,7 @@ private Object valueToSourceCode(Object value, String indent) {
}
}

private String valueToSourceCode(List values, String indent) {
private String valueToSourceCode(List values, int indent) {
var buffer = new StringBuilder();
buffer.append("java.util.List.of(");
var separator = ", ";
Expand Down
3 changes: 2 additions & 1 deletion modules/jooby-apt/src/test/java/tests/i2417/Issue2417.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public class Issue2417 {
public void shouldNotIgnoreAnnotationOnParam() throws Exception {
new ProcessorRunner(new C2417())
.withRouter(
app -> {
(app, source) -> {
System.out.println(source);
MockRouter router = new MockRouter(app);
assertEquals(
"2417",
Expand Down
21 changes: 21 additions & 0 deletions modules/jooby-apt/src/test/java/tests/i3455/C3455.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Jooby https://jooby.io
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
* Copyright 2014 Edgar Espina
*/
package tests.i3455;

import edu.umd.cs.findbugs.annotations.NonNull;
import io.jooby.annotation.GET;
import io.jooby.annotation.Path;
import io.jooby.annotation.QueryParam;
import io.swagger.v3.oas.annotations.media.Schema;

@Path("/\"path")
public class C3455 {
@GET("/required\"-string-param")
@Schema(description = "test\"ttttt")
public String requiredStringParam(@QueryParam("value\"") @NonNull String value) {
return value;
}
}
26 changes: 26 additions & 0 deletions modules/jooby-apt/src/test/java/tests/i3455/Issue3455.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Jooby https://jooby.io
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
* Copyright 2014 Edgar Espina
*/
package tests.i3455;

import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

import io.jooby.apt.ProcessorRunner;

public class Issue3455 {

@Test
public void shouldEscapeJavaSpecialCharacters() throws Exception {
new ProcessorRunner(new C3455())
.withRouter(
(app, source) -> {
assertTrue(source.toString().contains("\"/\\\"path/required\\\"-string-param\""));
assertTrue(source.toString().contains("\"test\\\"ttttt\""));
assertTrue(source.toString().contains("\"value\\\"\""));
});
}
}

0 comments on commit 8d57c4b

Please sign in to comment.