Hi all.
I just joined the list and didn't realize bug reports get sent here
directly. So I figured I'd send my complete email directly to the
list as well as archiving it in bugzilla.
This regards some new bug fixes I coded for the Slide client API.
The bug fixes apply to:
org.apache.webdav.lib.WebdavResource.getMethod(String path, File
file), and
org.apache.webdav.lib.WebdavResource.putMethod(String path, File file)
I had previously submitted a patch for putMethod(String, File) and
had it accepted (see Slide 2.1 bug 40835, http://issues.apache.org/
bugzilla/show_bug.cgi?id=40835 )--I was told it would appear in the
next release of the API. However I see there is still a problem
with this method even with the fix--and it turns out that the
problem also occurs in getMethod(String, File).
/////////// ** PUTMETHOD BUG **
Below is the orginal code for putMethod(String, File) :
///////////////////////
1: public boolean putMethod(String path, File file)
2: throws HttpException, IOException {
3:
4: setClient();
5: PutMethod method = new PutMethod(URIUtil.encodePathQuery
(path));
6: generateIfHeader(method);
7: if (getGetContentType() != null && !getGetContentType
().equals(""))
8: method.setRequestHeader("Content-Type",
getGetContentType());
9: long fileLength = file.length();
10: method.setRequestContentLength(fileLength <=
Integer.MAX_VALUE
12: ? (int) fileLength
13: :
PutMethod.CONTENT_LENGTH_CHUNKED);
14: method.setRequestBody(new FileInputStream(file));
15: generateTransactionHeader(method);
16: int statusCode = client.executeMethod(method);
17:
18: setStatusCode(statusCode);
19: return (statusCode >= 200 && statusCode < 300) ? true :
false;
20: }
///////////////////////
As you can see, the FileInputStream created in line 14 is never
closed. While this error won't manifest itself in a noticeable way
on *nix systems, on Windows a file opened for writing is locked and
hence applications on the client side will not be able to edit it
from therein (one would get a "File is in use" message).
The original solution was to replace line 14 with following code:
14 : FileInputStream fis = new FileInputStream(file);
14.1: method.setRequestBody(fis);
and then insert the following code after line 18:
18.1: fis.close();
However, the problem that still remains is this: what happens if an
exception is thrown between lines 15 and 18 (inclusive)?
Specifically, in line 16, the executeMethod of HttpClient may throw
an IOException or HttpException. If this occurs then the
FileInputStream will still not be closed. The solution to this is
below:
/////////// ** PUTMETHOD FIX **
///////////////////////
1: public boolean putMethod(String path, File file)
2: throws HttpException, IOException {
3:
4: FileInputStream fis = null;
5: try {
6: setClient();
7: PutMethod method = new PutMethod
(URIUtil.encodePathQuery(path));
8: generateIfHeader(method);
9: if (getGetContentType() != null && !getGetContentType
().equals(""))
10: method.setRequestHeader("Content-Type",
getGetContentType());
11: long fileLength = file.length();
12: method.setRequestContentLength(fileLength <=
Integer.MAX_VALUE
13: ? (int) fileLength
14: :
PutMethod.CONTENT_LENGTH_CHUNKED);
15: fis = new FileInputStream(file);
16: method.setRequestBody(fis);
17: generateTransactionHeader(method);
18: int statusCode = client.executeMethod(method);
19:
20: setStatusCode(statusCode);
21: return (statusCode >= 200 && statusCode < 300) ?
true : false;
22:
23: } finally {
24: if(fis != null)
25: fis.close();
26: }
27: }
///////////////////////
By enclosing the method's code in a try block, we can ensure fis is
always closed, even if an exception occurs after it is instantiated.
-------------------------
/////////// ** GETMETHOD BUG **
The identical problem exists in putMethod(String, File) of the same
class. The original code is below:
///////////////////////
1: public boolean getMethod(String path, File file)
2: throws HttpException, IOException {
3:
4: setClient();
5: GetMethod method = new GetMethod(URIUtil.encodePathQuery
(path));
6:
7: generateTransactionHeader(method);
8: int statusCode = client.executeMethod(method);
9:
10: setStatusCode(statusCode);
11:
12: // get the file only if status is any kind of OK
13: if (statusCode >= 200 && statusCode < 300) {
14:
15: // Do a simple little loop to read the response back
into the passed
16: // file parameter.
17: InputStream inStream = method.getResponseBodyAsStream
();
18:
19: FileOutputStream fos = new FileOutputStream(file);
20: byte buffer[] = new byte[65535];
21: int bytesRead;
22: while ((bytesRead = inStream.read(buffer)) >= 0) {
23: fos.write(buffer, 0, bytesRead);
24: }
25: inStream.close();
26: fos.close();
27:
28: return true;
29:
30: } else {
31: return false;
32: }
33: }
If an exception is thrown between lines 20 and 24 (inclusive) the
input and output streams inStream and fos will not be closed.
/////////// ** GETMETHOD FIX **
The solution is the same as it was for putMethod(String, File) :
///////////////////////
1: public boolean getMethod(String path, File file)
2: throws HttpException, IOException {
3:
4: setClient();
5: GetMethod method = new GetMethod(URIUtil.encodePathQuery
(path));
6:
7: generateTransactionHeader(method);
8: int statusCode = client.executeMethod(method);
9:
10: setStatusCode(statusCode);
11:
12: // get the file only if status is any kind of OK
13: if (statusCode >= 200 && statusCode < 300) {
14:
14.1: FileOutputStream fos = null;
14.2: InputStream inStream = null;
14.3: try {
15: // Do a simple little loop to read the response
back into the passed
16: // file parameter.
17*: inStream = method.getResponseBodyAsStream();
18:
19*: fos = new FileOutputStream(file);
20: byte buffer[] = new byte[65535];
21: int bytesRead;
22: while ((bytesRead = inStream.read(buffer)) >= 0) {
23: fos.write(buffer, 0, bytesRead);
24: }
-25-
-26-
27:
28: return true;
28.1:
28.2: } finally {
28.3: if(fos != null)
28.4: fos.close();
28.5: if(inStream != null)
28.6: inStream.close();
28.7: }
29:
30: } else {
31: return false;
32: }
33: }
///////////////////////
Lines 14.1-14.3 and 28.1-28.7 are added code, lines 25 and 26 have
been deleted from the original source, and lines 17 and 19 have
been updated (we now declare inStream and fos outside the try block
in lines 14.1-14.3).
Cheers!
Michael N. Christoff
Site Administrator
Continuing Professional Education Online
Centre for Addiction and Mental Health
33 Russell Street
Toronto, Ontario M5S 2S1
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]