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       * @see org.apache.mina.core.service.SimpleIoProcessorPool#DEFAULT_SIZE
97       * @since 2.0.0-M4
98       */
99      public NioDatagramConnector(Class<? extends IoProcessor<NioSession>> processorClass) {
100         super(new DefaultDatagramSessionConfig(), processorClass);
101     }
102 
103     public TransportMetadata getTransportMetadata() {
104         return NioDatagramSession.METADATA;
105     }
106 
107     public DatagramSessionConfig getSessionConfig() {
108         return (DatagramSessionConfig) sessionConfig;
109     }
110 
111     @Override
112     public InetSocketAddress getDefaultRemoteAddress() {
113         return (InetSocketAddress) super.getDefaultRemoteAddress();
114     }
115 
116     public void setDefaultRemoteAddress(InetSocketAddress defaultRemoteAddress) {
117         super.setDefaultRemoteAddress(defaultRemoteAddress);
118     }
119 
120     @Override
121     protected void init() throws Exception {
122         // Do nothing
123     }
124 
125     @Override
126     protected DatagramChannel newHandle(SocketAddress localAddress) throws Exception {
127         DatagramChannel ch = DatagramChannel.open();
128 
129         try {
130             if (localAddress != null) {
131                 try {
132                     ch.socket().bind(localAddress);
133                     setDefaultLocalAddress(localAddress);
134                 } catch (IOException ioe) {
135                     // Add some info regarding the address we try to bind to the
136                     // message
137                     String newMessage = "Error while binding on " + localAddress + "\n" + "original message : "
138                             + ioe.getMessage();
139                     Exception e = new IOException(newMessage);
140                     e.initCause(ioe.getCause());
141 
142                     // and close the channel
143                     ch.close();
144 
145                     throw e;
146                 }
147             }
148 
149             return ch;
150         } catch (Exception e) {
151             // If we got an exception while binding the datagram,
152             // we have to close it otherwise we will loose an handle
153             ch.close();
154             throw e;
155         }
156     }
157 
158     @Override
159     protected boolean connect(DatagramChannel handle, SocketAddress remoteAddress) throws Exception {
160         handle.connect(remoteAddress);
161         return true;
162     }
163 
164     @Override
165     protected NioSession newSession(IoProcessor<NioSession> processor, DatagramChannel handle) {
166         NioSession session = new NioDatagramSession(this, handle, processor);
167         session.getConfig().setAll(getSessionConfig());
168         return session;
169     }
170 
171     @Override
172     protected void close(DatagramChannel handle) throws Exception {
173         handle.disconnect();
174         handle.close();
175     }
176 
177     // Unused extension points.
178     @Override
179     @SuppressWarnings("unchecked")
180     protected Iterator<DatagramChannel> allHandles() {
181         return Collections.EMPTY_LIST.iterator();
182     }
183 
184     @Override
185     protected ConnectionRequest getConnectionRequest(DatagramChannel handle) {
186         throw new UnsupportedOperationException();
187     }
188 
189     @Override
190     protected void destroy() throws Exception {
191         // Do nothing
192     }
193 
194     @Override
195     protected boolean finishConnect(DatagramChannel handle) throws Exception {
196         throw new UnsupportedOperationException();
197     }
198 
199     @Override
200     protected void register(DatagramChannel handle, ConnectionRequest request) throws Exception {
201         throw new UnsupportedOperationException();
202     }
203 
204     @Override
205     protected int select(int timeout) throws Exception {
206         return 0;
207     }
208 
209     @Override
210     @SuppressWarnings("unchecked")
211     protected Iterator<DatagramChannel> selectedHandles() {
212         return Collections.EMPTY_LIST.iterator();
213     }
214 
215     @Override
216     protected void wakeup() {
217         // Do nothing
218     }
219 }