Skip to content

Commit 3fbdcd7

Browse files
authored
Merge pull request #2357 from dizzzz/feature/4xx_adaptive_output_logs
4xx: Implement adaptive serialisation for fn:trace and util:log* functions
2 parents 4d9d51e + af217ed commit 3fbdcd7

File tree

3 files changed

+61
-63
lines changed

3 files changed

+61
-63
lines changed

src/org/exist/xquery/functions/fn/FunTrace.java

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,17 @@
2121
*/
2222
package org.exist.xquery.functions.fn;
2323

24-
import java.io.StringWriter;
25-
import java.io.Writer;
2624
import org.exist.dom.QName;
27-
import org.exist.storage.serializers.Serializer;
28-
import org.exist.xquery.BasicFunction;
29-
import org.exist.xquery.Cardinality;
30-
import org.exist.xquery.Function;
31-
import org.exist.xquery.FunctionSignature;
32-
import org.exist.xquery.XPathException;
33-
import org.exist.xquery.XQueryContext;
34-
import org.exist.xquery.value.FunctionParameterSequenceType;
35-
import org.exist.xquery.value.FunctionReturnSequenceType;
36-
import org.exist.xquery.value.Item;
37-
import org.exist.xquery.value.NodeValue;
38-
import org.exist.xquery.value.Sequence;
39-
import org.exist.xquery.value.SequenceIterator;
40-
import org.exist.xquery.value.SequenceType;
41-
import org.exist.xquery.value.Type;
42-
import org.exist.xquery.value.ValueSequence;
25+
import org.exist.util.serializer.XQuerySerializer;
26+
import org.exist.xquery.*;
27+
import org.exist.xquery.value.*;
4328
import org.xml.sax.SAXException;
4429

30+
import javax.xml.transform.OutputKeys;
31+
import java.io.IOException;
32+
import java.io.StringWriter;
33+
import java.util.Properties;
34+
4535
/**
4636
* @author Dannes Wessels
4737
* @author Wolfgang Meier ([email protected])
@@ -72,18 +62,12 @@ public FunTrace(XQueryContext context) {
7262
* @see org.exist.xquery.BasicFunction#eval(Sequence[], Sequence)
7363
*/
7464
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
75-
76-
// TODO Add TRACE log statements using log4j
77-
// TODO Figure out why XQTS still does not work
78-
// TODO Remove unneeded comments
79-
65+
8066
String label = args[1].getStringValue();
8167
if(label==null){
8268
label="";
8369
}
84-
85-
final Serializer serializer= context.getBroker().getSerializer();
86-
70+
8771
Sequence result ;
8872

