DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT <http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17620>. ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND INSERTED IN THE BUG DATABASE.
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17620 SourceDataSource loses some text/xml attachment data Summary: SourceDataSource loses some text/xml attachment data Product: Axis Version: 1.1RC1 Platform: PC OS/Version: Windows NT/2K Status: NEW Severity: Normal Priority: Other Component: Serialization/Deserialization AssignedTo: [EMAIL PROTECTED] ReportedBy: [EMAIL PROTECTED] There are actually two observed problems. First, org.apache.axis.attachments.SourceDataSource doesn't correctly get the input data from a StreamSource object if either the StreamSource was not built with the constructor taking an InputStream or has not explicity had its input stream set via setInputStream(). SourceDataSource is getting the data via StreamSource.getInputStream(), which according to the Xalan docs, only returns a non-null value if the object has been initialized via an input stream as explained above. So if you initialize your StreamSource with, say, a java.io.File object or System ID string, 0 bytes of data are retrieved in SourceDataSource. Admittedly, the Xalan docs say the InputStream is the preferred method of intialization, becuase otherwise the character set encoding can be lost when the output is produced, but getting the data with the default UTF-8 encoding is probably better than totally failing to get the data. The other problem is that the way SourceDataSource uses the input stream, it assumes an atomic, non-blocking read, which is not guaranteed for a socket or URL stream. This is because available() only yields what is available without blocking, and for sockets, a single read may not consume all the input. I came up with a fix that addresses the first issue, modulo the concern about encodings, and can improve the partial read issue somewhat, but I am not sure it makes sense to suddenly add blocking read semantics. Here is the existing logic: InputStream is = data.getInputStream(); if (is != null && is.available() > 0) { byte[] bytes = new byte[is.available()]; is.read(bytes); os.write(bytes); } A proposed solution which fixes the atomic read problem, but not non-blocking, and creates UTF-8 encoded data when the InputStream is not available is: import javax.xml.transform.*; ... InputStream is = data.getInputStream(); if (is != null) { // If reading from a socket or URL, we could get a partial read. byte[] bytes = null; int avail; while ((avail = is.available()) > 0) { if (bytes == null || avail > bytes.length) bytes = new byte[avail]; is.read(bytes, 0, avail); os.write(bytes, 0, avail); } } else { // Create a transformer with no stylesheet (no transformation). StreamResult res = new StreamResult(os); TransformerFactory tf = TransformerFactory.newInstance(); Transformer serializer = tf.newTransformer(); serializer.transform(data, res); } Here is a test program showing how the available bytes are 0 when the StreamSource is built from a URL string. import javax.xml.transform.stream.StreamSource; import org.apache.axis.attachments.SourceDataSource; public class stst { public static void main(String[] args) throws Exception { // Case 1: breaks because calling getInputStream() // from StreamSource returned null. StreamSource ssrc = new StreamSource "http://www.xmethods.net/sd/2001/BNQuoteService.wsdl"); SourceDataSource sds = new SourceDataSource("foo", "text/xml", ssrc); System.out.println("case 1 available bytes: " + sds.getInputStream().available()); // Case 2: works ONLY because StreamSource was invoked with InputStream // constructor. May still fail if socket read isn't atomic. java.net.URL url = new java.net.URL( "http://www.xmethods.net/sd/2001/BNQuoteService.wsdl"); ssrc = new StreamSource(url.openStream(), "http://foo.com"); sds = new SourceDataSource("foo", "text/xml", ssrc); System.out.println("case 2 available bytes: " + sds.getInputStream().available()); } } My java version is: java full version "1.4.1-b21" Gary
