001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.log;
031:
032: import com.caucho.loader.EnvironmentLocal;
033: import com.caucho.util.Alarm;
034: import com.caucho.util.QDate;
035: import com.caucho.vfs.StderrStream;
036: import com.caucho.vfs.StdoutStream;
037: import com.caucho.vfs.StreamImpl;
038: import com.caucho.vfs.Vfs;
039: import com.caucho.vfs.WriteStream;
040:
041: import java.io.IOException;
042: import java.io.OutputStream;
043: import java.io.PrintStream;
044:
045: /**
046: * A stream that varies depending on the environment class loader.
047: */
048: public class EnvironmentStream extends StreamImpl {
049: // original stdout stream
050: private final static WriteStream _origSystemOut = Vfs
051: .openWrite(System.out);
052: // original stderr stream
053: private final static WriteStream _origSystemErr = Vfs
054: .openWrite(System.err);
055:
056: // static stdout stream
057: private static PrintStream _systemOut;
058: // static stderr stream
059: private static PrintStream _systemErr;
060:
061: // static stdout stream
062: private static EnvironmentStream _stdoutStream;
063: // static stderr stream
064: private static EnvironmentStream _stderrStream;
065:
066: // context variable storing the per-environment stream.
067: private EnvironmentLocal<OutputStream> _environmentStream;
068:
069: /**
070: * Create the environment stream.
071: *
072: * @param envVariable the variable for the underlying stream
073: * @param defaultStream the stream used if outside an environment
074: */
075: public EnvironmentStream(String envVariable,
076: OutputStream defaultStream) {
077: _environmentStream = new EnvironmentLocal<OutputStream>(
078: envVariable);
079: _environmentStream.setGlobal(defaultStream);
080: }
081:
082: /**
083: * Create the environment stream.
084: *
085: * @param defaultStream the stream used if outside an environment
086: */
087: public EnvironmentStream(OutputStream defaultStream) {
088: _environmentStream = new EnvironmentLocal<OutputStream>();
089: _environmentStream.setGlobal(defaultStream);
090: }
091:
092: /**
093: * Returns the context stream's variable.
094: */
095: public String getVariable() {
096: return _environmentStream.getVariable();
097: }
098:
099: /**
100: * Returns the global stream
101: */
102: public OutputStream getGlobalStream() {
103: return (OutputStream) _environmentStream.getGlobal();
104: }
105:
106: /**
107: * Returns the context stream's variable.
108: */
109: public Object setGlobalStream(OutputStream defaultStream) {
110: return _environmentStream.setGlobal(defaultStream);
111: }
112:
113: /**
114: * Returns the global stream
115: */
116: public OutputStream getStream() {
117: return (OutputStream) _environmentStream.get();
118: }
119:
120: /**
121: * Returns the context stream's variable.
122: */
123: public Object setStream(OutputStream os) {
124: return _environmentStream.set(os);
125: }
126:
127: /**
128: * True if the stream can write
129: */
130: public boolean canWrite() {
131: OutputStream stream = getStream();
132:
133: return stream != null;
134: }
135:
136: /**
137: * Write data to the stream.
138: */
139: public void write(byte[] buf, int offset, int length, boolean isEnd)
140: throws IOException {
141: OutputStream stream = getStream();
142:
143: if (stream == null)
144: return;
145:
146: synchronized (stream) {
147: stream.write(buf, offset, length);
148: if (isEnd)
149: stream.flush();
150: }
151: }
152:
153: /**
154: * Flush data to the stream.
155: */
156: public void flush() throws IOException {
157: OutputStream stream = getStream();
158:
159: if (stream == null)
160: return;
161:
162: synchronized (stream) {
163: stream.flush();
164: }
165: }
166:
167: /**
168: * Flush data to the stream.
169: */
170: public void close() throws IOException {
171: OutputStream stream = getStream();
172:
173: if (stream == null)
174: return;
175:
176: synchronized (stream) {
177: stream.flush();
178: }
179: }
180:
181: /**
182: * Sets the backing stream for System.out
183: */
184: public static void setStdout(OutputStream os) {
185: if (_stdoutStream == null) {
186: OutputStream systemOut = System.out;
187:
188: _stdoutStream = new EnvironmentStream(
189: "caucho.stdout.stream", systemOut);
190: WriteStream out = new WriteStream(_stdoutStream);
191: out.setDisableClose(true);
192: _systemOut = new PrintStream(out, true);
193: System.setOut(_systemOut);
194:
195: if (os == systemOut)
196: return;
197: }
198:
199: if (os == _systemErr || os == _systemOut)
200: return;
201:
202: if (os instanceof WriteStream) {
203: WriteStream out = (WriteStream) os;
204:
205: if (out.getSource() == StdoutStream.create()
206: || out.getSource() == StderrStream.create())
207: return;
208: }
209:
210: _stdoutStream.setStream(os);
211: }
212:
213: /**
214: * Returns the environment stream for System.out
215: */
216: public static EnvironmentStream getStdout() {
217: return _stdoutStream;
218: }
219:
220: /**
221: * Returns the original System.out writer
222: */
223: public static WriteStream getOriginalSystemOut() {
224: return _origSystemOut;
225: }
226:
227: /**
228: * Sets path as the backing stream for System.err
229: */
230: public static void setStderr(OutputStream os) {
231: if (_stderrStream == null) {
232: OutputStream systemErr = System.err;
233:
234: _stderrStream = new EnvironmentStream(
235: "caucho.stderr.stream", systemErr);
236: WriteStream err = new WriteStream(_stderrStream);
237: err.setDisableClose(true);
238: _systemErr = new PrintStream(err, true);
239: System.setErr(_systemErr);
240:
241: if (os == systemErr)
242: return;
243: }
244:
245: if (os == _systemErr || os == _systemOut)
246: return;
247:
248: if (os instanceof WriteStream) {
249: WriteStream out = (WriteStream) os;
250:
251: if (out.getSource() == StdoutStream.create()
252: || out.getSource() == StderrStream.create())
253: return;
254: }
255:
256: _stderrStream.setStream(os);
257: }
258:
259: /**
260: * Returns the environment stream for System.err
261: */
262: public static EnvironmentStream getStderr() {
263: return _stderrStream;
264: }
265:
266: /**
267: * Returns the original System.out writer
268: */
269: public static WriteStream getOriginalSystemErr() {
270: return _origSystemErr;
271: }
272:
273: /**
274: * Logs a message to the original stderr in cases where java.util.logging
275: * is dangerous, e.g. in the logging code itself.
276: */
277: public static void logStderr(String msg, Throwable e) {
278: try {
279: long now = Alarm.getCurrentTime();
280:
281: msg = QDate.formatLocal(now, "[%Y-%m-%d %H:%M:%S] ") + msg;
282:
283: _origSystemErr.println(msg);
284:
285: e.printStackTrace(_origSystemErr.getPrintWriter());
286:
287: _origSystemErr.flush();
288: } catch (Throwable e1) {
289: }
290: }
291:
292: /**
293: * Logs a message to the original stderr in cases where java.util.logging
294: * is dangerous, e.g. in the logging code itself.
295: */
296: public static void logStderr(String msg) {
297: try {
298: long now = Alarm.getCurrentTime();
299:
300: msg = QDate.formatLocal(now, "[%Y-%m-%d %H:%M:%S] ") + msg;
301:
302: _origSystemErr.println(msg);
303: } catch (Throwable e1) {
304: }
305: }
306:
307: static {
308: _origSystemOut.setFlushOnNewline(true);
309: _origSystemErr.setFlushOnNewline(true);
310: }
311: }
|