8973
if(args[0].isEmpty()){
@@ -95,38 +79,31 @@ public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathExce
9579

9680
int position = 0;
9781

82+
// Force adaptive serialization
83+
final Properties props = new Properties();
84+
props.setProperty(OutputKeys.METHOD, "adaptive");
85+
9886
for (final SequenceIterator i = args[0].iterate(); i.hasNext();) {
9987

10088
// Get item
10189
final Item next = i.nextItem();
10290

103-
// Only write if debug mode
91+
// Only write if logger is set to debug mode
10492
if (LOG.isDebugEnabled()) {
105-
106-
String value = null;
107-
position++;
10893

109-
final int type = next.getType();
110-
111-
// Serialize an element type
112-
if (Type.ELEMENT == type) {
113-
final Writer sw = new StringWriter();
114-
try {
115-
serializer.serialize((NodeValue) next, sw);
94+
position++;
11695

117-
} catch (final SAXException ex) {
118-
LOG.error(ex.getMessage());
119-
}
120-
value = sw.toString();
96+
try (StringWriter writer = new StringWriter()) {
97+
XQuerySerializer xqs = new XQuerySerializer(context.getBroker(), props, writer);
98+
xqs.serialize(next.toSequence());
12199

122-
// Get string value for other types
123-
} else {
124-
value = next.getStringValue();
100+
// Write to log
101+
LOG.debug("{} [{}] [{}]: {}", label, position, Type.getTypeName(next.getType()), writer.toString());
125102

103+
} catch (IOException | SAXException e) {
104+
throw new XPathException(this, e.getMessage());
126105
}
127-
128-
// Write to log
129-
LOG.debug(label + " [" + position + "]: " + Type.getTypeName(type) + ": " + value);
106+
130107
}
131108

132109
// Add to result

src/org/exist/xquery/functions/fn/JSON.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,26 @@ public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathExce
9595
}
9696
}
9797

98+
JsonFactory factory = createJsonFactory(liberal);
99+
100+
if (isCalledAs("parse-json")) {
101+
return parse(args[0], handleDuplicates, factory);
102+
} else {
103+
return parseResource(args[0], handleDuplicates, factory);
104+
}
105+
}
106+
107+
/**
108+
* Create and initialize JSON factory.
109+
*
110+
* @param liberal Set TRUE to allow non standard JSON features.
111+
*
112+
* @return JSON factory
113+
*/
114+
public static JsonFactory createJsonFactory(boolean liberal) {
98115
JsonFactory factory = new JsonFactory();
99116
factory.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
117+
100118
// duplicates are handled in readValue
101119
factory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, false);
102120
if (liberal) {
@@ -106,12 +124,7 @@ public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathExce
106124
factory.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
107125
factory.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
108126
}
109-
110-
if (isCalledAs("parse-json")) {
111-
return parse(args[0], handleDuplicates, factory);
112-
} else {
113-
return parseResource(args[0], handleDuplicates, factory);
114-
}
127+
return factory;
115128
}
116129

117130
private Sequence parse(Sequence json, String handleDuplicates, JsonFactory factory) throws XPathException {

src/org/exist/xquery/functions/util/LogFunction.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,16 @@
2727
import org.exist.dom.QName;
2828
import org.exist.source.StringSource;
2929
import org.exist.storage.serializers.Serializer;
30+
import org.exist.util.serializer.XQuerySerializer;
3031
import org.exist.xquery.*;
3132
import org.exist.xquery.value.*;
3233
import org.xml.sax.SAXException;
3334

35+
import javax.xml.transform.OutputKeys;
36+
import java.io.IOException;
37+
import java.io.StringWriter;
38+
import java.util.Properties;
39+
3440

3541
/**
3642
* @author Wolfgang Meier ([email protected])
@@ -84,6 +90,10 @@ public LogFunction(XQueryContext context, FunctionSignature signature) {
8490

8591
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
8692

93+
// Force adaptive serialization
94+
final Properties props = new Properties();
95+
props.setProperty(OutputKeys.METHOD, "adaptive");
96+
8797
SequenceIterator i;
8898

8999
final String calledAs = getName().getLocalPart();
@@ -137,17 +147,15 @@ public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathExce
137147
// Iterate over all input
138148
while (i.hasNext()) {
139149
final Item next = i.nextItem();
140-
if (Type.subTypeOf(next.getType(), Type.NODE)) {
141-
final Serializer serializer = context.getBroker().getSerializer();
142-
serializer.reset();
143-
try {
144-
buf.append(serializer.serialize((NodeValue) next));
145-
} catch (final SAXException e) {
146-
throw (new XPathException(this, "An exception occurred while serializing node to log: " + e.getMessage(), e));
147-
}
148-
} else {
149-
buf.append(next.getStringValue());
150+
try (StringWriter writer = new StringWriter()) {
151+
XQuerySerializer xqs = new XQuerySerializer(context.getBroker(), props, writer);
152+
xqs.serialize(next.toSequence());
153+
buf.append(writer.toString());
154+
155+
} catch (IOException | SAXException e) {
156+
throw new XPathException(this, e.getMessage());
150157
}
158+
151159
}
152160

153161
// Finally write the log

0 commit comments

Comments
 (0)