001: /*
002: * @(#)KeepAliveStream.java 1.22 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.net.www.http;
029:
030: import java.net.URL;
031: import java.io.*;
032: import sun.net.www.MeteredStream;
033: import sun.net.ProgressData;
034: import sun.net.ProgressEntry;
035:
036: /**
037: * A stream that has the property of being able to be kept alive for
038: * multiple downloads from the same server.
039: *
040: * @version 1.22, 10/10/06
041: * @author Stephen R. Pietrowicz (NCSA)
042: * @author Dave Brown
043: */
044: public class KeepAliveStream extends MeteredStream implements Hurryable {
045:
046: // instance variables
047: HttpClient hc;
048:
049: boolean hurried;
050:
051: /**
052: * Constructor
053: */
054: public KeepAliveStream(InputStream is, ProgressEntry te,
055: HttpClient hc) {
056: super (is, te);
057: this .hc = hc;
058: }
059:
060: /**
061: * Attempt to cache this connection
062: */
063: public void close() throws IOException {
064: // If the inputstream is closed already, just return.
065: if (closed) {
066: return;
067: }
068:
069: // Skip past the data that's left in the Inputstream because
070: // some sort of error may have occurred.
071: // Do this ONLY if the skip won't block. The stream may have
072: // been closed at the beginning of a big file and we don't want
073: // to hang around for nothing. So if we can't skip without blocking
074: // we just close the socket and, therefore, terminate the keepAlive
075: // NOTE: Don't close super class
076: try {
077: if (expected > count) {
078: long nskip = (long) (expected - count);
079: if (nskip <= available()) {
080: long n = 0;
081: while (n < nskip) {
082: nskip = nskip - n;
083: n = skip(nskip);
084: }
085: } else {
086: hc.closeServer();
087: }
088: }
089: if (!closed && !hurried) {
090: hc.finished();
091: }
092: } finally {
093: ProgressData.pdata.unregister(te);
094: // nulling out the underlying inputstream as well as
095: // httpClient to let gc collect the memories faster
096: in = null;
097: hc = null;
098: closed = true;
099: }
100: }
101:
102: /* we explicitly do not support mark/reset */
103:
104: public boolean markSupported() {
105: return false;
106: }
107:
108: public void mark(int limit) {
109: }
110:
111: public void reset() throws IOException {
112: throw new IOException("mark/reset not supported");
113: }
114:
115: public synchronized boolean hurry() {
116: try {
117: /* CASE 0: we're actually already done */
118: if (closed || count >= expected) {
119: return false;
120: } else if (in.available() < (expected - count)) {
121: /* CASE I: can't meet the demand */
122: return false;
123: } else {
124: /* CASE II: fill our internal buffer
125: * TODO: possibly check memory here
126: */
127: byte[] buf = new byte[expected - count];
128: DataInputStream dis = new DataInputStream(in);
129: dis.readFully(buf);
130: in = new ByteArrayInputStream(buf);
131: hurried = true;
132: return true;
133: }
134: } catch (IOException e) {
135: // e.printStackTrace();
136: return false;
137: }
138: }
139: }
|