View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.core.session;
21  
22  import java.io.IOException;
23  import java.net.SocketAddress;
24  import java.util.List;
25  import java.util.Set;
26  import java.util.concurrent.Executor;
27  
28  import org.apache.mina.core.file.FileRegion;
29  import org.apache.mina.core.filterchain.DefaultIoFilterChain;
30  import org.apache.mina.core.filterchain.IoFilter;
31  import org.apache.mina.core.filterchain.IoFilterChain;
32  import org.apache.mina.core.service.AbstractIoAcceptor;
33  import org.apache.mina.core.service.DefaultTransportMetadata;
34  import org.apache.mina.core.service.IoAcceptor;
35  import org.apache.mina.core.service.IoHandler;
36  import org.apache.mina.core.service.IoHandlerAdapter;
37  import org.apache.mina.core.service.IoProcessor;
38  import org.apache.mina.core.service.IoService;
39  import org.apache.mina.core.service.TransportMetadata;
40  import org.apache.mina.core.write.WriteRequest;
41  
42  /**
43   * A dummy {@link IoSession} for unit-testing or non-network-use of
44   * the classes that depends on {@link IoSession}.
45   *
46   * <h2>Overriding I/O request methods</h2>
47   * All I/O request methods (i.e. {@link #close()}, {@link #write(Object)} and
48   * {@link #setTrafficMask(TrafficMask)}) are final and therefore cannot be
49   * overridden, but you can always add your custom {@link IoFilter} to the
50   * {@link IoFilterChain} to intercept any I/O events and requests.
51   *
52   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
53   */
54  public class DummySession extends AbstractIoSession {
55  
56      private static final TransportMetadata TRANSPORT_METADATA =
57              new DefaultTransportMetadata(
58                      "mina", "dummy", false, false,
59                      SocketAddress.class, IoSessionConfig.class, Object.class);
60  
61      private static final SocketAddress ANONYMOUS_ADDRESS = new SocketAddress() {
62          private static final long serialVersionUID = -496112902353454179L;
63  
64          @Override
65          public String toString() {
66              return "?";
67          }
68      };
69  
70      private volatile IoService service;
71  
72      private volatile IoSessionConfig config = new AbstractIoSessionConfig() {
73          @Override
74          protected void doSetAll(IoSessionConfig config) {
75              // Do nothing
76          }
77      };
78  
79      private final IoFilterChain filterChain = new DefaultIoFilterChain(this);
80      private final IoProcessor<AbstractIoSession> processor;
81  
82      private volatile IoHandler handler = new IoHandlerAdapter();
83      private volatile SocketAddress localAddress = ANONYMOUS_ADDRESS;
84      private volatile SocketAddress remoteAddress = ANONYMOUS_ADDRESS;
85      private volatile TransportMetadata transportMetadata = TRANSPORT_METADATA;
86  
87      /**
88       * Creates a new instance.
89       */
90      public DummySession() {
91          // Initialize dummy service.
92          IoAcceptor acceptor = new AbstractIoAcceptor(
93                  new AbstractIoSessionConfig() {
94                      @Override
95                      protected void doSetAll(IoSessionConfig config) {
96                          // Do nothing
97                      }
98                  },
99                  new Executor() {
100                     public void execute(Runnable command) {
101                         // Do nothing
102                     }
103                 }) {
104 
105             @Override
106             protected Set<SocketAddress> bindInternal(List<? extends SocketAddress> localAddresses) throws Exception {
107                 throw new UnsupportedOperationException();
108             }
109 
110             @Override
111             protected void unbind0(List<? extends SocketAddress> localAddresses) throws Exception {
112                 throw new UnsupportedOperationException();
113             }
114 
115             public IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) {
116                 throw new UnsupportedOperationException();
117             }
118 
119             public TransportMetadata getTransportMetadata() {
120                 return TRANSPORT_METADATA;
121             }
122 
123             @Override
124             protected void dispose0() throws Exception {
125             }
126         };
127 
128         // Set meaningless default values.
129         acceptor.setHandler(new IoHandlerAdapter());
130 
131         service = acceptor;
132 
133         processor = new IoProcessor<AbstractIoSession>() {
134             public void add(AbstractIoSession session) {
135                 // Do nothing
136             }
137 
138             public void flush(AbstractIoSession session) {
139                 DummySession s = (DummySession) session;
140                 WriteRequest req = s.getWriteRequestQueue().poll(session);
141                 
142                 // Chek that the request is not null. If the session has been closed,
143                 // we may not have any pending requests.
144                 if (req != null) {
145                     Object m = req.getMessage();
146                     if (m instanceof FileRegion) {
147                         FileRegion file = (FileRegion) m;
148                         try {
149                             file.getFileChannel().position(file.getPosition() + file.getRemainingBytes());
150                             file.update(file.getRemainingBytes());
151                         } catch (IOException e) {
152                             s.getFilterChain().fireExceptionCaught(e);
153                         }
154                     }
155                     getFilterChain().fireMessageSent(req);
156                 }
157             }
158 
159             public void remove(AbstractIoSession session) {
160                 if (!session.getCloseFuture().isClosed()) {
161                     session.getFilterChain().fireSessionClosed();
162                 }
163             }
164 
165             public void updateTrafficControl(AbstractIoSession session) {
166                 // Do nothing
167             }
168 
169             public void dispose() {
170                 // Do nothing
171             }
172 
173             public boolean isDisposed() {
174                 return false;
175             }
176 
177             public boolean isDisposing() {
178                 return false;
179             }
180 
181         };
182 
183         try {
184             IoSessionDataStructureFactory factory = new DefaultIoSessionDataStructureFactory();
185             setAttributeMap(factory.getAttributeMap(this));
186             setWriteRequestQueue(factory.getWriteRequestQueue(this));
187         } catch (Exception e) {
188             throw new InternalError();
189         }
190     }
191 
192     public IoSessionConfig getConfig() {
193         return config;
194     }
195 
196     /**
197      * Sets the configuration of this session.
198      */
199     public void setConfig(IoSessionConfig config) {
200         if (config == null) {
201             throw new IllegalArgumentException("config");
202         }
203 
204         this.config = config;
205     }
206 
207     public IoFilterChain getFilterChain() {
208         return filterChain;
209     }
210 
211     public IoHandler getHandler() {
212         return handler;
213     }
214 
215     /**
216      * Sets the {@link IoHandler} which handles this session.
217      */
218     public void setHandler(IoHandler handler) {
219         if (handler == null) {
220             throw new IllegalArgumentException("handler");
221         }
222 
223         this.handler = handler;
224     }
225 
226     public SocketAddress getLocalAddress() {
227         return localAddress;
228     }
229 
230     public SocketAddress getRemoteAddress() {
231         return remoteAddress;
232     }
233 
234     /**
235      * Sets the socket address of local machine which is associated with
236      * this session.
237      */
238     public void setLocalAddress(SocketAddress localAddress) {
239         if (localAddress == null) {
240             throw new IllegalArgumentException("localAddress");
241         }
242 
243         this.localAddress = localAddress;
244     }
245 
246     /**
247      * Sets the socket address of remote peer.
248      */
249     public void setRemoteAddress(SocketAddress remoteAddress) {
250         if (remoteAddress == null) {
251             throw new IllegalArgumentException("remoteAddress");
252         }
253 
254         this.remoteAddress = remoteAddress;
255     }
256 
257     public IoService getService() {
258         return service;
259     }
260 
261     /**
262      * Sets the {@link IoService} which provides I/O service to this session.
263      */
264     public void setService(IoService service) {
265         if (service == null) {
266             throw new IllegalArgumentException("service");
267         }
268 
269         this.service = service;
270     }
271 
272     @Override
273     public final IoProcessor<AbstractIoSession> getProcessor() {
274         return processor;
275     }
276 
277     public TransportMetadata getTransportMetadata() {
278         return transportMetadata;
279     }
280 
281     /**
282      * Sets the {@link TransportMetadata} that this session runs on.
283      */
284     public void setTransportMetadata(TransportMetadata transportMetadata) {
285         if (transportMetadata == null) {
286             throw new IllegalArgumentException("transportMetadata");
287         }
288 
289         this.transportMetadata = transportMetadata;
290     }
291 
292     @Override
293     public void setScheduledWriteBytes(int byteCount){
294         super.setScheduledWriteBytes(byteCount);
295     }
296 
297     @Override
298     public void setScheduledWriteMessages(int messages) {
299         super.setScheduledWriteMessages(messages);
300     }
301 
302     /**
303      * Update all statistical properties related with throughput.  By default
304      * this method returns silently without updating the throughput properties
305      * if they were calculated already within last
306      * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}.
307      * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method
308      * updates the throughput properties immediately.
309      */
310     public void updateThroughput(boolean force) {
311         super.updateThroughput(System.currentTimeMillis(), force);
312     }
313 }