1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.nio.testserver;
29
30 import java.io.IOException;
31 import java.net.SocketAddress;
32 import java.nio.ByteBuffer;
33 import java.nio.channels.ByteChannel;
34 import java.nio.channels.SelectionKey;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.http.nio.reactor.IOSession;
38 import org.apache.http.nio.reactor.SessionBufferStatus;
39
40
41
42
43
44
45 public class LoggingIOSession implements IOSession {
46
47 private final Log log;
48 private final Wire wireLog;
49 private final String id;
50 private final IOSession session;
51 private final ByteChannel channel;
52
53 public LoggingIOSession(final IOSession session, final String id, final Log log, final Log wireLog) {
54 super();
55 this.session = session;
56 this.channel = new LoggingByteChannel();
57 this.id = id;
58 this.log = log;
59 this.wireLog = new Wire(wireLog, this.id);
60 }
61
62 @Override
63 public ByteChannel channel() {
64 return this.channel;
65 }
66
67 @Override
68 public SocketAddress getLocalAddress() {
69 return this.session.getLocalAddress();
70 }
71
72 @Override
73 public SocketAddress getRemoteAddress() {
74 return this.session.getRemoteAddress();
75 }
76
77 @Override
78 public int getEventMask() {
79 return this.session.getEventMask();
80 }
81
82 private static String formatOps(final int ops) {
83 final StringBuilder buffer = new StringBuilder(6);
84 buffer.append('[');
85 if ((ops & SelectionKey.OP_READ) > 0) {
86 buffer.append('r');
87 }
88 if ((ops & SelectionKey.OP_WRITE) > 0) {
89 buffer.append('w');
90 }
91 if ((ops & SelectionKey.OP_ACCEPT) > 0) {
92 buffer.append('a');
93 }
94 if ((ops & SelectionKey.OP_CONNECT) > 0) {
95 buffer.append('c');
96 }
97 buffer.append(']');
98 return buffer.toString();
99 }
100
101 @Override
102 public void setEventMask(final int ops) {
103 this.session.setEventMask(ops);
104 if (this.log.isDebugEnabled()) {
105 this.log.debug(this.id + " " + this.session + ": Event mask set " + formatOps(ops));
106 }
107 }
108
109 @Override
110 public void setEvent(final int op) {
111 this.session.setEvent(op);
112 if (this.log.isDebugEnabled()) {
113 this.log.debug(this.id + " " + this.session + ": Event set " + formatOps(op));
114 }
115 }
116
117 @Override
118 public void clearEvent(final int op) {
119 this.session.clearEvent(op);
120 if (this.log.isDebugEnabled()) {
121 this.log.debug(this.id + " " + this.session + ": Event cleared " + formatOps(op));
122 }
123 }
124
125 @Override
126 public void close() {
127 if (this.log.isDebugEnabled()) {
128 this.log.debug(this.id + " " + this.session + ": Close");
129 }
130 this.session.close();
131 }
132
133 @Override
134 public int getStatus() {
135 return this.session.getStatus();
136 }
137
138 @Override
139 public boolean isClosed() {
140 return this.session.isClosed();
141 }
142
143 @Override
144 public void shutdown() {
145 if (this.log.isDebugEnabled()) {
146 this.log.debug(this.id + " " + this.session + ": Shutdown");
147 }
148 this.session.shutdown();
149 }
150
151 @Override
152 public int getSocketTimeout() {
153 return this.session.getSocketTimeout();
154 }
155
156 @Override
157 public void setSocketTimeout(final int timeout) {
158 if (this.log.isDebugEnabled()) {
159 this.log.debug(this.id + " " + this.session + ": Set timeout " + timeout);
160 }
161 this.session.setSocketTimeout(timeout);
162 }
163
164 @Override
165 public void setBufferStatus(final SessionBufferStatus status) {
166 this.session.setBufferStatus(status);
167 }
168
169 @Override
170 public boolean hasBufferedInput() {
171 return this.session.hasBufferedInput();
172 }
173
174 @Override
175 public boolean hasBufferedOutput() {
176 return this.session.hasBufferedOutput();
177 }
178
179 @Override
180 public Object getAttribute(final String name) {
181 return this.session.getAttribute(name);
182 }
183
184 @Override
185 public void setAttribute(final String name, final Object obj) {
186 if (this.log.isDebugEnabled()) {
187 this.log.debug(this.id + " " + this.session + ": Set attribute " + name);
188 }
189 this.session.setAttribute(name, obj);
190 }
191
192 @Override
193 public Object removeAttribute(final String name) {
194 if (this.log.isDebugEnabled()) {
195 this.log.debug(this.id + " " + this.session + ": Remove attribute " + name);
196 }
197 return this.session.removeAttribute(name);
198 }
199
200 @Override
201 public String toString() {
202 return this.id + " " + this.session.toString();
203 }
204
205 class LoggingByteChannel implements ByteChannel {
206
207 @Override
208 public int read(final ByteBuffer dst) throws IOException {
209 final int bytesRead = session.channel().read(dst);
210 if (log.isDebugEnabled()) {
211 log.debug(id + " " + session + ": " + bytesRead + " bytes read");
212 }
213 if (bytesRead > 0 && wireLog.isEnabled()) {
214 final ByteBuffer b = dst.duplicate();
215 final int p = b.position();
216 b.limit(p);
217 b.position(p - bytesRead);
218 wireLog.input(b);
219 }
220 return bytesRead;
221 }
222
223 @Override
224 public int write(final ByteBuffer src) throws IOException {
225 final int byteWritten = session.channel().write(src);
226 if (log.isDebugEnabled()) {
227 log.debug(id + " " + session + ": " + byteWritten + " bytes written");
228 }
229 if (byteWritten > 0 && wireLog.isEnabled()) {
230 final ByteBuffer b = src.duplicate();
231 final int p = b.position();
232 b.limit(p);
233 b.position(p - byteWritten);
234 wireLog.output(b);
235 }
236 return byteWritten;
237 }
238
239 @Override
240 public void close() throws IOException {
241 if (log.isDebugEnabled()) {
242 log.debug(id + " " + session + ": Channel close");
243 }
244 session.channel().close();
245 }
246
247 @Override
248 public boolean isOpen() {
249 return session.channel().isOpen();
250 }
251
252 }
253
254 }