Fixes issue 2060. The readURL* and readFile* methods assumed that InputStream.read(byte[]) would always read the requested number of bytes before returning.
Patch by: mmendez
Review by: scottb
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1795 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/util/Util.java b/dev/core/src/com/google/gwt/dev/util/Util.java
index 123fecd..b252809 100644
--- a/dev/core/src/com/google/gwt/dev/util/Util.java
+++ b/dev/core/src/com/google/gwt/dev/util/Util.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -558,9 +558,7 @@
try {
fileInputStream = new FileInputStream(file);
int length = (int) file.length();
- byte[] data = new byte[length];
- fileInputStream.read(data);
- return data;
+ return readBytesFromInputStream(fileInputStream, length);
} catch (IOException e) {
return null;
} finally {
@@ -569,48 +567,20 @@
}
public static char[] readFileAsChars(File file) {
- if (!file.exists()) {
- return null;
+ String string = readFileAsString(file);
+ if (string != null) {
+ return string.toCharArray();
}
- Reader fileReader = null;
- try {
- fileReader = new InputStreamReader(new FileInputStream(file),
- DEFAULT_ENCODING);
- int length = (int) file.length();
- if (length < 0) {
- return null;
- }
- char[] fileContents = new char[length];
- int charsRead = fileReader.read(fileContents);
- if (charsRead < fileContents.length) {
- /*
- * Calling functions expect returned char[] to be fully populated. This
- * happens because some UTF-8 chars take more than one byte to
- * represent.
- */
- char[] trimmed = new char[charsRead];
- System.arraycopy(fileContents, 0, trimmed, 0, charsRead);
- fileContents = trimmed;
- }
- return fileContents;
- } catch (IOException e) {
- return null;
- } finally {
- Utility.close(fileReader);
- }
+ return null;
}
public static String readFileAsString(File file) {
- try {
- URL toURL = file.toURI().toURL();
- char[] buf = readURLAsChars(toURL);
- if (buf == null) {
- return null;
- }
- return String.valueOf(buf);
- } catch (MalformedURLException e) {
- return null;
+ byte[] bytes = readFileAsBytes(file);
+ if (bytes != null) {
+ return toString(bytes, DEFAULT_ENCODING);
}
+
+ return null;
}
/**
@@ -649,9 +619,8 @@
if (contentLength < 0) {
return null;
}
- byte[] data = new byte[contentLength];
- input.read(data);
- return data;
+
+ return readBytesFromInputStream(input, contentLength);
} catch (IOException e) {
return null;
} finally {
@@ -664,34 +633,12 @@
*/
public static char[] readURLAsChars(URL url) {
// ENH: add a weak cache that has an additional check against the file date
- InputStreamReader reader = null;
- try {
- URLConnection connection = url.openConnection();
- connection.setUseCaches(false);
- reader = new InputStreamReader(connection.getInputStream(),
- DEFAULT_ENCODING);
- int contentLength = connection.getContentLength();
- if (contentLength < 0) {
- return null;
- }
- char[] fileContents = new char[contentLength];
- int charsRead = reader.read(fileContents);
- if (charsRead < fileContents.length) {
- /*
- * Calling functions expect returned char[] to be fully populated. This
- * happens because some UTF-8 chars take more than one byte to
- * represent.
- */
- char[] trimmed = new char[charsRead];
- System.arraycopy(fileContents, 0, trimmed, 0, charsRead);
- fileContents = trimmed;
- }
- return fileContents;
- } catch (IOException e) {
- return null;
- } finally {
- Utility.close(reader);
+ byte[] bytes = readURLAsBytes(url);
+ if (bytes != null) {
+ return toString(bytes, DEFAULT_ENCODING).toCharArray();
}
+
+ return null;
}
/**
@@ -1000,6 +947,57 @@
return true;
}
+ /**
+ * Reads the specified number of bytes from the {@link InputStream}.
+ *
+ * @param byteLength number of bytes to read
+ * @return byte array containing the bytes read or <code>null</code> if
+ * there is an {@link IOException} or if the requested number of bytes
+ * can not be read from the {@link InputStream}
+ */
+ private static byte[] readBytesFromInputStream(InputStream input,
+ int byteLength) {
+
+ try {
+ byte[] bytes = new byte[byteLength];
+ int byteOffset = 0;
+ while (byteOffset < byteLength) {
+ int bytesReadCount = input.read(bytes, byteOffset, byteLength
+ - byteOffset);
+ if (bytesReadCount == -1) {
+ return null;
+ }
+
+ byteOffset += bytesReadCount;
+ }
+
+ return bytes;
+ } catch (IOException e) {
+ // Ignored.
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a string from the bytes using the specified character set name.
+ *
+ * @param bytes bytes to convert
+ * @param charsetName the name of the character set to use
+ *
+ * @return String for the given bytes and character set or <code>null</code>
+ * if the character set is not supported
+ */
+ private static String toString(byte[] bytes, String charsetName) {
+ try {
+ return new String(bytes, charsetName);
+ } catch (UnsupportedEncodingException e) {
+ // Ignored.
+ }
+
+ return null;
+ }
+
private static void writeAttribute(PrintWriter w, Attr attr, int depth)
throws IOException {
w.write(attr.getName());