ppalaga commented on issue #4065:
URL: https://github.com/apache/camel-quarkus/issues/4065#issuecomment-2429377856

   I wrote down this report for OpenJDK. Could you guys please review it before 
we submit it?
   
   ---->8-----
   
   
   Setting translet-name and package-name via TransformerFactory.setAttribute 
has unexpected effects.
   
   ## Background
   
   GraalVM native executables do not allow loading classes at runtime due to 
its closed world assumption. To make XSLT work with them, we generate XSLT 
Translet classes at build time and let native-image compile them into the 
native executable. For that to work reliably, we need to be able to set the 
name of the generated class so that we are then able to find the class and pass 
it to the native compiler.
   
   ## Steps to reproduce
   
   To generate a Translet class for a given XSL file, we perform steps similar 
to the following:
   
   ```java
   
   import javax.xml.transform.TransformerFactory;
   import javax.xml.transform.stream.StreamSource;
   import java.io.File;
   import java.nio.file.Files;
   import java.nio.file.Path;
   import java.util.Comparator;
   
   public class Main {
           public static void main(String[] args) throws Exception {
               TransformerFactory tf = TransformerFactory.newInstance();
       
               tf.setAttribute("generate-translet", true);
               tf.setAttribute("translet-name", "MyTranslet");
               tf.setAttribute("package-name", "org.acme");
               tf.setAttribute("destination-directory", "test");
       
               Path test = Path.of("test");
               if (Files.exists(test)) {
                   
Files.walk(test).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
               }
   
               File xslFile = new File(args[0]);
               tf.newTemplates(new 
StreamSource(Files.newInputStream(xslFile.toPath())));
   
               
Files.list(Path.of("test/org/acme")).forEach(System.out::println);
           }
   }
   
   ```
   
   The reproducer code can be taken from 
https://github.com/zhfeng/jdk-xalan-issue-reproducer .
   
   When this program is compiled through `javac Main.java` and run via `java 
Main test.xsl`, where `test.xsl` is any simple XSL file, such as
   
   ```xml
   
   <?xml version="1.0" encoding="iso-8859-1"?>
   <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
       <xsl:output method="xml" version="1.0" encoding="UTF-8"/>
   
       <xsl:template match="/request">
           <xsl:variable name="name" select="//name/text()"/>
           <response>
               <message>
                   <xsl:value-of select="concat('Hello, ', $name)"/>
               </message>
           </response>
       </xsl:template>
   </xsl:stylesheet>
   
   ```
   
   then, we *expect* to find the generated translet file under 
`test/org/acme/MyTranslet.class`.
   
   *In reality*, the generated translet is under 
`test/org/acme/die_verwandlung.class`.
   
   ## Analysis
   
   The execution flow goes via 
`com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(Source)`,
 where a new `com.sun.org.apache.xalan.internal.xsltc.trax.XSLTC` is created 
and its `setClassName(String)` and `setPackageName(String)` are called.
   
   `XSLTC.setClassName(String)` does some sanitization of the passed 
`className` and if the `_packageName` field is set, it sets the `_className` 
field to `_packageName + '.' + name`.
   
   Because `XSLTC._packageName` is initialized to `"die.verwandlung"`, then, 
after the first call of `setClassName("MyTranslet")`, the value of 
`_packageName` is `"die.verwandlung.MyTranslet"`.
   
   The `XSLTC.setPackageName("org.acme")` called afterwards, first sets the 
`_packageName` field to the passed value and then, if `_className != null`, it 
calls `setClassName(_className)`. 
   
   In our situation, it effectively means calling 
`setClassName("die.verwandlung.MyTranslet")`.
   
   The sanitization of the passed value done within this second 
`setClassName()` call transforms `"die.verwandlung.MyTranslet"` into 
`"die_verwandlung"`.
   
   Afterwards, the `_className` field is set to `_packageName + '.' + name` 
which is `"org.acme" + '.' + "die_verwandlung"` in our case.
   
   Observation: the ASF Xalan does not initialize `XSLTC._packageName` to 
`"die.verwandlung"` and therefore the reproducer code works as expected there.
   
   ## Possible solutions
   
   A. In `TransformerFactoryImpl.newTemplates(Source)`, call 
`XSLTC.setPackageName(String)` before `XSLTC.setClassName(String)`.
   
   B. In `XSLTC.setPackageName(String)`, instead of calling 
`setClassName(_className)`, pass only the simple class name extracted from the 
`_className` field to `setClassName(String)`.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@camel.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to