diff --git a/src/main/java/com/xmlcalabash/core/XProcConstants.java b/src/main/java/com/xmlcalabash/core/XProcConstants.java index 7430572b..105f4cbd 100644 --- a/src/main/java/com/xmlcalabash/core/XProcConstants.java +++ b/src/main/java/com/xmlcalabash/core/XProcConstants.java @@ -115,6 +115,7 @@ public class XProcConstants { public static final QName cx_depends_on = new QName("cx",NS_CALABASH_EX,"depends-on"); public static final QName cx_cache = new QName("cx",NS_CALABASH_EX,"cache"); public static final QName cx_type = new QName("cx",NS_CALABASH_EX,"type"); + public static final QName cx_forced_content_type = new QName("cx", NS_CALABASH_EX, "forced-content-type"); public static final QName xs_QName = new QName("xs", NS_XMLSCHEMA, "QName"); public static final QName xs_untypedAtomic = new QName("xs", NS_XMLSCHEMA, "untypedAtomic"); diff --git a/src/main/java/com/xmlcalabash/drivers/Main.java b/src/main/java/com/xmlcalabash/drivers/Main.java index db95feef..5635a1fb 100644 --- a/src/main/java/com/xmlcalabash/drivers/Main.java +++ b/src/main/java/com/xmlcalabash/drivers/Main.java @@ -282,14 +282,14 @@ boolean run(UserArgs userArgs, XProcConfiguration config) throws SaxonApiExcepti ReadableData rd; switch (input.getKind()) { case URI: - rd = new ReadableData(runtime, c_data, input.getUri(), input.getContentType()); + rd = new ReadableData(runtime, c_data, input.getUri(), null, input.getContentType()); doc = rd.read(); break; case INPUT_STREAM: InputStream inputStream = input.getInputStream(); try { - rd = new ReadableData(runtime, c_data, inputStream, input.getContentType()); + rd = new ReadableData(runtime, c_data, inputStream, null, input.getContentType()); doc = rd.read(); } finally { Closer.close(inputStream); diff --git a/src/main/java/com/xmlcalabash/io/ReadableData.java b/src/main/java/com/xmlcalabash/io/ReadableData.java index 1e302f9e..bc167691 100644 --- a/src/main/java/com/xmlcalabash/io/ReadableData.java +++ b/src/main/java/com/xmlcalabash/io/ReadableData.java @@ -52,6 +52,7 @@ public class ReadableData implements ReadablePipe { public static final QName _encoding = new QName("","encoding"); public static final QName c_encoding = new QName("c",XProcConstants.NS_XPROC_STEP, "encoding"); private String contentType = null; + private String forcedContentType = null; private Logger logger = LoggerFactory.getLogger(ReadablePipe.class); private int pos = 0; private QName wrapper = null; @@ -64,19 +65,28 @@ public class ReadableData implements ReadablePipe { /* Creates a new instance of ReadableDocument */ public ReadableData(XProcRuntime runtime, QName wrapper, String uri, String contentType) { - this(runtime, wrapper, uri, null, contentType); + this(runtime, wrapper, uri, null, contentType, null); + } + + public ReadableData(XProcRuntime runtime, QName wrapper, String uri, String contentType, String forcedContentType) { + this(runtime, wrapper, uri, null, contentType, forcedContentType); } public ReadableData(XProcRuntime runtime, QName wrapper, InputStream inputStream, String contentType) { - this(runtime, wrapper, null, inputStream, contentType); + this(runtime, wrapper, null, inputStream, contentType, null); + } + + public ReadableData(XProcRuntime runtime, QName wrapper, InputStream inputStream, String contentType, String forcedContentType) { + this(runtime, wrapper, null, inputStream, contentType, forcedContentType); } - private ReadableData(XProcRuntime runtime, QName wrapper, String uri, InputStream inputStream, String contentType) { + private ReadableData(XProcRuntime runtime, QName wrapper, String uri, InputStream inputStream, String contentType, String forcedContentType) { this.runtime = runtime; this.uri = uri; this.inputStream = inputStream; this.wrapper = wrapper; this.contentType = contentType; + this.forcedContentType = forcedContentType; } private DocumentSequence ensureDocuments() { @@ -96,7 +106,7 @@ private DocumentSequence ensureDocuments() { try { read(userContentType, null, inputStream, getContentType()); } finally { - // This is the only case where the inputStream should be + // This is the only case where the inputStream should be // closed. inputStream.close(); } @@ -117,7 +127,7 @@ public void load(URI dataURI, String serverContentType, serverContentType); } }); - // Also no need to close the input stream here, since + // Also no need to close the input stream here, since // DataStore implementations close the input stream when // necessary. } @@ -127,7 +137,7 @@ public void load(URI dataURI, String serverContentType, return documents; } - + // This method does NOT close the InputStream; it relies on the caller to close // the InputStream, as appropriate. private void read(String userContentType, URI dataURI, @@ -149,7 +159,10 @@ private void read(String userContentType, URI dataURI, TreeWriter tree = new TreeWriter(runtime); tree.startDocument(dataURI); - if (contentType != null && "content/unknown".equals(serverContentType)) { + if ((forcedContentType != null) && !"content/unknown".equals(forcedContentType)) { + // pretend... + serverContentType = forcedContentType; + } else if ((contentType != null) && "content/unknown".equals(serverContentType)) { // pretend... serverContentType = contentType; } diff --git a/src/main/java/com/xmlcalabash/model/DataBinding.java b/src/main/java/com/xmlcalabash/model/DataBinding.java index abbaaf23..15c3d60e 100644 --- a/src/main/java/com/xmlcalabash/model/DataBinding.java +++ b/src/main/java/com/xmlcalabash/model/DataBinding.java @@ -37,6 +37,7 @@ public class DataBinding extends Binding { private String href = null; private QName wrapper = XProcConstants.c_data; private String contentType = null; + private String forcedContentType = null; /* Creates a new instance of DocumentBinding */ public DataBinding() { @@ -75,6 +76,14 @@ public String getContentType() { return contentType; } + public void setForcedContentType(String forcedContentType) { + this.forcedContentType = forcedContentType; + } + + public String getForcedContentType() { + return forcedContentType; + } + protected void dump(int depth) { String indent = ""; for (int count = 0; count < depth; count++) { diff --git a/src/main/java/com/xmlcalabash/model/Parser.java b/src/main/java/com/xmlcalabash/model/Parser.java index d1491dcd..6d3bd703 100644 --- a/src/main/java/com/xmlcalabash/model/Parser.java +++ b/src/main/java/com/xmlcalabash/model/Parser.java @@ -46,6 +46,8 @@ import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; +import static com.xmlcalabash.core.XProcConstants.cx_forced_content_type; + /** * * @author ndw @@ -770,6 +772,7 @@ private DataBinding readData(XdmNode node) { String wrappfx = node.getAttributeValue(new QName("wrapper-prefix")); String wrapns = node.getAttributeValue(new QName("wrapper-namespace")); String contentType = node.getAttributeValue(new QName("content-type")); + String forcedContentType = node.getAttributeValue(cx_forced_content_type); if (wrappfx != null && wrapns == null) { throw XProcException.dynamicError(34, node, "You cannot specify a prefix without a namespace."); @@ -804,6 +807,10 @@ private DataBinding readData(XdmNode node) { doc.setContentType(contentType); } + if (forcedContentType != null) { + doc.setForcedContentType(forcedContentType); + } + for (XdmNode snode : new AxisNodes(runtime, node, Axis.CHILD, AxisNodes.PIPELINE)) { throw new IllegalArgumentException("Unexpected in document: " + snode.getNodeName()); } diff --git a/src/main/java/com/xmlcalabash/util/DefaultXMLCalabashConfigurer.java b/src/main/java/com/xmlcalabash/util/DefaultXMLCalabashConfigurer.java index 410117ef..1e7bdde3 100644 --- a/src/main/java/com/xmlcalabash/util/DefaultXMLCalabashConfigurer.java +++ b/src/main/java/com/xmlcalabash/util/DefaultXMLCalabashConfigurer.java @@ -46,7 +46,7 @@ public XdmNode loadDocument(Load load) { } public ReadablePipe makeReadableData(XProcRuntime runtime, DataBinding binding) { - return new ReadableData(runtime, binding.getWrapper(), binding.getHref(), binding.getContentType()); + return new ReadableData(runtime, binding.getWrapper(), binding.getHref(), binding.getContentType(), binding.getForcedContentType()); } public ReadablePipe makeReadableDocument(XProcRuntime runtime, DocumentBinding binding) { diff --git a/src/main/java/com/xmlcalabash/util/UserArgs.java b/src/main/java/com/xmlcalabash/util/UserArgs.java index 3a0884bb..f5ddaea8 100644 --- a/src/main/java/com/xmlcalabash/util/UserArgs.java +++ b/src/main/java/com/xmlcalabash/util/UserArgs.java @@ -29,6 +29,7 @@ import org.xml.sax.InputSource; import static com.xmlcalabash.core.XProcConstants.NS_XPROC; +import static com.xmlcalabash.core.XProcConstants.cx_forced_content_type; import static com.xmlcalabash.core.XProcConstants.p_data; import static com.xmlcalabash.core.XProcConstants.p_declare_step; import static com.xmlcalabash.core.XProcConstants.p_document; @@ -651,14 +652,14 @@ public XdmNode getImplicitPipeline(XProcRuntime runtime) throws IOException { InputStream libraryInputStream = library.getInputStream(); FileOutputStream fileOutputStream = null; try { - File tempLibrary = createTempFile("calabashLibrary", null); - tempLibrary.deleteOnExit(); + File tempLibrary = createTempFile("calabashLibrary", null); + tempLibrary.deleteOnExit(); fileOutputStream = new FileOutputStream(tempLibrary); - fileOutputStream.getChannel().transferFrom(newChannel(libraryInputStream), 0, MAX_VALUE); + fileOutputStream.getChannel().transferFrom(newChannel(libraryInputStream), 0, MAX_VALUE); libraries.set(0, new Input(tempLibrary.toURI().toASCIIString())); } finally { Closer.close(fileOutputStream); - libraryInputStream.close(); + libraryInputStream.close(); } } @@ -718,15 +719,15 @@ public XdmNode getImplicitPipeline(XProcRuntime runtime) throws IOException { InputStream libraryInputStream = library.getInputStream(); FileOutputStream fileOutputStream = null; try { - File tempLibrary = createTempFile("calabashLibrary", null); - tempLibrary.deleteOnExit(); + File tempLibrary = createTempFile("calabashLibrary", null); + tempLibrary.deleteOnExit(); fileOutputStream = new FileOutputStream(tempLibrary); - fileOutputStream.getChannel().transferFrom(newChannel(libraryInputStream), 0, MAX_VALUE); + fileOutputStream.getChannel().transferFrom(newChannel(libraryInputStream), 0, MAX_VALUE); - tree.addStartElement(p_import); - tree.addAttribute(new QName("href"), tempLibrary.toURI().toASCIIString()); - tree.startContent(); - tree.addEndElement(); + tree.addStartElement(p_import); + tree.addAttribute(new QName("href"), tempLibrary.toURI().toASCIIString()); + tree.startContent(); + tree.addEndElement(); } finally { Closer.close(fileOutputStream); libraryInputStream.close(); @@ -769,8 +770,8 @@ public XdmNode getImplicitPipeline(XProcRuntime runtime) throws IOException { } else { tree.addStartElement(qname); tree.addAttribute(new QName("href"), uri); - if (input.getType() == DATA) { - tree.addAttribute(new QName("content-type"), input.getContentType()); + if ((input.getType() == DATA) && (input.getContentType() != null)) { + tree.addAttribute(cx_forced_content_type, input.getContentType()); } tree.startContent(); tree.addEndElement(); @@ -782,30 +783,30 @@ public XdmNode getImplicitPipeline(XProcRuntime runtime) throws IOException { if (System.in.equals(inputStream)) { tree.addStartElement(qname); tree.addAttribute(new QName("href"), "-"); - if (input.getType() == DATA) { - tree.addAttribute(new QName("content-type"), input.getContentType()); + if ((input.getType() == DATA) && (input.getContentType() != null)) { + tree.addAttribute(cx_forced_content_type, input.getContentType()); } tree.startContent(); tree.addEndElement(); } else { FileOutputStream fileOutputStream = null; try { - File tempInput = createTempFile("calabashInput", null); - tempInput.deleteOnExit(); + File tempInput = createTempFile("calabashInput", null); + tempInput.deleteOnExit(); fileOutputStream = new FileOutputStream(tempInput); - fileOutputStream.getChannel().transferFrom(newChannel(inputStream), 0, MAX_VALUE); - - tree.addStartElement(qname); - tree.addAttribute(new QName("href"), tempInput.toURI().toASCIIString()); - if (input.getType() == DATA) { - tree.addAttribute(new QName("content-type"), input.getContentType()); - } - tree.startContent(); - tree.addEndElement(); + fileOutputStream.getChannel().transferFrom(newChannel(inputStream), 0, MAX_VALUE); + + tree.addStartElement(qname); + tree.addAttribute(new QName("href"), tempInput.toURI().toASCIIString()); + if ((input.getType() == DATA) && (input.getContentType() != null)) { + tree.addAttribute(cx_forced_content_type, input.getContentType()); + } + tree.startContent(); + tree.addEndElement(); } finally { Closer.close(fileOutputStream); inputStream.close(); - } + } } break;