View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
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 }