001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.console;
011:
012: import java.io.IOException;
013: import java.io.OutputStream;
014:
015: import org.eclipse.swt.graphics.Color;
016: import org.eclipse.ui.WorkbenchEncoding;
017: import org.eclipse.ui.internal.console.IOConsolePartitioner;
018:
019: /**
020: * OutputStream used to write to an IOConsole.
021: * <p>
022: * Clients are not intended to instantiate this class directly, instead
023: * use <code>IOConsole.newOutputStream()</code>. Clients are not intended
024: * to subclass this class.
025: * </p>
026: * <p>
027: * Clients should avoid writing large amounts of output to this stream in the UI
028: * thread. The console needs to process the output in the UI thread and if the client
029: * hogs the UI thread writing output to the console, the console will not be able
030: * to process the output.
031: * </p>
032: * @since 3.1
033: */
034: public class IOConsoleOutputStream extends OutputStream {
035: /**
036: * Flag indicating whether this stream has been closed.
037: */
038: private boolean closed = false;
039:
040: /**
041: * The console's document partitioner.
042: */
043: private IOConsolePartitioner partitioner;
044:
045: /**
046: * The console this stream is attached to.
047: */
048: private IOConsole console;
049:
050: /**
051: * Flag indicating that the console should be activated when data
052: * is written to this stream.
053: */
054: private boolean activateOnWrite = false;
055:
056: /**
057: * The color used to decorate data written to this stream.
058: */
059: private Color color;
060:
061: /**
062: * The font style used to decorate data written to this stream.
063: */
064: private int fontStyle;
065:
066: private String fEncoding;
067: private String fDefaultEncoding = WorkbenchEncoding
068: .getWorkbenchDefaultEncoding();
069:
070: private boolean fNeedsEncoding = false;
071:
072: private boolean prependCR;
073:
074: /**
075: * Constructs a new output stream on the given console.
076: *
077: * @param console I/O console
078: */
079: IOConsoleOutputStream(IOConsole console) {
080: this .console = console;
081: this .partitioner = (IOConsolePartitioner) console
082: .getPartitioner();
083: }
084:
085: /**
086: * Returns the font style used to decorate data written to this stream.
087: *
088: * @return the font style used to decorate data written to this stream
089: */
090: public int getFontStyle() {
091: return fontStyle;
092: }
093:
094: /**
095: * Sets the font style to be used to decorate data written to this stream.
096: *
097: * @param newFontStyle the font style to be used to decorate data written to this stream
098: */
099: public void setFontStyle(int newFontStyle) {
100: if (newFontStyle != fontStyle) {
101: int old = fontStyle;
102: fontStyle = newFontStyle;
103: console.firePropertyChange(this ,
104: IConsoleConstants.P_FONT_STYLE, new Integer(old),
105: new Integer(fontStyle));
106: }
107: }
108:
109: /**
110: * Returns whether the console this stream is writing to will be activated when this stream
111: * is written to.
112: *
113: * @return whether the console this stream is writing to will be activated when this stream
114: * is written to.
115: */
116: public boolean isActivateOnWrite() {
117: return activateOnWrite;
118: }
119:
120: /**
121: * Sets whether to activate the console this stream is writing to when this stream
122: * is written to.
123: *
124: * @param activateOnWrite whether the console this stream is writing to will be activated when this stream
125: * is written to.
126: */
127: public void setActivateOnWrite(boolean activateOnWrite) {
128: this .activateOnWrite = activateOnWrite;
129: }
130:
131: /**
132: * Sets the color of this stream. Use <code>null</code> to indicate
133: * the default color.
134: *
135: * @param newColor color of this stream, or <code>null</code>
136: */
137: public void setColor(Color newColor) {
138: Color old = color;
139: if (old == null || !old.equals(newColor)) {
140: color = newColor;
141: console.firePropertyChange(this ,
142: IConsoleConstants.P_STREAM_COLOR, old, newColor);
143: }
144: }
145:
146: /**
147: * Returns the color of this stream, or <code>null</code>
148: * if default.
149: *
150: * @return the color of this stream, or <code>null</code>
151: */
152: public Color getColor() {
153: return color;
154: }
155:
156: /**
157: * Returns true if the stream has been closed
158: * @return true is the stream has been closed, false otherwise.
159: */
160: public synchronized boolean isClosed() {
161: return closed;
162: }
163:
164: /*
165: * (non-Javadoc)
166: * @see java.io.OutputStream#close()
167: */
168: public synchronized void close() throws IOException {
169: if (closed) {
170: throw new IOException("Output Stream is closed"); //$NON-NLS-1$
171: }
172: if (prependCR) { // force writing of last /r
173: prependCR = false;
174: notifyParitioner("\r"); //$NON-NLS-1$
175: }
176: console.streamClosed(this );
177: closed = true;
178: partitioner = null;
179: }
180:
181: /*
182: * (non-Javadoc)
183: * @see java.io.OutputStream#flush()
184: */
185: public void flush() throws IOException {
186: if (closed) {
187: throw new IOException("Output Stream is closed"); //$NON-NLS-1$
188: }
189: }
190:
191: /*
192: * (non-Javadoc)
193: * @see java.io.OutputStream#write(byte[], int, int)
194: */
195: public void write(byte[] b, int off, int len) throws IOException {
196: if (fNeedsEncoding) {
197: encodedWrite(new String(b, off, len, fEncoding));
198: } else {
199: encodedWrite(new String(b, off, len));
200: }
201: }
202:
203: /*
204: * (non-Javadoc)
205: * @see java.io.OutputStream#write(byte[])
206: */
207: public void write(byte[] b) throws IOException {
208: write(b, 0, b.length);
209: }
210:
211: /*
212: * (non-Javadoc)
213: * @see java.io.OutputStream#write(int)
214: */
215: public void write(int b) throws IOException {
216: write(new byte[] { (byte) b }, 0, 1);
217: }
218:
219: /**
220: * Writes a string to the attached console.
221: *
222: * @param str the string to write to the attached console.
223: * @throws IOException if the stream is closed.
224: */
225: public synchronized void write(String str) throws IOException {
226: if (fNeedsEncoding) {
227: byte[] defaultBytes = str.getBytes();
228: str = new String(defaultBytes, fEncoding);
229: }
230: encodedWrite(str);
231: }
232:
233: private void encodedWrite(String encodedString) throws IOException {
234: if (closed) {
235: throw new IOException("Output Stream is closed"); //$NON-NLS-1$
236: }
237: if (prependCR) {
238: encodedString = "\r" + encodedString; //$NON-NLS-1$
239: prependCR = false;
240: }
241: if (encodedString.endsWith("\r")) { //$NON-NLS-1$
242: prependCR = true;
243: encodedString = new String(encodedString.substring(0,
244: encodedString.length() - 1));
245: }
246: notifyParitioner(encodedString);
247: }
248:
249: private void notifyParitioner(String encodedString)
250: throws IOException {
251: try {
252: partitioner.streamAppended(this , encodedString);
253:
254: if (activateOnWrite) {
255: console.activate();
256: } else {
257: ConsolePlugin.getDefault().getConsoleManager()
258: .warnOfContentChange(console);
259: }
260: } catch (IOException e) {
261: if (!closed) {
262: close();
263: }
264: throw e;
265: }
266: }
267:
268: /**
269: * Sets the character encoding used to interpret characters written to this steam.
270: *
271: * @param encoding encoding identifier
272: */
273: public void setEncoding(String encoding) {
274: fEncoding = encoding;
275: fNeedsEncoding = (fEncoding != null)
276: && (!fEncoding.equals(fDefaultEncoding));
277: }
278: }
|