Skip to content

Commit

Permalink
Merge pull request #17902 from Sanne/XmlParsingOpt
Browse files Browse the repository at this point in the history
native-image optimisations to allow excluding the JDK's XML parser from a PostgreSQL / Hibernate app
  • Loading branch information
Sanne authored Jun 16, 2021
2 parents 43cf24d + 962dc02 commit f2b5115
Show file tree
Hide file tree
Showing 19 changed files with 1,284 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/native-tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
{
"category": "Data5",
"timeout": 65,
"test-modules": "jpa-postgresql, narayana-stm, narayana-jta, reactive-pg-client, hibernate-reactive-postgresql",
"test-modules": "jpa-postgresql, jpa-postgresql-withxml, narayana-stm, narayana-jta, reactive-pg-client, hibernate-reactive-postgresql",
"os-name": "ubuntu-latest"
},
{
Expand Down
1 change: 1 addition & 0 deletions .github/quarkus-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ triage:
- integration-tests/jpa-mssql/
- integration-tests/jpa-mysql/
- integration-tests/jpa-postgresql/
- integration-tests/jpa-postgresql-withxml/
- integration-tests/jpa-without-entity/
- integration-tests/jpa/
- integration-tests/infinispan-cache-jpa/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package io.quarkus.jdbc.postgresql.runtime.graal;

import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.postgresql.core.BaseConnection;
import org.postgresql.util.GT;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;
import org.postgresql.xml.DefaultPGXmlFactoryFactory;
import org.postgresql.xml.PGXmlFactoryFactory;

/**
* Used by PgSQLXML: easier to keep the actual code separated from the substitutions.
*/
public final class DomHelper {

//This is the actual code reaching to the JDK XML types; no other code except
//the reflective call in the previous method should trigger this inclusion.
public static String processDomResult(DOMResult domResult, BaseConnection conn) throws SQLException {
return maybeProcessAsDomResult(domResult, conn);
}

// This is only ever invoked if field domResult got initialized; which in turn
// is only possible if setResult(Class) is reacheable.
public static String maybeProcessAsDomResult(DOMResult domResult, BaseConnection conn) throws SQLException {
try {
return (String) DomHelper.class.getMethod(obfuscatedMethodName(), DOMResult.class, BaseConnection.class)
.invoke(null, domResult, conn);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new RuntimeException("Unexpected failure in reflective call - please report", e);
} catch (InvocationTargetException e) {
final Throwable cause = e.getCause();
if (cause instanceof SQLException) {
//Propagate normal SQLException(s):
throw (SQLException) cause;
} else {
throw new RuntimeException("Unexpected failure in reflective call - please report", e);
}
}
}

//When GraalVM can figure out a constant name for the target method to be invoked reflectively,
//it automatically registers it for reflection. We don't want that to happen in this particular case.
private static String obfuscatedMethodName() {
return "reallyProcessDom" + "Result";
}

public static String reallyProcessDomResult(DOMResult domResult, BaseConnection conn) throws SQLException {
TransformerFactory factory = getXmlFactoryFactory(conn).newTransformerFactory();
try {
Transformer transformer = factory.newTransformer();
DOMSource domSource = new DOMSource(domResult.getNode());
StringWriter stringWriter = new StringWriter();
StreamResult streamResult = new StreamResult(stringWriter);
transformer.transform(domSource, streamResult);
return stringWriter.toString();
} catch (TransformerException te) {
throw new PSQLException(GT.tr("Unable to convert DOMResult SQLXML data to a string."),
PSQLState.DATA_ERROR, te);
}
}

private static PGXmlFactoryFactory getXmlFactoryFactory(BaseConnection conn) throws SQLException {
if (conn != null) {
return conn.getXmlFactoryFactory();
}
return DefaultPGXmlFactoryFactory.INSTANCE;
}
}
Loading

0 comments on commit f2b5115

Please sign in to comment.