001 /*
002 * The MIT License
003 * Copyright (c) 2012 Microsoft Corporation
004 *
005 * Permission is hereby granted, free of charge, to any person obtaining a copy
006 * of this software and associated documentation files (the "Software"), to deal
007 * in the Software without restriction, including without limitation the rights
008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
009 * copies of the Software, and to permit persons to whom the Software is
010 * furnished to do so, subject to the following conditions:
011 *
012 * The above copyright notice and this permission notice shall be included in
013 * all copies or substantial portions of the Software.
014 *
015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
021 * THE SOFTWARE.
022 */
023
024 package microsoft.exchange.webservices.data.misc;
025
026 import microsoft.exchange.webservices.data.core.ExchangeService;
027 import microsoft.exchange.webservices.data.core.request.HangingServiceRequestBase;
028 import microsoft.exchange.webservices.data.core.enumeration.misc.TraceFlags;
029 import org.apache.commons.logging.Log;
030 import org.apache.commons.logging.LogFactory;
031
032 import javax.xml.stream.XMLStreamException;
033
034 import java.io.ByteArrayOutputStream;
035 import java.io.IOException;
036 import java.io.InputStream;
037
038 /**
039 * A stream that traces everything it returns from its Read() call.
040 * That trace may be retrieved at the end of the stream.
041 */
042 public class HangingTraceStream extends InputStream {
043
044 private static final Log LOG = LogFactory.getLog(HangingTraceStream.class);
045
046 private final InputStream underlyingStream;
047 private final ExchangeService service;
048 private ByteArrayOutputStream responseCopy;
049
050 /**
051 * Initializes a new instance of the HangingTraceStream class.
052 *
053 * @param stream The stream.
054 * @param service the service.
055 */
056 public HangingTraceStream(final InputStream stream, final ExchangeService service) {
057 this.underlyingStream = stream;
058 this.service = service;
059 }
060
061 /**
062 * Gets a value indicating whether the current stream supports reading.
063 *
064 * @return true
065 */
066 public boolean getCanRead() {
067 return true;
068 }
069
070 /**
071 * Gets a value indicating whether the current stream supports seeking.
072 *
073 * @return false
074 */
075 public boolean getCanSeek() {
076 return false;
077 }
078
079 /**
080 * Gets a value indicating whether the current stream supports writing.
081 *
082 * @return false
083 */
084 public boolean getCanWrite() {
085 return false;
086 }
087
088 /**
089 * When overridden in a derived class, clears all buffers
090 * for this stream and causes any buffered data to be
091 * written to the underlying device.
092 *@exception An I/O error occurs.
093 */
094 /*
095 * @Override public void close() { // no-op }
096 */
097
098 /**
099 * When overridden in a derived class, reads a sequence of
100 * bytes from the current stream and advances the
101 * position within the stream by the number of bytes read.
102 *
103 * @param buffer An array of bytes. When this method returns, the buffer
104 * contains the specified byte array with the values between
105 * @param offset The zero-based byte offset in at which to
106 * begin storing the data read from the current stream.
107 * @param count The maximum number of bytes to be read from the current stream.
108 * @return The total number of bytes read into the buffer.
109 * This can be less than the number of bytes requested if that
110 * many bytes are not currently available, or zero (0)
111 * if the end of the stream has been reached.
112 * @throws IOException The sum of offset and count is larger than the buffer length.
113 */
114 @Override
115 public int read(byte[] buffer, int offset, int count) throws IOException {
116 count = HangingServiceRequestBase.BUFFER_SIZE;
117 final int retVal = underlyingStream.read(buffer, offset, count);
118
119 if (HangingServiceRequestBase.isLogAllWireBytes()) {
120 final String readString = new String(buffer, offset, count, "UTF-8");
121 final String logMessage = String.format(
122 "HangingTraceStream ID [%d] returned %d bytes. Bytes returned: [%s]",
123 hashCode(), retVal, readString);
124
125 try {
126 service.traceMessage(TraceFlags.DebugMessage, logMessage);
127 } catch (final XMLStreamException e) {
128 LOG.error(e);
129 }
130 }
131
132 if (responseCopy != null) {
133 responseCopy.write(buffer, offset, retVal);
134 }
135
136 return retVal;
137 }
138
139 /**
140 * Sets the response copy.
141 *
142 * @param responseCopy a copy of response
143 */
144 public void setResponseCopy(final ByteArrayOutputStream responseCopy) {
145 this.responseCopy = responseCopy;
146 }
147
148 @Override
149 public int read() throws IOException {
150 return 0;
151 }
152
153 }
154