001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.access.servlet; 015 016import java.io.ByteArrayOutputStream; 017import java.io.IOException; 018 019import javax.servlet.ServletOutputStream; 020import javax.servlet.ServletResponse; 021import javax.servlet.WriteListener; 022 023public class TeeServletOutputStream extends ServletOutputStream { 024 025 final ServletOutputStream underlyingStream; 026 final ByteArrayOutputStream baosCopy; 027 028 TeeServletOutputStream(ServletResponse httpServletResponse) throws IOException { 029 // System.out.println("TeeServletOutputStream.constructor() called"); 030 this.underlyingStream = httpServletResponse.getOutputStream(); 031 baosCopy = new ByteArrayOutputStream(); 032 } 033 034 byte[] getOutputStreamAsByteArray() { 035 return baosCopy.toByteArray(); 036 } 037 038 @Override 039 public void write(int val) throws IOException { 040 if (underlyingStream != null) { 041 underlyingStream.write(val); 042 baosCopy.write(val); 043 } 044 } 045 046 @Override 047 public void write(byte[] byteArray) throws IOException { 048 if (underlyingStream == null) { 049 return; 050 } 051 // System.out.println("WRITE TeeServletOutputStream.write(byte[]) called"); 052 write(byteArray, 0, byteArray.length); 053 } 054 055 @Override 056 public void write(byte byteArray[], int offset, int length) throws IOException { 057 if (underlyingStream == null) { 058 return; 059 } 060 // System.out.println("WRITE TeeServletOutputStream.write(byte[], int, int) 061 // called"); 062 // System.out.println(new String(byteArray, offset, length)); 063 underlyingStream.write(byteArray, offset, length); 064 baosCopy.write(byteArray, offset, length); 065 } 066 067 @Override 068 public void close() throws IOException { 069 // System.out.println("CLOSE TeeServletOutputStream.close() called"); 070 071 // If the servlet accessing the stream is using a writer instead of 072 // an OutputStream, it will probably call os.close() before calling 073 // writer.close. Thus, the underlying output stream will be called 074 // before the data sent to the writer could be flushed. 075 } 076 077 @Override 078 public void flush() throws IOException { 079 if (underlyingStream == null) { 080 return; 081 } 082 // System.out.println("FLUSH TeeServletOutputStream.flush() called"); 083 underlyingStream.flush(); 084 baosCopy.flush(); 085 } 086 087 @Override 088 public boolean isReady() { 089 throw new RuntimeException("Not yet implemented"); 090 } 091 092 @Override 093 public void setWriteListener(WriteListener listener) { 094 throw new RuntimeException("Not yet implemented"); 095 } 096}