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