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.transport.socket.nio;
21  
22  import java.io.IOException;
23  import java.net.InetSocketAddress;
24  import java.net.SocketAddress;
25  import java.nio.channels.DatagramChannel;
26  import java.util.Collections;
27  import java.util.Iterator;
28  import java.util.concurrent.Executor;
29  
30  import org.apache.mina.core.polling.AbstractPollingIoConnector;
31  import org.apache.mina.core.service.IoConnector;
32  import org.apache.mina.core.service.IoProcessor;
33  import org.apache.mina.core.service.SimpleIoProcessorPool;
34  import org.apache.mina.core.service.TransportMetadata;
35  import org.apache.mina.transport.socket.DatagramConnector;
36  import org.apache.mina.transport.socket.DatagramSessionConfig;
37  import org.apache.mina.transport.socket.DefaultDatagramSessionConfig;
38  
39  /**
40   * {@link IoConnector} for datagram transport (UDP/IP).
41   *
42   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
43   */
44  public final class NioDatagramConnector extends AbstractPollingIoConnector<NioSession, DatagramChannel> implements
45  DatagramConnector {
46  
47      /**
48       * Creates a new instance.
49       */
50      public NioDatagramConnector() {
51          super(new DefaultDatagramSessionConfig(), NioProcessor.class);
52      }
53  
54      /**
55       * Creates a new instance.
56       * 
57       * @param processorCount The number of IoProcessor instance to create
58       */
59      public NioDatagramConnector(int processorCount) {
60          super(new DefaultDatagramSessionConfig(), NioProcessor.class, processorCount);
61      }
62  
63      /**
64       * Creates a new instance.
65       * 
66       * @param processor The IoProcessor instance to use
67       */
68      public NioDatagramConnector(IoProcessor<NioSession> processor) {
69          super(new DefaultDatagramSessionConfig(), processor);
70      }
71  
72      /**
73       * Constructor for {@link NioDatagramConnector} with default configuration which will use a built-in
74       * thread pool executor to manage the given number of processor instances. The processor class must have
75       * a constructor that accepts ExecutorService or Executor as its single argument, or, failing that, a
76       * no-arg constructor.
77       * 
78       * @param processorClass the processor class.
79       * @param processorCount the number of processors to instantiate.
80       * @see SimpleIoProcessorPool#SimpleIoProcessorPool(Class, Executor, int, java.nio.channels.spi.SelectorProvider)
81       * @since 2.0.0-M4
82       */
83      public NioDatagramConnector(Class<? extends IoProcessor<NioSession>> processorClass, int processorCount) {
84          super(new DefaultDatagramSessionConfig(), processorClass, processorCount);
85      }
86  
87      /**
88       * Constructor for {@link NioDatagramConnector} with default configuration with default configuration which will use a built-in
89       * thread pool executor to manage the default number of processor instances. The processor class must have
90       * a constructor that accepts ExecutorService or Executor as its single argument, or, failing that, a
91       * no-arg constructor. The default number of instances is equal to the number of processor cores
92       * in the system, plus one.
93       * 
94       * @param processorClass the processor class.
95       * @see SimpleIoProcessorPool#SimpleIoProcessorPool(Class, Executor, int, java.nio.channels.spi.SelectorProvider)
96       * @since 2.0.0-M4
97       */
98      public NioDatagramConnector(Class<? extends IoProcessor<NioSession>> processorClass) {
99          super(new DefaultDatagramSessionConfig(), processorClass);
100     }
101 
102     /**
103      * {@inheritDoc}
104      */
105     @Override
106     public TransportMetadata getTransportMetadata() {
107         return NioDatagramSession.METADATA;
108     }
109 
110     /**
111      * {@inheritDoc}
112      */
113     @Override
114     public DatagramSessionConfig getSessionConfig() {
115         return (DatagramSessionConfig) sessionConfig;
116     }
117 
118     /**
119      * {@inheritDoc}
120      */
121     @Override
122     public InetSocketAddress getDefaultRemoteAddress() {
123         return (InetSocketAddress) super.getDefaultRemoteAddress();
124     }
125 
126     /**
127      * {@inheritDoc}
128      */
129     @Override
130     public void setDefaultRemoteAddress(InetSocketAddress defaultRemoteAddress) {
131         super.setDefaultRemoteAddress(defaultRemoteAddress);
132     }
133 
134     /**
135      * {@inheritDoc}
136      */
137     @Override
138     protected void init() throws Exception {
139         // Do nothing
140     }
141 
142     /**
143      * {@inheritDoc}
144      */
145     @Override
146     protected DatagramChannel newHandle(SocketAddress localAddress) throws Exception {
147         DatagramChannel ch = DatagramChannel.open();
148 
149         try {
150             if (localAddress != null) {
151                 try {
152                     ch.socket().bind(localAddress);
153                     setDefaultLocalAddress(localAddress);
154                 } catch (IOException ioe) {
155                     // Add some info regarding the address we try to bind to the
156                     // message
157                     String newMessage = "Error while binding on " + localAddress + "\n" + "original message : "
158                             + ioe.getMessage();
159                     Exception e = new IOException(newMessage);
160                     e.initCause(ioe.getCause());
161 
162                     // and close the channel
163                     ch.close();
164 
165                     throw e;
166                 }
167             }
168 
169             return ch;
170         } catch (Exception e) {
171             // If we got an exception while binding the datagram,
172             // we have to close it otherwise we will loose an handle
173             ch.close();
174             throw e;
175         }
176     }
177 
178     /**
179      * {@inheritDoc}
180      */
181     @Override
182     protected boolean connect(DatagramChannel handle, SocketAddress remoteAddress) throws Exception {
183         handle.connect(remoteAddress);
184         return true;
185     }
186 
187     /**
188      * {@inheritDoc}
189      */
190     @Override
191     protected NioSession newSession(IoProcessor<NioSession> processor, DatagramChannel handle) {
192         NioSession session = new NioDatagramSession(this, handle, processor);
193         session.getConfig().setAll(getSessionConfig());
194         return session;
195     }
196 
197     /**
198      * {@inheritDoc}
199      */
200     @Override
201     protected void close(DatagramChannel handle) throws Exception {
202         handle.disconnect();
203         handle.close();
204     }
205 
206     /**
207      * {@inheritDoc}
208      */
209     // Unused extension points.
210     @Override
211     protected Iterator<DatagramChannel> allHandles() {
212         return Collections.emptyIterator();
213     }
214 
215     /**
216      * {@inheritDoc}
217      */
218     @Override
219     protected ConnectionRequest getConnectionRequest(DatagramChannel handle) {
220         throw new UnsupportedOperationException();
221     }
222 
223     /**
224      * {@inheritDoc}
225      */
226     @Override
227     protected void destroy() throws Exception {
228         // Do nothing
229     }
230 
231     /**
232      * {@inheritDoc}
233      */
234     @Override
235     protected boolean finishConnect(DatagramChannel handle) throws Exception {
236         throw new UnsupportedOperationException();
237     }
238 
239     /**
240      * {@inheritDoc}
241      */
242     @Override
243     protected void register(DatagramChannel handle, ConnectionRequest request) throws Exception {
244         throw new UnsupportedOperationException();
245     }
246 
247     /**
248      * {@inheritDoc}
249      */
250     @Override
251     protected int select(int timeout) throws Exception {
252         return 0;
253     }
254 
255     /**
256      * {@inheritDoc}
257      */
258     @Override
259     protected Iterator<DatagramChannel> selectedHandles() {
260         return Collections.emptyIterator();
261     }
262 
263     /**
264      * {@inheritDoc}
265      */
266     @Override
267     protected void wakeup() {
268         // Do nothing
269     }
270 }