/* * Copyright (c) 2014-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.stetho.server; import javax.annotation.concurrent.ThreadSafe; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @ThreadSafe public class LeakyBufferedInputStream extends BufferedInputStream { private boolean mLeaked; private boolean mMarked; public LeakyBufferedInputStream(InputStream in, int bufSize) { super(in, bufSize); } @Override public synchronized void mark(int readlimit) { throwIfLeaked(); mMarked = true; super.mark(readlimit); } @Override public synchronized void reset() throws IOException { throwIfLeaked(); mMarked = false; super.reset(); } @Override public boolean markSupported() { return true; } public synchronized InputStream leakBufferAndStream() { throwIfLeaked(); throwIfMarked(); mLeaked = true; return new CompositeInputStream( new InputStream[] { new ByteArrayInputStream(clearBufferLocked()), in }); } private byte[] clearBufferLocked() { byte[] leaked = new byte[count - pos]; System.arraycopy(buf, pos, leaked, 0, leaked.length); pos = 0; count = 0; return leaked; } private void throwIfLeaked() { if (mLeaked) { throw new IllegalStateException(); } } private void throwIfMarked() { if (mMarked) { throw new IllegalStateException(); } } }