message: Add support for mark() to JavaUrl.DelayedInputStream.
diff: */
  package com.netflix.msl.io;
  +import java.io.BufferedInputStream;
  import java.io.FilterInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  @@ -28,10 +29,16 @@ import java.net.URLConnection;
  */
  public class JavaUrl implements Url {
  /**
  - * A delayed input stream does not open the real input stream until one of its
  - * its methods is called. This class may be useful in situations where the
  - * connection will not permit use of its output stream after the input stream
  - * is requested.
  + * <p>A delayed input stream does not open the real input stream until one
  + * of its methods is called. This class may be useful in situations where
  + * the connection will not permit use of its output stream after the input
  + * stream is requested.</p>
  + *
  + * <p>The input stream itself will be a {@link BufferedInputStream} which
  + * will read ahead for improved performance, and support the
  + * {@link #mark(int)}, {@link #reset()}, and {@link #skip(long)}
  + * methods. This is necessary to facilitate stream reuse across multiple
  + * MSL messages.</p>
  */
  public class DelayedInputStream extends FilterInputStream {
  /**
  @@ -46,66 +53,93 @@ public class JavaUrl implements Url {
  this.conn = conn;
  }
  + /**
  + * <p>If the connection input stream has not already been opened, open
  + * it and wrap it inside a {@link BufferedInputStream}, then assign it
  + * to the parent member variable {@link FilterInputStream#in}.</p>
  + *
  + * <p>If mark was called and delayed, also mark the input stream.</p>
  + *
  + * @throws IOException any exception thrown by
  + * {@link URLConnection#getInputStream()}.
  + */
  + private void openOnce() throws IOException {
  + // Return immediately if already open.
  + if (in != null) return;
  +
  + // Open and wrap the input stream.
  + final InputStream source = conn.getInputStream();
  + in = new BufferedInputStream(source);
  +
  + // If mark had been called earlier, mark the input stream now.
  + if (readlimit != -1)
  + in.mark(readlimit);
  + }
  +
  @Override
  public int available() throws IOException {
  - if (in == null)
  - in = conn.getInputStream();
  + openOnce();
  return super.available();
  }
  @Override
  public void close() throws IOException {
  - if (in == null)
  - in = conn.getInputStream();
  + openOnce();
  super.close();
  }
  @Override
  public synchronized void mark(final int readlimit) {
  + // Mark the BufferedInputStream if it is already open.
  + if (in != null)
  + super.mark(readlimit);
  +
  + // Otherwise remember that mark was called so it can be called on
  + // the BufferedInputStream once opened.
  + else
  + this.readlimit = readlimit;
  }
  @Override
  public boolean markSupported() {
  - return false;
  + // BufferedInputStream supports mark.
  + return true;
  }
  @Override
  public int read() throws IOException {
  - if (in == null)
  - in = conn.getInputStream();
  - return in.read();
  + openOnce();
  + return super.read();
  }
  @Override
  public int read(final byte[] b, final int off, final int len) throws IOException {
  - if (in == null)
  - in = conn.getInputStream();
  + openOnce();
  return super.read(b, off, len);
  }
  @Override
  public int read(final byte[] b) throws IOException {
  - if (in == null)
  - in = conn.getInputStream();
  + openOnce();
  return super.read(b);
  }
  @Override
  public synchronized void reset() throws IOException {
  - if (in == null)
  - in = conn.getInputStream();
  + openOnce();
  super.reset();
  }
  @Override
  public long skip(final long n) throws IOException {
  - if (in == null)
  - in = conn.getInputStream();
  + openOnce();
  return super.skip(n);
  }
  /** Connection providing the input stream. */
  private final URLConnection conn;
  + /** Mark read limit. -1 if no mark is set. */
  + private int readlimit = -1;
  }
  /**
  