Example usage for java.io InputStream skip

List of usage examples for java.io InputStream skip

Introduction

In this page you can find the example usage for java.io InputStream skip.

Prototype

public long skip(long n) throws IOException 

Source Link

Document

Skips over and discards n bytes of data from this input stream.

Usage

From source file:org.opencms.webdav.CmsWebdavServlet.java

/**
 * Copy the contents of the specified input stream to the specified
 * output stream, and ensure that both streams are closed before returning
 * (even in the face of an exception).<p>
 *
 * @param istream the input stream to read from
 * @param ostream the output stream to write to
 * @param start the start of the range which will be copied
 * @param end the end of the range which will be copied
 * //from ww w. ja  va2s.  c om
 * @return the exception which occurred during processing
 */
protected IOException copyRange(InputStream istream, ServletOutputStream ostream, long start, long end) {

    if (LOG.isDebugEnabled()) {
        LOG.debug(Messages.get().getBundle().key(Messages.LOG_SERVE_BYTES_2, new Long(start), new Long(end)));
    }

    try {
        istream.skip(start);
    } catch (IOException e) {
        return e;
    }

    IOException exception = null;
    long bytesToRead = (end - start) + 1;

    byte[] buffer = new byte[m_input];
    int len = buffer.length;
    while ((bytesToRead > 0) && (len >= buffer.length)) {
        try {
            len = istream.read(buffer);
            if (bytesToRead >= len) {
                ostream.write(buffer, 0, len);
                bytesToRead -= len;
            } else {
                ostream.write(buffer, 0, (int) bytesToRead);
                bytesToRead = 0;
            }
        } catch (IOException e) {
            exception = e;
            len = -1;
        }

        if (len < buffer.length) {
            break;
        }
    }

    return exception;
}

From source file:de.innovationgate.wgpublisher.WGPDispatcher.java

private void writeRangesData(DataSource data, List<AcceptRange> ranges, HttpServletResponse response,
        String dbHint, long size) throws IOException, HttpErrorException, UnsupportedEncodingException {

    ServletOutputStream out = response.getOutputStream();
    for (AcceptRange range : ranges) {
        InputStream in = data.getInputStream();
        if (in == null) {
            throw new HttpErrorException(404, "File not found: " + data.getName(), dbHint);
        }//  ww w  . j a  va2 s .  co  m

        if (ranges.size() != 1) {
            out.println();
            out.println("--" + BYTERANGE_BOUNDARY);
            out.println("Content-Type: " + data.getContentType());
            out.println("Content-Range: bytes " + range.from + "-" + range.to + "/" + size);
            out.println();
        }

        if (range.from > 0) {
            in.skip(range.from);
        }

        try {
            WGUtils.inToOutLimited(in, out, (new Long(range.to - range.from + 1)).intValue(), 2048);
            out.flush();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }
    }

    if (ranges.size() != 1) {
        out.println();
        out.print("--" + BYTERANGE_BOUNDARY + "--");
        out.flush();
    }

}

From source file:org.sakaiproject.sdata.tool.JCRHandler.java

