001: package com.quadcap.net.server;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.FileOutputStream;
042: import java.io.IOException;
043: import java.io.OutputStream;
044:
045: import com.quadcap.util.Debug;
046:
047: /**
048: * An efficient worker output stream, which is <B>NOT</B> destroyed after
049: * each session, to reduce allocation overhead. This class performs
050: * all necessary buffering of the Socket OutputStream, so no extra
051: * "buffer stream" classes are needed.
052: *
053: * @author Stan Bailes
054: */
055: public final class WorkerOutputStream extends OutputStream {
056: static final int MAX = 4096;
057: byte[] buf = new byte[MAX];
058: byte[] temp = new byte[16];
059: int pos = 0;
060: OutputStream out;
061:
062: //#ifdef DEBUG
063: static boolean doTrace = false;
064: FileOutputStream log;
065:
066: //#endif
067:
068: public WorkerOutputStream(FileOutputStream log) {
069: //#ifdef DEBUG
070: doTrace = (log != null);
071: this .log = log;
072: //#endif
073: }
074:
075: public final void reset(OutputStream out) throws IOException {
076: this .out = out;
077: this .pos = 0;
078: //#ifdef DEBUG
079: if (doTrace) {
080: log
081: .write(("RESET " + Thread.currentThread().getName() + "\r\n")
082: .getBytes());
083: }
084: //#endif
085: }
086:
087: public final void write(int c) throws IOException {
088: if (pos >= MAX) {
089: owrite(buf, 0, MAX);
090: }
091: buf[pos++] = (byte) c;
092: }
093:
094: final void owrite(byte[] b, int off, int len) throws IOException {
095: out.write(b, off, len);
096: pos = 0;
097: //#ifdef DEBUG
098: if (doTrace) {
099: log.write("WRITE\r\n".getBytes());
100: log.write(b, off, len);
101: }
102: //#endif
103: }
104:
105: public final void write(String s) throws IOException {
106: int len = s.length();
107: int off = 0;
108: while (len + pos >= MAX) {
109: int slen = MAX - pos;
110: s.getBytes(off, off + slen, buf, pos);
111: owrite(buf, 0, MAX);
112: off += slen;
113: len -= slen;
114: pos = 0;
115: }
116: if (len > 0) {
117: s.getBytes(off, len, buf, pos);
118: pos += len;
119: }
120: }
121:
122: public final void write(byte[] b, int off, int len)
123: throws IOException {
124: final int npos = pos + len;
125: if (npos >= MAX) {
126: if (pos == 0) {
127: owrite(b, off, len);
128: } else {
129: final int slen = MAX - pos;
130: System.arraycopy(b, off, buf, pos, slen);
131: owrite(buf, 0, MAX);
132: len -= slen;
133: if (len < MAX) {
134: System.arraycopy(b, off + slen, buf, 0, len);
135: pos = len;
136: } else {
137: pos = 0;
138: owrite(b, off + slen, len);
139: }
140: }
141: } else {
142: System.arraycopy(b, off, buf, pos, len);
143: pos = npos;
144: }
145: }
146:
147: public final void write(byte[] b) throws IOException {
148: write(b, 0, b.length);
149: }
150:
151: public final void flush() throws IOException {
152: if (pos > 0) {
153: owrite(buf, 0, pos);
154: pos = 0;
155: }
156: out.flush();
157: }
158:
159: static final byte[] digits = "0123456789".getBytes();
160:
161: public final void writeInt(int x) throws IOException {
162: int p = 0;
163: while (x > 0) {
164: temp[p++] = digits[x % 10];
165: x /= 10;
166: }
167: if (p == 0)
168: temp[p++] = (byte) '0';
169: if (pos + p < MAX) {
170: while (p > 0)
171: buf[pos++] = temp[--p];
172: } else {
173: while (p > 0)
174: write(temp[--p]);
175: }
176: }
177:
178: public final void close() throws IOException {
179: flush();
180: out.close();
181: //#ifdef DEBUG
182: if (doTrace)
183: log.write("CLOSE\r\n".getBytes());
184: //#endif
185: }
186: }
|