Skip to content

Commit 7779301

Browse files
committed
Web-Client dependency upgrade to 4.0.4-SNAPSHOT
`XSLTWriterBase::transform` used by both `ModelXSLTWriter` and `ResultSetXSLTWriter`
1 parent b4203e8 commit 7779301

6 files changed

Lines changed: 104 additions & 61 deletions

File tree

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,13 @@
134134
<dependency>
135135
<groupId>${project.groupId}</groupId>
136136
<artifactId>client</artifactId>
137-
<version>4.0.3</version>
137+
<version>4.0.4-SNAPSHOT</version>
138138
<classifier>classes</classifier>
139139
</dependency>
140140
<dependency>
141141
<groupId>${project.groupId}</groupId>
142142
<artifactId>client</artifactId>
143-
<version>4.0.3</version>
143+
<version>4.0.4-SNAPSHOT</version>
144144
<type>war</type>
145145
</dependency>
146146
<!-- required by jsonld-java - version same as Jersey's HTTP Client -->

src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ protected ProxyResourceBase(@Context UriInfo uriInfo, @Context Request request,
156156

157157
List<jakarta.ws.rs.core.MediaType> readableMediaTypesList = new ArrayList<>();
158158
readableMediaTypesList.addAll(mediaTypes.getReadable(Model.class));
159-
readableMediaTypesList.addAll(mediaTypes.getReadable(ResultSet.class)); // not in the superclass
159+
readableMediaTypesList.addAll(mediaTypes.getReadable(ResultSet.class));
160160
this.readableMediaTypes = readableMediaTypesList.toArray(MediaType[]::new);
161161

162162
if (agentContext.isPresent())

src/main/java/com/atomgraph/linkeddatahub/writer/ModelXSLTWriter.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,38 @@
1616
package com.atomgraph.linkeddatahub.writer;
1717

1818
import com.atomgraph.client.util.DataManager;
19+
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
1920
import com.atomgraph.linkeddatahub.model.auth.Agent;
21+
import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider;
2022
import java.lang.annotation.Annotation;
2123
import java.lang.reflect.Type;
2224
import java.security.MessageDigest;
2325
import jakarta.inject.Singleton;
26+
import jakarta.ws.rs.InternalServerErrorException;
2427
import jakarta.ws.rs.Produces;
2528
import jakarta.ws.rs.core.EntityTag;
2629
import jakarta.ws.rs.core.MediaType;
2730
import jakarta.ws.rs.core.MultivaluedMap;
2831
import jakarta.ws.rs.ext.MessageBodyWriter;
2932
import jakarta.ws.rs.ext.Provider;
33+
import java.io.ByteArrayOutputStream;
3034
import java.io.IOException;
3135
import java.io.OutputStream;
3236
import java.math.BigInteger;
3337
import java.util.Arrays;
38+
import java.util.HashMap;
39+
import java.util.Map;
40+
import javax.xml.transform.TransformerException;
41+
import net.sf.saxon.s9api.SaxonApiException;
3442
import net.sf.saxon.s9api.XsltExecutable;
3543
import org.apache.http.HttpHeaders;
3644
import org.apache.jena.ontology.OntModelSpec;
3745
import org.apache.jena.rdf.model.Model;
46+
import org.apache.jena.riot.RDFFormat;
47+
import org.apache.jena.riot.RDFWriter;
48+
import org.apache.jena.riot.SysRIOT;
49+
import org.slf4j.Logger;
50+
import org.slf4j.LoggerFactory;
3851

3952
/**
4053
* JAX-RS writer that renders RDF as HTML using XSLT stylesheet.
@@ -47,6 +60,8 @@
4760
public class ModelXSLTWriter extends XSLTWriterBase implements MessageBodyWriter<Model>
4861
{
4962

63+
private static final Logger log = LoggerFactory.getLogger(ModelXSLTWriter.class);
64+
5065
/**
5166
* Constructs XSLT writer.
5267
*
@@ -85,7 +100,43 @@ public void writeTo(Model model, Class<?> type, Type genericType, Annotation[] a
85100
headerMap.replace(HttpHeaders.ETAG, Arrays.asList(new EntityTag(eTagHash.toString(16))));
86101
}
87102

88-
super.writeTo(processWrite(model), type, type, annotations, mediaType, headerMap, entityStream);
103+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
104+
{
105+
Map<String, Object> properties = new HashMap<>() ;
106+
properties.put("allowBadURIs", "true"); // round-tripping RDF/POST with user input may contain invalid URIs
107+
org.apache.jena.sparql.util.Context cxt = new org.apache.jena.sparql.util.Context();
108+
cxt.set(SysRIOT.sysRdfWriterProperties, properties);
109+
110+
RDFWriter.create().
111+
format(RDFFormat.RDFXML_PLAIN).
112+
context(cxt).
113+
source(model).
114+
output(baos);
115+
116+
transform(baos, mediaType, headerMap, entityStream);
117+
}
118+
catch (TransformerException | SaxonApiException ex)
119+
{
120+
if (log.isErrorEnabled()) log.error("XSLT transformation failed", ex);
121+
throw new InternalServerErrorException(ex);
122+
}
123+
}
124+
125+
/**
126+
* Hook for RDF model processing before write.
127+
*
128+
* @param model RDF model
129+
* @return RDF model
130+
*/
131+
public Model processWrite(Model model)
132+
{
133+
// show foaf:mbox in end-user apps
134+
if (getApplication().get().canAs(EndUserApplication.class)) return model;
135+
// show foaf:mbox for authenticated agents
136+
if (getSecurityContext() != null && getSecurityContext().getUserPrincipal() instanceof Agent) return model;
137+
138+
// show foaf:mbox_sha1sum for all other agents (in admin apps)
139+
return ValidatingModelProvider.hashMboxes(getMessageDigest()).apply(model); // apply processing from superclasses
89140
}
90141

91142
}