@Override
public void doGet(final HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    OutputStream out = null;//w  ww.j a  v  a  2  s. c  o  m
    InputStream in = null;
    try {
        snoopRequest(request);

        ResourceDefinition rp = resourceDefinitionFactory.getSpec(request);
        SDataFunction m = resourceFunctionFactory.get(rp.getFunctionDefinition());

        if (describe(request, response, m)) {
            return;
        }

        Node n = jcrNodeFactory.getNode(rp.getRepositoryPath());
        if (n == null) {
            response.reset();
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        String primaryNodeType = n.getPrimaryNodeType().getName();
        String version = rp.getVersion();
        if (version != null) {
            try {
                n = n.getVersionHistory().getVersion(version);
            } catch (VersionException e) {
                throw new SDataAccessException(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
            }
            n = n.getNode(JCRConstants.JCR_FROZENNODE);
            if (n.hasProperty(JCRConstants.JCR_FROZENPRIMARYTYPE)) {
                primaryNodeType = n.getProperty(JCRConstants.JCR_FROZENPRIMARYTYPE).getString();
            }
        }

        if (m != null) {
            m.call(this, request, response, n, rp);
        } else {

            if (JCRConstants.NT_FILE.equals(primaryNodeType)) {

                Node resource = n.getNode(JCRConstants.JCR_CONTENT);
                Property lastModified = resource.getProperty(JCRConstants.JCR_LASTMODIFIED);
                Property mimeType = resource.getProperty(JCRConstants.JCR_MIMETYPE);
                Property content = resource.getProperty(JCRConstants.JCR_DATA);

                response.setContentType(mimeType.getString());
                if (mimeType.getString().startsWith("text")) {
                    if (resource.hasProperty(JCRConstants.JCR_ENCODING)) {
                        Property encoding = resource.getProperty(JCRConstants.JCR_ENCODING);
                        response.setCharacterEncoding(encoding.getString());
                    }
                }
                response.setDateHeader(LAST_MODIFIED, lastModified.getDate().getTimeInMillis());
                setGetCacheControl(response, rp.isPrivate());

                String currentEtag = String.valueOf(lastModified.getDate().getTimeInMillis());
                response.setHeader("ETag", currentEtag);

                long lastModifiedTime = lastModified.getDate().getTimeInMillis();

                if (!checkPreconditions(request, response, lastModifiedTime, currentEtag)) {
                    return;
                }
                long totallength = content.getLength();
                long[] ranges = new long[2];
                ranges[0] = 0;
                ranges[1] = totallength;
                if (!checkRanges(request, response, lastModifiedTime, currentEtag, ranges)) {
                    return;
                }

                long length = ranges[1] - ranges[0];

                if (totallength != length) {
                    response.setHeader("Accept-Ranges", "bytes");
                    response.setDateHeader("Last-Modified", lastModifiedTime);
                    response.setHeader("Content-Range",
                            "bytes " + ranges[0] + "-" + (ranges[1] - 1) + "/" + totallength);
                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

                    LOG.info("Partial Content Sent " + HttpServletResponse.SC_PARTIAL_CONTENT);
                } else {
                    response.setStatus(HttpServletResponse.SC_OK);
                }

                response.setContentLength((int) length);

                out = response.getOutputStream();

                in = content.getStream();
                long loc = in.skip(ranges[0]);
                if (loc != ranges[0]) {
                    throw new RestServiceFaultException(HttpServletResponse.SC_BAD_REQUEST,
                            "Range specified is invalid asked for " + ranges[0] + " got " + loc);
                }
                byte[] b = new byte[10240];
                int nbytes = 0;
                while ((nbytes = in.read(b)) > 0 && length > 0) {
                    if (nbytes < length) {
                        out.write(b, 0, nbytes);
                        length = length - nbytes;
                    } else {
                        out.write(b, 0, (int) length);
                        length = 0;
                    }
                }
            } else {
                boolean handled = handleSmartNode(request, response, rp, n);
                if (!handled) {
                    doDefaultGet(request, response, rp, n);
                }
            }
        }
    } catch (UnauthorizedException ape) {
        // catch any Unauthorized exceptions and send a 401
        response.reset();
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ape.getMessage());
    } catch (PermissionDeniedException pde) {
        // catch any permission denied exceptions, and send a 403
        response.reset();
        response.sendError(HttpServletResponse.SC_FORBIDDEN, pde.getMessage());

    } catch (SDataException e) {
        LOG.error("Failed  To service Request " + e.getMessage());
        e.printStackTrace();
        sendError(request, response, e);
    } catch (Exception e) {
        LOG.error("Failed  TO service Request ", e);
        sendError(request, response, e);
        snoopRequest(request);
    } finally {

        try {
            out.close();
        } catch (Exception ex) {
        }
        try {
            in.close();
        } catch (Exception ex) {
        }
    }
}

From source file:org.regenstrief.util.Util.java

/**
 * Retrieves the number of bytes remaining in the InputStream and closes it
 * /*from   w  w  w. j  a v a2s.  co m*/
 * @param is the InputStream
 * @return the number of bytes
 **/
public final static long size(final InputStream is) {
    long size = 0, c;

    try {
        while (true) {
            while ((c = is.skip(BUFFER_SIZE)) > 0) { // Skip bytes
                size += c;
            }
            if (is.read() == -1) { // EOF cannot be determined by skipping, so read
                break;
            }
            size++; // Add a byte for the read
        }
        is.close();
    } catch (final IOException e) {
        throw new RuntimeException(e);
    }

    return size;
}

From source file:org.rhq.enterprise.server.content.ContentSourceManagerBean.java

@SuppressWarnings("unchecked")
private long outputPackageVersionBitsRangeHelper(int resourceId, PackageDetailsKey packageDetailsKey,
        OutputStream outputStream, long startByte, long endByte, int packageVersionId) {

    // TODO: Should we make sure the resource is subscribed/allowed to receive the the package version?
    //       Or should we not bother to perform this check?  if the caller knows the PV ID, it
    //       probably already got it through its repos

    Query query = entityManager/* w ww.j a  va 2s . co m*/
            .createNamedQuery(PackageBits.QUERY_PACKAGE_BITS_LOADED_STATUS_PACKAGE_VERSION_ID);
    query.setParameter("id", packageVersionId);
    LoadedPackageBitsComposite composite = (LoadedPackageBitsComposite) query.getSingleResult();

    boolean packageBitsAreAvailable = composite.isPackageBitsAvailable();
    if (packageBitsAreAvailable) {
        // it says the package bits are available, but if its stored on the filesystem, we should
        // make sure no one deleted the file.  If the file is deleted, let's simply download it again.
        if (!composite.isPackageBitsInDatabase()) {
            try {
                File bitsFile = getPackageBitsLocalFileAndCreateParentDir(composite.getPackageVersionId(),
                        composite.getFileName());
                if (!bitsFile.exists()) {
                    log.warn("Package version [" + packageDetailsKey + "] has had its bits file [" + bitsFile
                            + "] deleted. Will attempt to download it again.");
                    packageBitsAreAvailable = false;
                }
            } catch (Exception e) {
                throw new RuntimeException("Package version [" + packageDetailsKey
                        + "] has had its bits file deleted but cannot download it again.", e);
            }
        }
    }

    PackageVersionContentSource pvcs = null; // will be non-null only if package bits were not originally available

    if (!packageBitsAreAvailable) {
        if (resourceId == -1) {
            throw new IllegalStateException("Package bits must be inserted prior to the agent asking for them "
                    + "during a cotent-based resource creation");
        }
        // if we got here, the package bits have not been downloaded yet.  This eliminates the
        // possibility that the package version were directly uploaded by a user
        // or auto-discovered by a resource and attached to a repo. So, that leaves
        // the only possibility - the package version comes from a content source and therefore has
        // a PackageVersionContentSource mapping.  Let's find that mapping.
        Query q2 = entityManager
                .createNamedQuery(PackageVersionContentSource.QUERY_FIND_BY_PKG_VER_ID_AND_RES_ID);
        q2.setParameter("resourceId", resourceId);
        q2.setParameter("packageVersionId", packageVersionId);
        List<PackageVersionContentSource> pvcss = q2.getResultList();

        // Note that its possible more than one content source can deliver a PV - if a resource is subscribed
        // to repo(s) that contain multiple content sources that can deliver a PV, we just take
        // the first one we find.

        if (pvcss.size() == 0) {
            throw new RuntimeException("Resource [" + resourceId + "] cannot access package version ["
                    + packageDetailsKey + "] - no content source exists to deliver it");
        }

        pvcs = pvcss.get(0);

        // Make it a true EJB call so we suspend our tx and get a new tx.
        // This way, we start with a fresh tx timeout when downloading and this
        // won't affect the time we are in in this method's tx (I hope that's how it works).
        // This is because this method itself may take a long time to send the data to the output stream
        // and we don't want out tx timing out due to the time it takes downloading.
        PackageBits bits = null;
        bits = contentSourceManager.downloadPackageBits(subjectManager.getOverlord(), pvcs);

        if (bits != null) {
            // rerun the query just to make sure we really downloaded it successfully
            query.setParameter("id", pvcs.getPackageVersionContentSourcePK().getPackageVersion().getId());
            composite = (LoadedPackageBitsComposite) query.getSingleResult();

            if (!composite.isPackageBitsAvailable()) {
                throw new RuntimeException("Failed to download package bits [" + packageDetailsKey
                        + "] for resource [" + resourceId + "]");
            }
        } else {
            // package bits are not loaded and never will be loaded due to content source's download mode == NEVER
            composite = null;
        }
    }

    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet results = null;
    InputStream bitsStream = null;

    try {
        if (composite == null) {
            // this is DownloadMode.NEVER and we are really in pass-through mode, stream directly from adapter
            ContentServerPluginContainer pc = ContentManagerHelper.getPluginContainer();
            ContentProviderManager adapterMgr = pc.getAdapterManager();
            int contentSourceId = pvcs.getPackageVersionContentSourcePK().getContentSource().getId();
            bitsStream = adapterMgr.loadPackageBits(contentSourceId, pvcs.getLocation());
        } else {
            if (composite.isPackageBitsInDatabase()) {
                // this is  DownloadMode.DATABASE - put the bits in the database

                conn = dataSource.getConnection();
                ps = conn.prepareStatement("SELECT BITS FROM " + PackageBits.TABLE_NAME + " WHERE ID = ?");

                ps.setInt(1, composite.getPackageBitsId());
                results = ps.executeQuery();
                results.next();
                Blob blob = results.getBlob(1);

                long bytesRetrieved = 0L;
                if (endByte < 0L) {
                    if (startByte == 0L) {
                        bytesRetrieved = StreamUtil.copy(blob.getBinaryStream(), outputStream, false);
                    }
                } else {
                    long length = (endByte - startByte) + 1;
                    //InputStream stream = blob.getBinaryStream(startByte, length);  // JDK 6 api
                    InputStream stream = blob.getBinaryStream();
                    bytesRetrieved = StreamUtil.copy(stream, outputStream, startByte, length);
                }
                log.debug("Retrieved and sent [" + bytesRetrieved + "] bytes for [" + packageDetailsKey + "]");
                ps.close();
                conn.close();
                return bytesRetrieved;

            } else {
                // this is  DownloadMode.FILESYSTEM - put the bits on the filesystem
                File bitsFile = getPackageBitsLocalFileAndCreateParentDir(composite.getPackageVersionId(),
                        composite.getFileName());
                if (!bitsFile.exists()) {
                    throw new RuntimeException(
                            "Package bits at [" + bitsFile + "] are missing for [" + packageDetailsKey + "]");
                }

                bitsStream = new FileInputStream(bitsFile);
            }
        }

        // the magic happens here - outputStream is probably a remote stream down to the agent
        long bytesRetrieved;
        if (endByte < 0L) {
            if (startByte > 0L) {
                bitsStream.skip(startByte);
            }
            bytesRetrieved = StreamUtil.copy(bitsStream, outputStream, false);
        } else {
            BufferedInputStream bis = new BufferedInputStream(bitsStream);
            long length = (endByte - startByte) + 1;
            bytesRetrieved = StreamUtil.copy(bis, outputStream, startByte, length);
        }

        // close our stream but leave the output stream open
        try {
            bitsStream.close();
        } catch (Exception closeError) {
            log.warn("Failed to close the bits stream", closeError);
        }

        bitsStream = null;

        log.debug("Retrieved and sent [" + bytesRetrieved + "] bytes for [" + packageDetailsKey + "]");

        return bytesRetrieved;
    } catch (SQLException sql) {
        throw new RuntimeException(
                "Did not download the package bits to the DB for [" + packageDetailsKey + "]", sql);
    } catch (Exception e) {
        throw new RuntimeException("Could not stream package bits for [" + packageDetailsKey + "]", e);
    } finally {
        if (bitsStream != null) {
            try {
                bitsStream.close();
            } catch (IOException e) {
                log.warn("Failed to close bits stream for: " + packageDetailsKey);
            }
        }

        if (results != null) {
            try {
                results.close();
            } catch (SQLException e) {
                log.warn("Failed to close result set from jdbc blob query for: " + packageDetailsKey);
            }
        }

        if (ps != null) {
            try {
                ps.close();
            } catch (SQLException e) {
                log.warn("Failed to close prepared statement from jdbc blob query for: " + packageDetailsKey);
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                log.warn("Failed to close prepared statement from jdbc blob query for: " + packageDetailsKey);
            }
        }
    }
}

From source file:org.regenstrief.util.Util.java

/**
 * Skips the desired the number of bytes (or until EOF) in the InputStream
 * /*from   ww  w  .j  a  v  a  2s  . co m*/
 * @param is the InputStream
 * @param skip the number of bytes to skip
 * @return the number of bytes
 **/
public final static long skip(final InputStream is, final long skip) {
    long size = 0, c, remaining = skip;

    try {
        do {
            while ((remaining > 0) && ((c = is.skip(remaining)) > 0)) { // Skip bytes
                size += c;
                remaining = skip - size;
            }
            if ((remaining == 0) || (is.read() == -1)) { // EOF cannot be determined by skipping, so read
                break;
            }
            size++; // Add a byte for the read
            remaining = skip - size;
        } while (remaining > 0);
    } catch (final IOException e) {
        throw new RuntimeException(e);
    }

    return size;
}

From source file:org.lockss.jetty.LockssResourceHandler.java

public void sendData(HttpRequest request, HttpResponse response, String pathInContext, Resource resource,
        boolean writeHeaders) throws IOException {
    long resLength = resource.length();

    //  see if there are any range headers
    Enumeration reqRanges = request.getDotVersion() > 0 ? request.getFieldValues(HttpFields.__Range) : null;

    if (!writeHeaders || reqRanges == null || !reqRanges.hasMoreElements()) {
        // look for a gziped content.
        Resource data = resource;
        if (_minGzipLength > 0) {
            String accept = request.getField(HttpFields.__AcceptEncoding);
            if (accept != null && resLength > _minGzipLength && !pathInContext.endsWith(".gz")) {
                Resource gz = getHttpContext().getResource(pathInContext + ".gz");
                if (gz.exists() && accept.indexOf("gzip") >= 0) {
                    if (log.isDebugEnabled())
                        log.debug("gzip=" + gz);
                    response.setField(HttpFields.__ContentEncoding, "gzip");
                    data = gz;//w  ww .ja v  a 2s . c  o  m
                    resLength = data.length();
                }
            }
        }
        writeHeaders(response, resource, resLength);

        request.setHandled(true);

        // (sethm) Begin content rewrite hack.
        //
        // Content Rewriting: If the PARAM_REWRITE_GIF_PNG
        // config parameter is set, and this is GIF content, use
        // JIMI to rewrite as PNG

        InputStream in = data.getInputStream();
        OutputStream out = null;
        boolean enableRewrite = CurrentConfig.getCurrentConfig().getBoolean(ProxyManager.PARAM_REWRITE_GIF_PNG,
                ProxyManager.DEFAULT_REWRITE_GIF_PNG);
        if (!proxyMgr.isRepairRequest(request) && enableRewrite
                && "image/gif".equals(HeaderUtil.getMimeTypeFromContentType(response.getContentType()))
                && "from-cache".equals(response.getField("X-Lockss"))) {
            try {
                JimiRasterImage img = Jimi.getRasterImage(in, Jimi.SYNCHRONOUS);
                // Content length cannot be known before the data is
                // written.  Remove the Content-Length header.
                response.removeField("Content-Length");
                response.setContentType("image/png");
                out = response.getOutputStream();
                Jimi.putImage("image/png", img, out);
                out.flush();
            } catch (JimiException ex) {
                throw new IOException(ex.getMessage());
            }
        } else {
            out = response.getOutputStream();
            IO.copy(in, out, resLength);
        }

        if (in != null) {
            in.close();
        }
        if (out != null) {
            out.close();
        }

        // End hack.
        //
        // OutputStream out = response.getOutputStream();
        // data.writeTo(out,0,resLength);
        //

        return;
    }

    // Parse the satisfiable ranges
    List ranges = InclusiveByteRange.satisfiableRanges(reqRanges, resLength);
    if (log.isDebugEnabled())
        log.debug("ranges: " + reqRanges + " == " + ranges);

    //  if there are no satisfiable ranges, send 416 response
    if (ranges == null || ranges.size() == 0) {
        log.debug("no satisfiable ranges");
        writeHeaders(response, resource, resLength);
        response.setStatus(HttpResponse.__416_Requested_Range_Not_Satisfiable);
        response.setReason((String) HttpResponse.__statusMsg
                .get(TypeUtil.newInteger(HttpResponse.__416_Requested_Range_Not_Satisfiable)));

        response.setField(HttpFields.__ContentRange, InclusiveByteRange.to416HeaderRangeString(resLength));

        OutputStream out = response.getOutputStream();
        resource.writeTo(out, 0, resLength);
        request.setHandled(true);
        return;
    }

    //  if there is only a single valid range (must be satisfiable
    //  since were here now), send that range with a 216 response
    if (ranges.size() == 1) {
        InclusiveByteRange singleSatisfiableRange = (InclusiveByteRange) ranges.get(0);
        if (log.isDebugEnabled())
            log.debug("single satisfiable range: " + singleSatisfiableRange);
        long singleLength = singleSatisfiableRange.getSize(resLength);
        writeHeaders(response, resource, singleLength);
        response.setStatus(HttpResponse.__206_Partial_Content);
        response.setReason(
                (String) HttpResponse.__statusMsg.get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
        response.setField(HttpFields.__ContentRange, singleSatisfiableRange.toHeaderRangeString(resLength));
        OutputStream out = response.getOutputStream();
        resource.writeTo(out, singleSatisfiableRange.getFirst(resLength), singleLength);
        request.setHandled(true);
        return;
    }

    //  multiple non-overlapping valid ranges cause a multipart
    //  216 response which does not require an overall
    //  content-length header
    //
    ResourceCache.ResourceMetaData metaData = (ResourceCache.ResourceMetaData) resource.getAssociate();
    String encoding = metaData.getMimeType();
    MultiPartResponse multi = new MultiPartResponse(response);
    response.setStatus(HttpResponse.__206_Partial_Content);
    response.setReason(
            (String) HttpResponse.__statusMsg.get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));

    // If the request has a "Request-Range" header then we need to
    // send an old style multipart/x-byteranges Content-Type. This
    // keeps Netscape and acrobat happy. This is what Apache does.
    String ctp;
    if (request.containsField(HttpFields.__RequestRange))
        ctp = "multipart/x-byteranges; boundary=";
    else
        ctp = "multipart/byteranges; boundary=";
    response.setContentType(ctp + multi.getBoundary());

    InputStream in = (resource instanceof CachedResource) ? null : resource.getInputStream();
    OutputStream out = response.getOutputStream();
    long pos = 0;

    for (int i = 0; i < ranges.size(); i++) {
        InclusiveByteRange ibr = (InclusiveByteRange) ranges.get(i);
        String header = HttpFields.__ContentRange + ": " + ibr.toHeaderRangeString(resLength);
        if (log.isDebugEnabled())
            log.debug("multi range: " + encoding + " " + header);
        multi.startPart(encoding, new String[] { header });

        long start = ibr.getFirst(resLength);
        long size = ibr.getSize(resLength);
        if (in != null) {
            // Handle non cached resource
            if (start < pos) {
                in.close();
                in = resource.getInputStream();
                pos = 0;
            }
            while (pos < start) {
                pos += in.skip(start - pos);
            }
            IO.copy(in, out, size);
            pos += size;
        } else
            // Handle cached resource
            resource.writeTo(out, start, size);

    }
    if (in != null)
        in.close();
    multi.close();

    request.setHandled(true);

    return;
}

From source file:org.sakaiproject.content.impl.BaseContentService.java

/**
 * Copy the partial contents of the specified input stream to the specified
 * output stream./*from  w  w  w  .  j  a v a2s.  c om*/
 * 
 * @param istream The input stream to read from
 * @param ostream The output stream to write to
 * @param start Start of the range which will be copied
 * @param end End of the range which will be copied
 * @return Exception which occurred during processing
 */
protected IOException copyRange(InputStream istream, OutputStream ostream, long start, long end) {

    try {
        istream.skip(start);
    } catch (IOException e) {
        return e;
    }

    IOException exception = null;
    long bytesToRead = end - start + 1;

    byte buffer[] = new byte[STREAM_BUFFER_SIZE];
    int len = buffer.length;
    while ((bytesToRead > 0) && (len >= buffer.length)) {
        try {
            len = istream.read(buffer);
            if (bytesToRead >= len) {
                ostream.write(buffer, 0, len);
                bytesToRead -= len;
            } else {
                ostream.write(buffer, 0, (int) bytesToRead);
                bytesToRead = 0;
            }
        } catch (IOException e) {
            exception = e;
            len = -1;
        }
        if (len < buffer.length)
            break;
    }

    return exception;
}