aboutsummaryrefslogtreecommitdiff
path: root/WordPress/src/main/java/org/xmlrpc/android/LoggedInputStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'WordPress/src/main/java/org/xmlrpc/android/LoggedInputStream.java')
-rw-r--r--WordPress/src/main/java/org/xmlrpc/android/LoggedInputStream.java111
1 files changed, 111 insertions, 0 deletions
diff --git a/WordPress/src/main/java/org/xmlrpc/android/LoggedInputStream.java b/WordPress/src/main/java/org/xmlrpc/android/LoggedInputStream.java
new file mode 100644
index 000000000..ad16c40a0
--- /dev/null
+++ b/WordPress/src/main/java/org/xmlrpc/android/LoggedInputStream.java
@@ -0,0 +1,111 @@
+package org.xmlrpc.android;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * A LoggedInputStream adds logging functionality to another input stream.
+ * <p>Note that calls on a LoggedInputStream are passed "as-is" to the underlying stream.</p>
+ *
+ *
+ * <p>We're using a LoggedInputStream in {@code XMLRPClient.java} to log the XML-RPC response document in case of parser errors.<br />
+ *
+ * There are plenty of other ways to log the response, but a {@code XmlPullParser} wants an InputStream as input parameter, and
+ * a LoggedInputStream seems the most reliable solution, with the smallest memory footprint.<br />
+ * Below are other examples of logging we tried:</p>
+ * <ul>
+ * <li>Read the first 1000 characters from the original input stream, then create a new SequenceInputStream with both the characters just read (a new ByteArrayInputStream),
+ * and the original input stream.</li>
+ * <li>Read the whole content in a String and log it, then create an StringInputStream over the string, and pass the new stream to the parser.</li>
+ * </ul>
+ */
+
+public final class LoggedInputStream extends InputStream {
+ private final InputStream inputStream;
+
+ private final static int MAX_LOG_SIZE = 1000;
+ private final byte[] loggedString = new byte[MAX_LOG_SIZE];
+ private int loggedStringSize = 0;
+
+ public LoggedInputStream(InputStream input) {
+ this.inputStream = input;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return inputStream.available();
+ }
+
+ @Override
+ public void close() throws IOException {
+ inputStream.close();
+ }
+
+ @Override
+ public void mark(int readlimit) {
+ inputStream.mark(readlimit);
+ }
+
+ @Override
+ public boolean markSupported() {
+ return inputStream.markSupported();
+ }
+
+ @Override
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ int bytesRead = inputStream.read(buffer, byteOffset, byteCount);
+ if (bytesRead != -1) {
+ log(buffer, byteOffset, bytesRead);
+ }
+ return bytesRead;
+ }
+
+ @Override
+ public int read(byte[] buffer) throws IOException {
+ return this.read(buffer, 0, buffer.length);
+ }
+
+ @Override
+ public int read() throws IOException {
+ int characterRead = inputStream.read();
+ if (characterRead != -1) {
+ log(characterRead);
+ }
+ return characterRead;
+ }
+
+ @Override
+ public synchronized void reset() throws IOException {
+ inputStream.reset();
+ }
+
+ @Override
+ public long skip(long byteCount) throws IOException {
+ return inputStream.skip(byteCount);
+ }
+
+ private void log(byte[] inputArray, int byteOffset, int byteCount) {
+ int availableSpace = MAX_LOG_SIZE - loggedStringSize;
+ if (availableSpace <= 0) {
+ return;
+ }
+ int bytesLength = Math.min(availableSpace, byteCount);
+ int startingPosition = MAX_LOG_SIZE - availableSpace;
+ System.arraycopy(inputArray, byteOffset, loggedString, startingPosition, bytesLength);
+ loggedStringSize += bytesLength;
+ }
+
+ private void log(int inputChar) {
+ byte[] logThis = {(byte) inputChar};
+ log(logThis, 0, 1);
+ }
+
+ public String getResponseDocument() {
+ if (loggedStringSize == 0) {
+ return "";
+ } else {
+ return new String(loggedString, 0, loggedStringSize);
+ }
+ }
+}