Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import net.sf.saxon.s9api.*;
import net.sf.saxon.serialize.SerializationProperties;
import net.sf.saxon.trans.UncheckedXPathException;
import org.apache.commons.io.output.StringBuilderWriter;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use java.io.StringWriter here please

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.dom.QName;
Expand Down Expand Up @@ -162,6 +163,34 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro

final Xslt30Transformer xslt30Transformer = xsltExecutable.load30();

xslt30Transformer.setMessageListener((content, terminate, locator) ->{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please have this as a separate class at the bottom of the file rather than a large lambda here,

e.g.

private static class XsltMessageListener implements MessageListener {
...
}

try {
final StringBuilderWriter writer = new StringBuilderWriter();
final Serializer serializer = context.getBroker().getBrokerPool().getSaxonProcessor().newSerializer();
serializer.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
serializer.setOutputWriter(writer);
serializer.serializeNode(content);

final String source;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Nullable final String source;

Import the annotation from googlecode findbugs library please

final int sourceLine;
final int sourceColumn;
if (locator != null) {
source = locator.getSystemId();
sourceLine = locator.getLineNumber();
sourceColumn = locator.getColumnNumber();
} else {
source = null;
sourceLine = -1;
sourceColumn = -1;
}

LOGGER.info("<xsl:message terminate=\"{}\" source=\"{}\" sourceLine=\"{}\" sourceColumn=\"{}\">{}</xsl:message>",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if source is null please don't print out the source= bit. Same goes for if sourceLine is -1 please don't print out the sourceLine and sourceColumn

terminate, source, sourceLine, sourceColumn, writer.toString());
} catch (final SaxonApiException e) {
LOGGER.error("Unable to serialize xsl:message content", e);
}
});

options.initialMode.ifPresent(qNameValue -> xslt30Transformer.setInitialMode(Convert.ToSaxon.of(qNameValue.getQName())));
xslt30Transformer.setInitialTemplateParameters(options.templateParams, false);
xslt30Transformer.setInitialTemplateParameters(options.tunnelParams, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
package org.exist.xquery.functions.fn.transform;

import com.evolvedbinary.j8fu.tuple.Tuple2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.exist.EXistException;
import org.exist.collections.Collection;
import org.exist.security.PermissionDeniedException;
Expand Down Expand Up @@ -49,7 +54,9 @@

import javax.xml.transform.Source;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;

import static com.evolvedbinary.j8fu.tuple.Tuple.Tuple;
import static org.junit.Assert.*;
Expand Down Expand Up @@ -247,6 +254,46 @@ public void identityMixedMemoryAndPersistentDom() throws XPathException, Permiss
expectQuery(IDENTITY_MIXED_XSLT_QUERY_5, expected);
}

@Test
public void xslMessageIsLogged() throws EXistException, PermissionDeniedException, IOException {
final CapturingAppender appender = new CapturingAppender();
appender.start();

final org.apache.logging.log4j.core.Logger transformLogger =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fully qualified names hare are not needed

(org.apache.logging.log4j.core.Logger) LogManager.getLogger(Transform.class);
transformLogger.addAppender(appender);

try {
final String query =
"fn:transform(map {\n" +
" \"stylesheet-text\": '<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"3.0\">\n" +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

version should be 2.0 not 3.0

" <xsl:template match=\"/\">\n" +
" <xsl:message>Hello from XSLT</xsl:message>\n" +
" <out/>\n" +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this?

" </xsl:template>\n" +
" </xsl:stylesheet>',\n" +
" \"source-node\": document { <in/> }\n" +
"})?output";

final BrokerPool pool = existEmbeddedServer.getBrokerPool();
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()));
final XQueryUtil.QueryResult queryResult = XQueryUtil.query(broker, new StringSource(query), false, null, null, null, null, null)) {
assertNotNull(queryResult.result);
} catch (final XPathException e) {
fail("Transform should have succeeded: " + e.getMessage());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just throw the exception from tests

}

final Optional<String> logged = appender.getMessages().stream()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need a stream here. Please avoid streams where possible.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need Optional.

.filter(message -> message.contains("<xsl:message"))
.findFirst();

assertTrue("Expected an xsl:message log entry", logged.isPresent());
assertTrue(logged.get().contains("Hello from XSLT"));
} finally {
transformLogger.removeAppender(appender);
}
}

private static void expectQuery(final String query, final Source expected) throws EXistException, XPathException, PermissionDeniedException, IOException {
final BrokerPool pool = existEmbeddedServer.getBrokerPool();
try(final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()));
Expand Down Expand Up @@ -298,4 +345,26 @@ private static void createCollection(final DBBroker broker, final Txn transactio
}
}
}

/**
* A minimal in-memory Log4j2 appender that just remembers every
* formatted message it receives, so a test can inspect what was logged.
*/
private static class CapturingAppender extends AbstractAppender {

private final List<String> messages = new CopyOnWriteArrayList<>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not be CopyOnWriteArrayList


CapturingAppender() {
super("capturing-appender", null, PatternLayout.createDefaultLayout(), false, Property.EMPTY_ARRAY);
}

@Override
public void append(final LogEvent event) {
messages.add(event.getMessage().getFormattedMessage());
}

List<String> getMessages() {
return messages;
}
}
}
Loading