001: /*
002: * Enhydra Java Application Server Project
003: *
004: * The contents of this file are subject to the Enhydra Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License on
007: * the Enhydra web site ( http://www.enhydra.org/ ).
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
011: * the License for the specific terms governing rights and limitations
012: * under the License.
013: *
014: * The Initial Developer of the Enhydra Application Server is Lutris
015: * Technologies, Inc. The Enhydra Application Server and portions created
016: * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
017: * All Rights Reserved.
018: *
019: * Contributor(s):
020: *
021: * $Id: OutputStreamHub.java,v 1.2 2006-06-15 13:47:01 sinisa Exp $
022: */
023:
024: package com.lutris.util;
025:
026: import java.io.IOException;
027: import java.io.OutputStream;
028: import java.util.Enumeration;
029: import java.util.Vector;
030:
031: /**
032: This class implements a "hub", or redistribution center.
033: Like a "Y" connector for garden hoses, but with an arbitrary
034: number of outputs, not just 2. <P>
035:
036: Instances of this class maintain teir own set of OutputStreams.
037: When you create an instance of this class, the set is empty.
038: Writes to the hub have no effect. call <CODE>add()</CODE> to
039: register OutputStreams with the hub. All OutputStream calls are
040: routed to all the current members of the set.
041:
042: @see java.io.OutputStream
043: @author Andy John
044: */
045: public class OutputStreamHub extends OutputStream {
046:
047: private Vector myStreams;
048: private boolean closed;
049:
050: /**
051: Create a new hub with no members.
052: */
053: public OutputStreamHub() {
054: myStreams = new Vector();
055: closed = false;
056: }
057:
058: /**
059: Add a new OutputStream to the set. When <code>write()</code>s
060: happen, the will be coppied to all the current members of the set.
061:
062: @param newMember The OutputStream to add to the set.
063: @see java.io.OutputStream
064: */
065: public void add(OutputStream newMember) {
066: synchronized (myStreams) {
067: myStreams.addElement(newMember);
068: }
069: }
070:
071: /**
072: Remove an OutputStream from the set.
073:
074: @param member The OutputStream to remove.
075: @see java.io.OutputStream
076: */
077: public void remove(OutputStream member) {
078: synchronized (myStreams) {
079: myStreams.removeElement(member);
080: }
081: }
082:
083: /**
084: Is the given OutputStream currently in the set?
085:
086: @param stream The OutputStream to search for.
087: @see java.io.OutputStream
088: */
089: public boolean contains(OutputStream stream) {
090: synchronized (myStreams) {
091: return myStreams.contains(stream);
092: }
093: }
094:
095: //----------------------------------------
096:
097: /**
098: Write an integer to all the members. Writes are attempted on all
099: members. The last exception thrown, if there are more than
100: one, will be thown from this method.
101:
102: @param b The int to write.
103: @see java.io.OutputStream
104: */
105: public void write(int b) throws IOException {
106: synchronized (myStreams) {
107: if (closed)
108: throw new IOException(
109: "write() called on closed OutputStream");
110: IOException err = null;
111: Enumeration e = myStreams.elements();
112: while (e.hasMoreElements()) {
113: OutputStream o = (OutputStream) e.nextElement();
114: try {
115: o.write(b);
116: } catch (IOException ioe) {
117: err = ioe;
118: }
119: }
120: if (err != null)
121: throw err;
122: }
123: }
124:
125: /**
126: Write an array of bytes to all the members.
127: Writes are attempted on all
128: members. The last exception thrown, if there are more than
129: one, will be thown from this method.
130:
131: @param b The byte array to write.
132: @see java.io.OutputStream
133: */
134: public void write(byte b[]) throws IOException {
135: synchronized (myStreams) {
136: if (closed)
137: throw new IOException(
138: "write() called on closed OutputStream");
139: IOException err = null;
140: Enumeration e = myStreams.elements();
141: while (e.hasMoreElements()) {
142: OutputStream o = (OutputStream) e.nextElement();
143: try {
144: o.write(b);
145: } catch (IOException ioe) {
146: err = ioe;
147: }
148: }
149: if (err != null)
150: throw err;
151: }
152: }
153:
154: /**
155: Write part of an array of bytes to all the members.
156: Bytes b[off]..b[off+len-1] will be written.
157: Writes are attempted on all
158: members. The last exception thrown, if there are more than
159: one, will be thown from this method.
160:
161: @param b The byte array to write part of.
162: @param off The offset.
163: @param len How many bytes to write.
164: @see java.io.OutputStream
165: */
166: public void write(byte b[], int off, int len) throws IOException {
167: synchronized (myStreams) {
168: if (closed)
169: throw new IOException(
170: "write() called on closed OutputStream");
171: IOException err = null;
172: Enumeration e = myStreams.elements();
173: while (e.hasMoreElements()) {
174: OutputStream o = (OutputStream) e.nextElement();
175: try {
176: o.write(b, off, len);
177: } catch (IOException ioe) {
178: err = ioe;
179: }
180: }
181: if (err != null)
182: throw err;
183: }
184: }
185:
186: /**
187: Flushes are attempted on all members.
188: The last exception thrown, if there are more than
189: one, will be thown from this method.
190:
191: @see java.io.OutputStream
192: */
193: public void flush() throws IOException {
194: synchronized (myStreams) {
195: if (closed)
196: throw new IOException(
197: "flush() called on closed OutputStream");
198: IOException err = null;
199: Enumeration e = myStreams.elements();
200: while (e.hasMoreElements()) {
201: OutputStream o = (OutputStream) e.nextElement();
202: try {
203: o.flush();
204: } catch (IOException ioe) {
205: err = ioe;
206: }
207: }
208: if (err != null)
209: throw err;
210: }
211: }
212:
213: /**
214: Closes the stream. Do not call <CODE>write()</CODE> after this.
215: Calls <CODE>close()</CODE> on all member OutputStreams.
216: The last exception thrown, if there are more than
217: one, will be thown from this method.
218:
219: @see java.io.OutputStream
220: */
221: public void close() throws IOException {
222: synchronized (myStreams) {
223: if (closed)
224: throw new IOException("OutputStream already closed.");
225: closed = true;
226: IOException err = null;
227: Enumeration e = myStreams.elements();
228: while (e.hasMoreElements()) {
229: OutputStream o = (OutputStream) e.nextElement();
230: try {
231: o.close();
232: } catch (IOException ioe) {
233: err = ioe;
234: }
235: }
236: if (err != null)
237: throw err;
238: }
239: }
240:
241: }
|