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 }