You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by bu...@apache.org on 2003/03/03 21:51:27 UTC
DO NOT REPLY [Bug 17620] New: -
SourceDataSource loses some text/xml attachment data
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: axis-dev@ws.apache.org
ReportedBy: gary.gordon@softwareagusa.com
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