package org.openprovenance.prov.xml; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBElement; import org.openprovenance.prov.model.Namespace; import org.w3c.dom.ls.LSInput; import org.w3c.dom.ls.LSResourceResolver; import org.xml.sax.SAXException; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Schema; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.Source; /** Deserialiser of OPM Graphs. */ public class ProvDeserialiser { static ProvUtilities utils=new ProvUtilities(); // it is recommended by the Jaxb documentation that one JAXB // context is created for one application. This object is thread // safe (in the sun impelmenation, but not // marshallers/unmarshallers. static protected JAXBContext jc; public ProvDeserialiser () throws JAXBException { if (jc==null) jc = JAXBContext.newInstance( ProvFactory.packageList ); // note, it is sometimes recommended to pass the current classloader } public ProvDeserialiser (String packageList) throws JAXBException { if (jc==null) jc = JAXBContext.newInstance(packageList); } private static ThreadLocal<ProvDeserialiser> threadDeserialiser= new ThreadLocal<ProvDeserialiser> () { protected synchronized ProvDeserialiser initialValue () { try { return new ProvDeserialiser(); } catch (JAXBException jxb) { throw new RuntimeException("ProvDeserialiser: deserialiser init failure()"); } } }; public static ProvDeserialiser getThreadProvDeserialiser() { return threadDeserialiser.get(); } public Document deserialiseDocument (File serialised) throws JAXBException { Unmarshaller u=jc.createUnmarshaller(); Object root= u.unmarshal(serialised); @SuppressWarnings("unchecked") Document res=(Document)((JAXBElement<Document>) root).getValue(); updateNamespaces(res); return res; } /** * After reading a document, this method should be called to ensure that Namespaces are properly chained. * @param document a {@link Document} to update */ public void updateNamespaces(Document document) { Namespace rootNamespace = Namespace.gatherNamespaces(document); document.setNamespace(rootNamespace); for (org.openprovenance.prov.model.Bundle bu: utils.getBundle(document)) { Namespace ns=bu.getNamespace(); if (ns!=null) { ns.setParent(rootNamespace); } else { ns=new Namespace(); ns.setParent(rootNamespace); bu.setNamespace(ns); } } } public Document deserialiseDocument (InputStream is) throws JAXBException { Unmarshaller u=jc.createUnmarshaller(); Object root= u.unmarshal(is); @SuppressWarnings("unchecked") Document res=(Document)((JAXBElement<Document>) root).getValue(); updateNamespaces(res); return res; } class ResourceResolver implements LSResourceResolver { public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { System.out.println("resolveResource " + type + "\n" + namespaceURI + "\n" + publicId + "\n" + systemId + "\n" + baseURI); // note: in this sample, the XSD's are expected to be in the root of the classpath InputStream resourceAsStream = this.getClass().getClassLoader() .getResourceAsStream("/w3c/"+systemId); return new Input(publicId, systemId, resourceAsStream); } } class Input implements LSInput { private String publicId; private String systemId; public String getPublicId() { return publicId; } public void setPublicId(String publicId) { this.publicId = publicId; } public String getBaseURI() { return null; } public InputStream getByteStream() { return null; } public boolean getCertifiedText() { return false; } public Reader getCharacterStream() { return null; } public String getEncoding() { return null; } public String getStringData() { synchronized (inputStream) { try { byte[] input = new byte[inputStream.available()]; inputStream.read(input); String contents = new String(input); return contents; } catch (IOException e) { // e.printStackTrace(); //System.out.println("Exception " + e); return null; } } } public void setBaseURI(String baseURI) { } public void setByteStream(InputStream byteStream) { } public void setCertifiedText(boolean certifiedText) { } public void setCharacterStream(Reader characterStream) { } public void setEncoding(String encoding) { } public void setStringData(String stringData) { } public String getSystemId() { return systemId; } public void setSystemId(String systemId) { this.systemId = systemId; } public BufferedInputStream getInputStream() { return inputStream; } public void setInputStream(BufferedInputStream inputStream) { this.inputStream = inputStream; } private BufferedInputStream inputStream; public Input(String publicId, String sysId, InputStream input) { this.publicId = publicId; this.systemId = sysId; this.inputStream = new BufferedInputStream(input); } } public Document validateDocument(String[] schemaFiles, File serialised) throws JAXBException, SAXException, IOException { int schemaCount; schemaCount = 2; //System.setProperty("javax.xml.validation.SchemaFactory:http://www.w3.org/XML/XMLSchema/v1.1", // "org.apache.xerces.jaxp.validation.XMLSchema11Factory"); SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); // "http://www.w3.org/XML/XMLSchema/v1.1"); // associate the schema factory with the resource resolver, which is responsible for resolving the imported XSD's //sf.setResourceResolver(new ResourceResolver()); Source[] sources = new Source[schemaCount + schemaFiles.length]; sources = new Source[schemaCount + schemaFiles.length]; sources[0] = new StreamSource(this.getClass().getResourceAsStream("/w3c/" + "xml.xsd")); sources[1] = new StreamSource(this.getClass().getResourceAsStream("/w3c/" + "prov-single.xsd")); int i = 0; for (String schemaFile : schemaFiles) { sources[schemaCount + i] = new StreamSource(new File(schemaFile)); i++; } Schema schema = sf.newSchema(sources); Unmarshaller u = jc.createUnmarshaller(); u.setSchema(schema); Object root = u.unmarshal(serialised); @SuppressWarnings("unchecked") Document res = (Document) ((JAXBElement<Document>) root).getValue(); return res; } }