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.IoHandler;
35  import org.apache.mina.core.service.IoHandlerAdapter;
36  import org.apache.mina.core.service.IoProcessor;
37  import org.apache.mina.core.service.IoService;
38  import org.apache.mina.core.service.TransportMetadata;
39  import org.apache.mina.core.write.WriteRequest;
40  import org.apache.mina.core.write.WriteRequestQueue;
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 = new DefaultTransportMetadata("mina", "dummy", false,
57              false, SocketAddress.class, IoSessionConfig.class, Object.class);
58  
59      private static final SocketAddress ANONYMOUS_ADDRESS = new SocketAddress() {
60          private static final long serialVersionUID = -496112902353454179L;
61  
62          @Override
63          public String toString() {
64              return "?";
65          }
66      };
67  
68      private volatile IoService service;
69  
70      private volatile IoSessionConfig config = new AbstractIoSessionConfig() {
71          @Override
72          protected void doSetAll(IoSessionConfig config) {
73              // Do nothing
74          }
75      };
76  
77      private final IoFilterChain filterChain = new DefaultIoFilterChain(this);
78  
79      private final IoProcessor<AbstractIoSession> processor;
80  
81      private volatile IoHandler handler = new IoHandlerAdapter();
82  
83      private volatile SocketAddress localAddress = ANONYMOUS_ADDRESS;
84  
85      private volatile SocketAddress remoteAddress = ANONYMOUS_ADDRESS;
86  
87      private volatile TransportMetadata transportMetadata = TRANSPORT_METADATA;
88  
89      /**
90       * Creates a new instance.
91       */
92      public DummySession() {
93          super(
94  
95          // Initialize dummy service.
96                  new AbstractIoAcceptor(new AbstractIoSessionConfig() {
97                      @Override
98                      protected void doSetAll(IoSessionConfig config) {
99                          // Do nothing
100                     }
101                 }, new Executor() {
102                     public void execute(Runnable command) {
103                         // Do nothing
104                     }
105                 }) {
106 
107                     @Override
108                     protected Set<SocketAddress> bindInternal(List<? extends SocketAddress> localAddresses)
109                             throws Exception {
110                         throw new UnsupportedOperationException();
111                     }
112 
113                     @Override
114                     protected void unbind0(List<? extends SocketAddress> localAddresses) throws Exception {
115                         throw new UnsupportedOperationException();
116                     }
117 
118                     public IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) {
119                         throw new UnsupportedOperationException();
120                     }
121 
122                     public TransportMetadata getTransportMetadata() {
123                         return TRANSPORT_METADATA;
124                     }
125 
126                     @Override
127                     protected void dispose0() throws Exception {
128                     }
129                 });
130 
131         processor = new IoProcessor<AbstractIoSession>() {
132             public void add(AbstractIoSession session) {
133                 // Do nothing
134             }
135 
136             public void flush(AbstractIoSession session) {
137                 DummySession s = (DummySession) session;
138                 WriteRequest req = s.getWriteRequestQueue().poll(session);
139 
140                 // Chek that the request is not null. If the session has been closed,
141                 // we may not have any pending requests.
142                 if (req != null) {
143                     Object m = req.getMessage();
144                     if (m instanceof FileRegion) {
145                         FileRegion file = (FileRegion) m;
146                         try {
147                             file.getFileChannel().position(file.getPosition() + file.getRemainingBytes());
148                             file.update(file.getRemainingBytes());
149                         } catch (IOException e) {
150                             s.getFilterChain().fireExceptionCaught(e);
151                         }
152                     }
153                     getFilterChain().fireMessageSent(req);
154                 }
155             }
156 
157             /**
158              * {@inheritDoc}
159              */
160             public void write(AbstractIoSession session, WriteRequest writeRequest) {
161                 WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue();
162 
163                 writeRequestQueue.offer(session, writeRequest);
164 
165                 if (!session.isWriteSuspended()) {
166                     this.flush(session);
167                 }
168             }
169 
170             public void remove(AbstractIoSession session) {
171                 if (!session.getCloseFuture().isClosed()) {
172                     session.getFilterChain().fireSessionClosed();
173                 }
174             }
175 
176             public void updateTrafficControl(AbstractIoSession session) {
177                 // Do nothing
178             }
179 
180             public void dispose() {
181                 // Do nothing
182             }
183 
184             public boolean isDisposed() {
185                 return false;
186             }
187 
188             public boolean isDisposing() {
189                 return false;
190             }
191 
192         };
193 
194         this.service = super.getService();
195 
196         try {
197             IoSessionDataStructureFactory factory = new DefaultIoSessionDataStructureFactory();
198             setAttributeMap(factory.getAttributeMap(this));
199             setWriteRequestQueue(factory.getWriteRequestQueue(this));
200         } catch (Exception e) {
201             throw new InternalError();
202         }
203     }
204 
205     public IoSessionConfig getConfig() {
206         return config;
207     }
208 
209     /**
210      * Sets the configuration of this session.
211      */
212     public void setConfig(IoSessionConfig config) {
213         if (config == null) {
214             throw new IllegalArgumentException("config");
215         }
216 
217         this.config = config;
218     }
219 
220     public IoFilterChain getFilterChain() {
221         return filterChain;
222     }
223 
224     public IoHandler getHandler() {
225         return handler;
226     }
227 
228     /**
229      * Sets the {@link IoHandler} which handles this session.
230      */
231     public void setHandler(IoHandler handler) {
232         if (handler == null) {
233             throw new IllegalArgumentException("handler");
234         }
235 
236         this.handler = handler;
237     }
238 
239     public SocketAddress getLocalAddress() {
240         return localAddress;
241     }
242 
243     public SocketAddress getRemoteAddress() {
244         return remoteAddress;
245     }
246 
247     /**
248      * Sets the socket address of local machine which is associated with
249      * this session.
250      */
251     public void setLocalAddress(SocketAddress localAddress) {
252         if (localAddress == null) {
253             throw new IllegalArgumentException("localAddress");
254         }
255 
256         this.localAddress = localAddress;
257     }
258 
259     /**
260      * Sets the socket address of remote peer.
261      */
262     public void setRemoteAddress(SocketAddress remoteAddress) {
263         if (remoteAddress == null) {
264             throw new IllegalArgumentException("remoteAddress");
265         }
266 
267         this.remoteAddress = remoteAddress;
268     }
269 
270     public IoService getService() {
271         return service;
272     }
273 
274     /**
275      * Sets the {@link IoService} which provides I/O service to this session.
276      */
277     public void setService(IoService service) {
278         if (service == null) {
279             throw new IllegalArgumentException("service");
280         }
281 
282         this.service = service;
283     }
284 
285     @Override
286     public final IoProcessor<AbstractIoSession> getProcessor() {
287         return processor;
288     }
289 
290     public TransportMetadata getTransportMetadata() {
291         return transportMetadata;
292     }
293 
294     /**
295      * Sets the {@link TransportMetadata} that this session runs on.
296      */
297     public void setTransportMetadata(TransportMetadata transportMetadata) {
298         if (transportMetadata == null) {
299             throw new IllegalArgumentException("transportMetadata");
300         }
301 
302         this.transportMetadata = transportMetadata;
303     }
304 
305     @Override
306     public void setScheduledWriteBytes(int byteCount) {
307         super.setScheduledWriteBytes(byteCount);
308     }
309 
310     @Override
311     public void setScheduledWriteMessages(int messages) {
312         super.setScheduledWriteMessages(messages);
313     }
314 
315     /**
316      * Update all statistical properties related with throughput.  By default
317      * this method returns silently without updating the throughput properties
318      * if they were calculated already within last
319      * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}.
320      * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method
321      * updates the throughput properties immediately.
322      */
323     public void updateThroughput(boolean force) {
324         super.updateThroughput(System.currentTimeMillis(), force);
325     }
326 }