001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2007 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.lib.web.micro.base;
028:
029: import java.io.IOException;
030: import java.io.InputStream;
031: import javax.servlet.ServletInputStream;
032:
033: /**
034: * A marker class for a {@link ServletInputStream} that contains embedded
035: * "noop" and "flush" commands.
036: * <p>
037: * Our {@link ServletTunnel} needs this to preserve piped {@link
038: * java.io.InputStream#flush()} calls. We use "noop"s to keep the stream
039: * alive.
040: * <p>
041: * We use a "2" extension to avoid breaking the InputStream API contract.
042: */
043: public abstract class AnnotatedInputStream extends ServletInputStream {
044:
045: public static final int NOOP = -3;
046: public static final int FLUSH = -2;
047:
048: // "CLOSE" is effectively "-1"
049:
050: /**
051: * @return the input stream cast as an AnnotatedInputStream, or trivially
052: * wrapped if it is not an AnnotatedInputStream
053: */
054: public static AnnotatedInputStream toAnnotatedInputStream(
055: final InputStream in) {
056: if (in instanceof AnnotatedInputStream || in == null) {
057: return (AnnotatedInputStream) in;
058: }
059: // wrap
060: return new AnnotatedInputStream() {
061: // use plain "read" methods for our "read2" impls:
062: public int read2() throws IOException {
063: int ret = read();
064: return (ret < 0 ? -1 : ret);
065: }
066:
067: public int read2(byte[] b) throws IOException {
068: int ret = read(b);
069: return (ret < 0 ? -1 : ret);
070: }
071:
072: public int read2(byte[] b, int off, int len)
073: throws IOException {
074: int ret = read(b, off, len);
075: return (ret < 0 ? -1 : ret);
076: }
077:
078: // forward the rest:
079: public int read() throws IOException {
080: return in.read();
081: }
082:
083: public int read(byte[] b) throws IOException {
084: return in.read(b);
085: }
086:
087: public int read(byte[] b, int off, int len)
088: throws IOException {
089: return in.read(b, off, len);
090: }
091:
092: public long skip(long n) throws IOException {
093: return in.skip(n);
094: }
095:
096: public int available() throws IOException {
097: return in.available();
098: }
099:
100: public void close() throws IOException {
101: in.close();
102: }
103:
104: public void mark(int readlimit) {
105: in.mark(readlimit);
106: }
107:
108: public void reset() throws IOException {
109: in.reset();
110: }
111:
112: public boolean markSupported() {
113: return in.markSupported();
114: }
115: };
116: }
117:
118: /**
119: * @return a NOOP if the caller should call this method again, a FLUSH if the
120: * caller should flush their stream, otherwise a standard {@link #read()}
121: * return value.
122: */
123: public abstract int read2() throws IOException;
124:
125: /** @see read2(byte[],int,int) */
126: public int read2(byte[] b) throws IOException {
127: return read2(b, 0, b.length);
128: }
129:
130: /**
131: * @return a NOOP if the caller should call this method again, a FLUSH if the
132: * caller should flush their stream, otherwise a standard
133: * {@link #read(byte[],int,int)} return value.
134: * If the value is NOOP or FLUSH then zero bytes were written to the array.
135: */
136: public abstract int read2(byte[] b, int off, int len)
137: throws IOException;
138:
139: //
140: // backwards-compatibility:
141: //
142:
143: /** Backwards-compatible {@link java.io.InputStream#read()} implementation */
144: public int read() throws IOException {
145: while (true) {
146: int ret = read2();
147: if (ret == NOOP || ret == FLUSH)
148: continue;
149: return ret;
150: }
151: }
152:
153: /** Backwards-compatible {@link java.io.InputStream#read(byte[])} implementation */
154: public int read(byte b[]) throws IOException {
155: return read(b, 0, b.length);
156: }
157:
158: /** Backwards-compatible {@link java.io.InputStream#read(byte[],int,int)} implementation */
159: public int read(byte[] b, int off, int len) throws IOException {
160: while (true) {
161: int count = read2(b, off, len);
162: if (count == NOOP || count == FLUSH)
163: continue;
164: return count;
165: }
166: }
167: }
|