src/main/java/com/atomgraph/linkeddatahub/writer/ResultSetXSLTWriter.java

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,17 @@
2626
import jakarta.ws.rs.core.Response;
2727
import jakarta.ws.rs.ext.MessageBodyWriter;
2828
import jakarta.ws.rs.ext.Provider;
29-
import java.io.ByteArrayInputStream;
3029
import java.io.ByteArrayOutputStream;
3130
import java.io.IOException;
3231
import java.io.OutputStream;
3332
import java.lang.annotation.Annotation;
3433
import java.lang.reflect.Type;
3534
import java.math.BigInteger;
36-
import static java.nio.charset.StandardCharsets.UTF_8;
3735
import java.security.MessageDigest;
38-
import java.time.ZonedDateTime;
3936
import java.util.Arrays;
4037
import javax.xml.transform.TransformerException;
41-
import javax.xml.transform.URIResolver;
42-
import javax.xml.transform.stream.StreamSource;
43-
import net.sf.saxon.lib.ResourceResolverWrappingURIResolver;
44-
import net.sf.saxon.lib.UnparsedTextURIResolver;
4538
import net.sf.saxon.s9api.SaxonApiException;
46-
import net.sf.saxon.s9api.Serializer;
47-
import net.sf.saxon.s9api.Xslt30Transformer;
4839
import net.sf.saxon.s9api.XsltExecutable;
49-
import net.sf.saxon.value.DateTimeValue;
5040
import org.apache.http.HttpHeaders;
5141
import org.apache.jena.ontology.OntModelSpec;
5242
import org.apache.jena.query.ResultSetFormatter;
@@ -104,31 +94,7 @@ public void writeTo(ResultSetRewindable results, Class<?> type, Type genericType
10494

10595
ResultSetFormatter.outputAsXML(baos, results);
10696

107-
Xslt30Transformer xsltTrans = getXsltExecutable().load30();
108-
Serializer out = xsltTrans.newSerializer();
109-
out.setOutputStream(entityStream);
110-
out.setOutputProperty(Serializer.Property.ENCODING, UTF_8.name());
111-
112-
if (mediaType.isCompatible(MediaType.TEXT_HTML_TYPE))
113-
{
114-
out.setOutputProperty(Serializer.Property.METHOD, "html");
115-
out.setOutputProperty(Serializer.Property.MEDIA_TYPE, MediaType.TEXT_HTML);
116-
out.setOutputProperty(Serializer.Property.DOCTYPE_SYSTEM, "http://www.w3.org/TR/html4/strict.dtd");
117-
out.setOutputProperty(Serializer.Property.DOCTYPE_PUBLIC, "-//W3C//DTD HTML 4.01//EN");
118-
}
119-
if (mediaType.isCompatible(MediaType.APPLICATION_XHTML_XML_TYPE))
120-
{
121-
out.setOutputProperty(Serializer.Property.METHOD, "xhtml");
122-
out.setOutputProperty(Serializer.Property.MEDIA_TYPE, MediaType.APPLICATION_XHTML_XML);
123-
out.setOutputProperty(Serializer.Property.DOCTYPE_SYSTEM, "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
124-
out.setOutputProperty(Serializer.Property.DOCTYPE_PUBLIC, "-//W3C//DTD XHTML 1.0 Strict//EN");
125-
}
126-
127-
xsltTrans.setResourceResolver(new ResourceResolverWrappingURIResolver((URIResolver)getDataManager()));
128-
xsltTrans.getUnderlyingController().setUnparsedTextURIResolver((UnparsedTextURIResolver)getDataManager());
129-
xsltTrans.getUnderlyingController().setCurrentDateTime(DateTimeValue.fromZonedDateTime(ZonedDateTime.now())); // TO-DO: make TZ configurable
130-
xsltTrans.setStylesheetParameters(getParameters(headerMap));
131-
xsltTrans.transform(new StreamSource(new ByteArrayInputStream(baos.toByteArray())), out);
97+
transform(baos, mediaType, headerMap, entityStream);
13298
}
13399
catch (TransformerException | SaxonApiException ex)
134100
{

src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import com.atomgraph.client.util.DataManager;
1919
import com.atomgraph.client.vocabulary.AC;
20-
import static com.atomgraph.client.writer.ModelXSLTWriterBase.getSource;
2120
import com.atomgraph.linkeddatahub.apps.model.AdminApplication;
2221
import com.atomgraph.linkeddatahub.apps.model.Application;
2322
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
@@ -31,7 +30,6 @@
3130
import com.atomgraph.client.vocabulary.LDT;
3231
import com.atomgraph.core.util.Link;
3332
import com.atomgraph.core.vocabulary.SD;
34-
import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider;
3533
import com.atomgraph.linkeddatahub.server.security.AuthorizationContext;
3634
import com.atomgraph.linkeddatahub.vocabulary.FOAF;
3735
import com.atomgraph.linkeddatahub.vocabulary.LDHC;
@@ -51,8 +49,11 @@
5149
import jakarta.ws.rs.core.Context;
5250
import jakarta.ws.rs.core.MultivaluedMap;
5351
import jakarta.ws.rs.core.SecurityContext;
52+
import java.io.ByteArrayInputStream;
53+
import java.io.ByteArrayOutputStream;
5454
import javax.xml.transform.Source;
5555
import javax.xml.transform.TransformerException;
56+
import javax.xml.transform.stream.StreamSource;
5657
import net.sf.saxon.s9api.QName;
5758
import net.sf.saxon.s9api.SaxonApiException;
5859
import net.sf.saxon.s9api.XdmAtomicValue;
@@ -64,6 +65,7 @@
6465
import org.apache.jena.rdf.model.Model;
6566
import org.apache.jena.rdf.model.ModelFactory;
6667
import org.apache.jena.rdf.model.StmtIterator;
68+
import org.apache.jena.riot.RDFLanguages;
6769
import org.slf4j.Logger;
6870
import org.slf4j.LoggerFactory;
6971

@@ -72,7 +74,7 @@
7274
*
7375
* @author Martynas Jusevičius {@literal <martynas@atomgraph.com>}
7476
*/
75-
public abstract class XSLTWriterBase extends com.atomgraph.client.writer.ModelXSLTWriterBase
77+
public abstract class XSLTWriterBase extends com.atomgraph.client.writer.XSLTWriterBase
7678
{
7779
private static final Logger log = LoggerFactory.getLogger(XSLTWriterBase.class);
7880
private static final Set<String> NAMESPACES;
@@ -219,23 +221,6 @@ public Model getAppModel(Application app, boolean includeEndUserAdmin)
219221

220222
return model;
221223
}
222-
223-
/**
224-
* Hook for RDF model processing before write.
225-
*
226-
* @param model RDF model
227-
* @return RDF model
228-
*/
229-
public Model processWrite(Model model)
230-
{
231-
// show foaf:mbox in end-user apps
232-
if (getApplication().get().canAs(EndUserApplication.class)) return model;
233-
// show foaf:mbox for authenticated agents
234-
if (getSecurityContext() != null && getSecurityContext().getUserPrincipal() instanceof Agent) return model;
235-
236-
// show foaf:mbox_sha1sum for all other agents (in admin apps)
237-
return ValidatingModelProvider.hashMboxes(getMessageDigest()).apply(model); // apply processing from superclasses
238-
}
239224

240225
/**
241226
* Override the Web-Client's implementation because LinkedDataHub concatenates <code>Link</code> headers into a single value.
@@ -274,6 +259,25 @@ public URI getLinkURI(MultivaluedMap<String, Object> headerMap, ObjectProperty p
274259
return null;
275260
}
276261

262+
/**
263+
* Creates stream source from RDF model.
264+
* The model is serialized using the RDF/XML syntax.
265+
*
266+
* @param model RDF model
267+
* @return XML stream source
268+
* @throws IOException I/O error
269+
*/
270+
public StreamSource getSource(Model model) throws IOException
271+
{
272+
if (model == null) throw new IllegalArgumentException("Model cannot be null");
273+
274+
try (ByteArrayOutputStream stream = new ByteArrayOutputStream())
275+
{
276+
model.write(stream, RDFLanguages.RDFXML.getName(), null);
277+
return new StreamSource(new ByteArrayInputStream(stream.toByteArray()));
278+
}
279+
}
280+
277281
/**
278282
* Returns system application.
279283
*

src/main/java/com/atomgraph/linkeddatahub/writer/function/Construct.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
import com.atomgraph.client.vocabulary.SPIN;
2020
import com.atomgraph.linkeddatahub.vocabulary.LDH;
21-
import com.atomgraph.linkeddatahub.writer.ModelXSLTWriter;
21+
import java.io.ByteArrayInputStream;
22+
import java.io.ByteArrayOutputStream;
2223
import java.io.IOException;
24+
import javax.xml.transform.stream.StreamSource;
2325
import net.sf.saxon.s9api.ExtensionFunction;
2426
import net.sf.saxon.s9api.ItemType;
2527
import net.sf.saxon.s9api.ItemTypeFactory;
@@ -35,6 +37,7 @@
3537
import org.apache.jena.rdf.model.ModelFactory;
3638
import org.apache.jena.rdf.model.Resource;
3739
import org.apache.jena.rdf.model.ResourceFactory;
40+
import org.apache.jena.riot.RDFLanguages;
3841
import org.apache.jena.vocabulary.RDF;
3942

4043
/**
@@ -105,14 +108,33 @@ public XdmValue call(XdmValue[] arguments) throws SaxonApiException
105108
}
106109
);
107110

108-
return getProcessor().newDocumentBuilder().build(ModelXSLTWriter.getSource(model));
111+
return getProcessor().newDocumentBuilder().build(getSource(model));
109112
}
110113
catch (IOException ex)
111114
{
112115
throw new SaxonApiException(ex);
113116
}
114117
}
115118

119+
/**
120+
* Creates stream source from RDF model.
121+
* The model is serialized using the RDF/XML syntax.
122+
*
123+
* @param model RDF model
124+
* @return XML stream source
125+
* @throws IOException I/O error
126+
*/
127+
public StreamSource getSource(Model model) throws IOException
128+
{
129+
if (model == null) throw new IllegalArgumentException("Model cannot be null");
130+
131+
try (ByteArrayOutputStream stream = new ByteArrayOutputStream())
132+
{
133+
model.write(stream, RDFLanguages.RDFXML.getName(), null);
134+
return new StreamSource(new ByteArrayInputStream(stream.toByteArray()));
135+
}
136+
}
137+
116138
/**
117139
* Returns the associated XSLT processor.
118140
*

0 commit comments

Comments
 (0)