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.service;
    21
    22  import java.net.SocketAddress;
    23  import java.util.concurrent.Executor;
    24  import java.util.concurrent.Executors;
    25
    26  import org.apache.mina.core.future.ConnectFuture;
    27  import org.apache.mina.core.future.IoFuture;
    28  import org.apache.mina.core.future.IoFutureListener;
    29  import org.apache.mina.core.session.IdleStatus;
    30  import org.apache.mina.core.session.IoSession;
    31  import org.apache.mina.core.session.IoSessionConfig;
    32  import org.apache.mina.core.session.IoSessionInitializer;
    33
    34  /**
    35   * A base implementation of {@link IoConnector}.
    36   *
    37   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    38   */
    39  public abstract class AbstractIoConnector extends AbstractIoService implements IoConnector {
    40      /**
    41       * The minimum timeout value that is supported (in milliseconds).
    42       */
    43      private long connectTimeoutCheckInterval = 50L;
    44
    45      private long connectTimeoutInMillis = 60 * 1000L; // 1 minute by default
    46
    47      private SocketAddress defaultRemoteAddress;
    48
    49      /**
    50       * Constructor for {@link AbstractIoConnector}. You need to provide a default
    51       * session configuration and an {@link Executor} for handling I/O events. If
    52       * null {@link Executor} is provided, a default one will be created using
    53       * {@link Executors#newCachedThreadPool()}.
    54       *
    55       * {@see AbstractIoService#AbstractIoService(IoSessionConfig, Executor)}
    56       *
    57       * @param sessionConfig
    58       *            the default configuration for the managed {@link IoSession}
    59       * @param executor
    60       *            the {@link Executor} used for handling execution of I/O
    61       *            events. Can be <code>null</code>.
    62       */
    63      protected AbstractIoConnector(IoSessionConfig sessionConfig, Executor executor) {
    64          super(sessionConfig, executor);
    65      }
    66
    67      /**
    68       * Returns the minimum connection timeout value for this connector
    69       *
    70       * @return
    71       *  The minimum time that this connector can have for a connection
    72       *  timeout in milliseconds.
    73       */
    74      public long getConnectTimeoutCheckInterval() {
    75          return connectTimeoutCheckInterval;
    76      }
    77
    78      public void setConnectTimeoutCheckInterval(long minimumConnectTimeout) {
    79          if (getConnectTimeoutMillis() < minimumConnectTimeout) {
    80              this.connectTimeoutInMillis = minimumConnectTimeout;
    81          }
    82
    83          this.connectTimeoutCheckInterval = minimumConnectTimeout;
    84      }
    85
    86      /**
    87       * @deprecated
    88       *  Take a look at <tt>getConnectTimeoutMillis()</tt>
    89       */
    90      public final int getConnectTimeout() {
    91          return (int) connectTimeoutInMillis / 1000;
    92      }
    93
    94      /**
    95       * {@inheritDoc}
    96       */
    97      public final long getConnectTimeoutMillis() {
    98          return connectTimeoutInMillis;
    99      }
    100
    101     /**
    102      * @deprecated
    103      *  Take a look at <tt>setConnectTimeoutMillis(long)</tt>
    104      */
    105     public final void setConnectTimeout(int connectTimeout) {
    106
    107         setConnectTimeoutMillis(connectTimeout * 1000L);
    108     }
    109
    110     /**
    111      * Sets the connect timeout value in milliseconds.
    112      *
    113      */
    114     public final void setConnectTimeoutMillis(long connectTimeoutInMillis) {
    115         if (connectTimeoutInMillis <= connectTimeoutCheckInterval) {
    116             this.connectTimeoutCheckInterval = connectTimeoutInMillis;
    117         }
    118         this.connectTimeoutInMillis = connectTimeoutInMillis;
    119     }
    120
    121     /**
    122      * {@inheritDoc}
    123      */
    124     public SocketAddress getDefaultRemoteAddress() {
    125         return defaultRemoteAddress;
    126     }
    127
    128     /**
    129      * {@inheritDoc}
    130      */
    131     public final void setDefaultRemoteAddress(SocketAddress defaultRemoteAddress) {
    132         if (defaultRemoteAddress == null) {
    133             throw new IllegalArgumentException("defaultRemoteAddress");
    134         }
    135
    136         if (!getTransportMetadata().getAddressType().isAssignableFrom(defaultRemoteAddress.getClass())) {
    137             throw new IllegalArgumentException("defaultRemoteAddress type: " + defaultRemoteAddress.getClass()
    138                     + " (expected: " + getTransportMetadata().getAddressType() + ")");
    139         }
    140         this.defaultRemoteAddress = defaultRemoteAddress;
    141     }
    142
    143     /**
    144      * {@inheritDoc}
    145      */
    146     public final ConnectFuture connect() {
    147         SocketAddress defaultRemoteAddress = getDefaultRemoteAddress();
    148         if (defaultRemoteAddress == null) {
    149             throw new IllegalStateException("defaultRemoteAddress is not set.");
    150         }
    151
    152         return connect(defaultRemoteAddress, null, null);
    153     }
    154
    155     /**
    156      * {@inheritDoc}
    157      */
    158     public ConnectFuture connect(IoSessionInitializer<? extends ConnectFuture> sessionInitializer) {
    159         SocketAddress defaultRemoteAddress = getDefaultRemoteAddress();
    160         if (defaultRemoteAddress == null) {
    161             throw new IllegalStateException("defaultRemoteAddress is not set.");
    162         }
    163
    164         return connect(defaultRemoteAddress, null, sessionInitializer);
    165     }
    166
    167     /**
    168      * {@inheritDoc}
    169      */
    170     public final ConnectFuture connect(SocketAddress remoteAddress) {
    171         return connect(remoteAddress, null, null);
    172     }
    173
    174     /**
    175      * {@inheritDoc}
    176      */
    177     public ConnectFuture connect(SocketAddress remoteAddress,
    178             IoSessionInitializer<? extends ConnectFuture> sessionInitializer) {
    179         return connect(remoteAddress, null, sessionInitializer);
    180     }
    181
    182     /**
    183      * {@inheritDoc}
    184      */
    185     public ConnectFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
    186         return connect(remoteAddress, localAddress, null);
    187     }
    188
    189     /**
    190      * {@inheritDoc}
    191      */
    192     public final ConnectFuture connect(SocketAddress remoteAddress, SocketAddress localAddress,
    193             IoSessionInitializer<? extends ConnectFuture> sessionInitializer) {
    194         if (isDisposing()) {
    195             throw new IllegalStateException("The connector has been disposed.");
    196         }
    197
    198         if (remoteAddress == null) {
    199             throw new IllegalArgumentException("remoteAddress");
    200         }
    201
    202         if (!getTransportMetadata().getAddressType().isAssignableFrom(remoteAddress.getClass())) {
    203             throw new IllegalArgumentException("remoteAddress type: " + remoteAddress.getClass() + " (expected: "
    204                     + getTransportMetadata().getAddressType() + ")");
    205         }
    206
    207         if (localAddress != null && !getTransportMetadata().getAddressType().isAssignableFrom(localAddress.getClass())) {
    208             throw new IllegalArgumentException("localAddress type: " + localAddress.getClass() + " (expected: "
    209                     + getTransportMetadata().getAddressType() + ")");
    210         }
    211
    212         if (getHandler() == null) {
    213             if (getSessionConfig().isUseReadOperation()) {
    214                 setHandler(new IoHandler() {
    215                     public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
    216                         // Empty handler
    217                     }
    218
    219                     public void messageReceived(IoSession session, Object message) throws Exception {
    220                         // Empty handler
    221                     }
    222
    223                     public void messageSent(IoSession session, Object message) throws Exception {
    224                         // Empty handler
    225                     }
    226
    227                     public void sessionClosed(IoSession session) throws Exception {
    228                         // Empty handler
    229                     }
    230
    231                     public void sessionCreated(IoSession session) throws Exception {
    232                         // Empty handler
    233                     }
    234
    235                     public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
    236                         // Empty handler
    237                     }
    238
    239                     public void sessionOpened(IoSession session) throws Exception {
    240                         // Empty handler
    241                     }
    242                 });
    243             } else {
    244                 throw new IllegalStateException("handler is not set.");
    245             }
    246         }
    247
    248         return connect0(remoteAddress, localAddress, sessionInitializer);
    249     }
    250
    251     /**
    252      * Implement this method to perform the actual connect operation.
    253      *
    254      * @param localAddress <tt>null</tt> if no local address is specified
    255      */
    256     protected abstract ConnectFuture connect0(SocketAddress remoteAddress, SocketAddress localAddress,
    257             IoSessionInitializer<? extends ConnectFuture> sessionInitializer);
    258
    259     /**
    260      * Adds required internal attributes and {@link IoFutureListener}s
    261      * related with event notifications to the specified {@code session}
    262      * and {@code future}.  Do not call this method directly;
    263      * {@link #finishSessionInitialization(IoSession, IoFuture, IoSessionInitializer)}
    264      * will call this method instead.
    265      */
    266     @Override
    267     protected final void finishSessionInitialization0(final IoSession session, IoFuture future) {
    268         // In case that ConnectFuture.cancel() is invoked before
    269         // setSession() is invoked, add a listener that closes the
    270         // connection immediately on cancellation.
    271         future.addListener(new IoFutureListener<ConnectFuture>() {
    272             public void operationComplete(ConnectFuture future) {
    273                 if (future.isCanceled()) {
    274                     session.close(true);
    275                 }
    276             }
    277         });
    278     }
    279
    280     /**
    281      * {@inheritDoc}
    282      */
    283     @Override
    284     public String toString() {
    285         TransportMetadata m = getTransportMetadata();
    286         return '(' + m.getProviderName() + ' ' + m.getName() + " connector: " + "managedSessionCount: "
    287                 + getManagedSessionCount() + ')';
    288     }
    289 }