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.hc.core5.testing.nio;
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  import java.util.concurrent.locks.Lock;
36  
37  import org.apache.hc.core5.annotation.Internal;
38  import org.apache.hc.core5.io.CloseMode;
39  import org.apache.hc.core5.reactor.Command;
40  import org.apache.hc.core5.reactor.IOEventHandler;
41  import org.apache.hc.core5.reactor.IOSession;
42  import org.apache.hc.core5.reactor.ProtocolIOSession;
43  import org.apache.hc.core5.testing.classic.Wire;
44  import org.apache.hc.core5.util.Timeout;
45  import org.slf4j.Logger;
46  
47  @Internal
48  public class LoggingIOSession implements IOSession {
49  
50      private final Logger log;
51      private final Wire wireLog;
52      private final IOSession session;
53  
54      public LoggingIOSession(final IOSession session, final Logger log, final Logger wireLog) {
55          super();
56          this.session = session;
57          this.log = log;
58          this.wireLog = wireLog != null ? new Wire(wireLog, session.getId()) : null;
59      }
60  
61      public LoggingIOSession(final ProtocolIOSession session, final Logger log) {
62          this(session, log, null);
63      }
64  
65      @Override
66      public String getId() {
67          return session.getId();
68      }
69  
70      @Override
71      public Lock getLock() {
72          return this.session.getLock();
73      }
74  
75      @Override
76      public void enqueue(final Command command, final Command.Priority priority) {
77          this.session.enqueue(command, priority);
78          if (this.log.isDebugEnabled()) {
79              this.log.debug("{} enqueued {} with priority {}", this.session, command.getClass().getSimpleName(), priority);
80          }
81      }
82  
83      @Override
84      public boolean hasCommands() {
85          return this.session.hasCommands();
86      }
87  
88      @Override
89      public Command poll() {
90          return this.session.poll();
91      }
92  
93      @Override
94      public ByteChannel channel() {
95          return this.session.channel();
96      }
97  
98      @Override
99      public SocketAddress getLocalAddress() {
100         return this.session.getLocalAddress();
101     }
102 
103     @Override
104     public SocketAddress getRemoteAddress() {
105         return this.session.getRemoteAddress();
106     }
107 
108     @Override
109     public int getEventMask() {
110         return this.session.getEventMask();
111     }
112 
113     private static String formatOps(final int ops) {
114         final StringBuilder buffer = new StringBuilder(6);
115         buffer.append('[');
116         if ((ops & SelectionKey.OP_READ) > 0) {
117             buffer.append('r');
118         }
119         if ((ops & SelectionKey.OP_WRITE) > 0) {
120             buffer.append('w');
121         }
122         if ((ops & SelectionKey.OP_ACCEPT) > 0) {
123             buffer.append('a');
124         }
125         if ((ops & SelectionKey.OP_CONNECT) > 0) {
126             buffer.append('c');
127         }
128         buffer.append(']');
129         return buffer.toString();
130     }
131 
132     @Override
133     public void setEventMask(final int ops) {
134         this.session.setEventMask(ops);
135         if (this.log.isDebugEnabled()) {
136             this.log.debug("{} event mask set {}", this.session, formatOps(ops));
137         }
138     }
139 
140     @Override
141     public void setEvent(final int op) {
142         this.session.setEvent(op);
143         if (this.log.isDebugEnabled()) {
144             this.log.debug("{} event set {}", this.session, formatOps(op));
145         }
146     }
147 
148     @Override
149     public void clearEvent(final int op) {
150         this.session.clearEvent(op);
151         if (this.log.isDebugEnabled()) {
152             this.log.debug("{} event cleared {}", this.session, formatOps(op));
153         }
154     }
155 
156     @Override
157     public void close() {
158         if (this.log.isDebugEnabled()) {
159             this.log.debug("{} close", this.session);
160         }
161         this.session.close();
162     }
163 
164     @Override
165     public Status getStatus() {
166         return this.session.getStatus();
167     }
168 
169     @Override
170     public boolean isOpen() {
171         return session.isOpen();
172     }
173 
174     @Override
175     public void close(final CloseMode closeMode) {
176         if (this.log.isDebugEnabled()) {
177             this.log.debug("{} shutdown {}", this.session, closeMode);
178         }
179         this.session.close(closeMode);
180     }
181 
182     @Override
183     public Timeout getSocketTimeout() {
184         return this.session.getSocketTimeout();
185     }
186 
187     @Override
188     public void setSocketTimeout(final Timeout timeout) {
189         if (this.log.isDebugEnabled()) {
190             this.log.debug("{} set timeout {}", this.session, timeout);
191         }
192         this.session.setSocketTimeout(timeout);
193     }
194 
195     @Override
196     public int read(final ByteBuffer dst) throws IOException {
197         final int bytesRead = session.read(dst);
198         if (log.isDebugEnabled()) {
199             log.debug("{} {} bytes read", session, bytesRead);
200         }
201         if (bytesRead > 0 && wireLog.isEnabled()) {
202             final ByteBuffer b = dst.duplicate();
203             final int p = b.position();
204             b.limit(p);
205             b.position(p - bytesRead);
206             wireLog.input(b);
207         }
208         return bytesRead;
209     }
210 
211     @Override
212     public int write(final ByteBuffer src) throws IOException {
213         final int byteWritten = session.write(src);
214         if (log.isDebugEnabled()) {
215             log.debug("{} {} bytes written", session, byteWritten);
216         }
217         if (byteWritten > 0 && wireLog.isEnabled()) {
218             final ByteBuffer b = src.duplicate();
219             final int p = b.position();
220             b.limit(p);
221             b.position(p - byteWritten);
222             wireLog.output(b);
223         }
224         return byteWritten;
225     }
226 
227     @Override
228     public void updateReadTime() {
229         this.session.updateReadTime();
230     }
231 
232     @Override
233     public void updateWriteTime() {
234         this.session.updateWriteTime();
235     }
236 
237     @Override
238     public long getLastReadTime() {
239         return this.session.getLastReadTime();
240     }
241 
242     @Override
243     public long getLastWriteTime() {
244         return this.session.getLastWriteTime();
245     }
246 
247     @Override
248     public long getLastEventTime() {
249         return this.session.getLastEventTime();
250     }
251 
252     @Override
253     public IOEventHandler getHandler() {
254         return this.session.getHandler();
255     }
256 
257     @Override
258     public void upgrade(final IOEventHandler handler) {
259         if (this.log.isDebugEnabled()) {
260             this.log.debug("{} protocol upgrade: {}", this.session, handler != null ? handler.getClass() : null);
261         }
262         this.session.upgrade(handler);
263     }
264 
265     @Override
266     public String toString() {
267         return this.session.toString();
268     }
269 
270 }