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