##### Coverage Report - com.sun.grizzly.UDPSelectorHandler

Classes in this File | Line Coverage | Branch Coverage | Complexity
UDPSelectorHandler |
71 % | 68/96
60 % | 18/30
| 0.0;0
UDPSelectorHandler$1 |
100 % | 2/2
N/A | N/A
| 0.0;0

1 |  |
     /*
2 |  |
      *
3 |  |
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 |  |
      *
5 |  |
      * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved.
6 |  |
      *
7 |  |
      * The contents of this file are subject to the terms of either the GNU
8 |  |
      * General Public License Version 2 only ("GPL") or the Common Development
9 |  |
      * and Distribution License("CDDL") (collectively, the "License").  You
10 |  |
      * may not use this file except in compliance with the License. You can obtain
11 |  |
      * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
12 |  |
      * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
13 |  |
      * language governing permissions and limitations under the License.
14 |  |
      *
15 |  |
      * When distributing the software, include this License Header Notice in each
16 |  |
      * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
17 |  |
      * Sun designates this particular file as subject to the "Classpath" exception
18 |  |
      * as provided by Sun in the GPL Version 2 section of the License file that
19 |  |
      * accompanied this code.  If applicable, add the following below the License
20 |  |
      * Header, with the fields enclosed by brackets [] replaced by your own
21 |  |
      * identifying information: "Portions Copyrighted [year]
22 |  |
      * [name of copyright owner]"
23 |  |
      *
24 |  |
      * Contributor(s):
25 |  |
      *
26 |  |
      * If you wish your version of this file to be governed by only the CDDL or
27 |  |
      * only the GPL Version 2, indicate your decision by adding "[Contributor]
28 |  |
      * elects to include this software in this distribution under the [CDDL or GPL
29 |  |
      * Version 2] license."  If you don't indicate a single choice of license, a
30 |  |
      * recipient has the option to distribute your version of this file under
31 |  |
      * either the CDDL, the GPL Version 2 or to extend the choice of license to
32 |  |
      * its licensees as provided above.  However, if you add GPL Version 2 code
33 |  |
      * and therefore, elected the GPL Version 2 license, then the option applies
34 |  |
      * only if the new code is made subject to such option by the copyright
35 |  |
      * holder.
36 |  |
      *
37 |  |
      */
38 |  |
39 |  |
     package com.sun.grizzly;
40 |  |
41 |  |
     import com.sun.grizzly.async.UDPAsyncQueueReader;
42 |  |
     import com.sun.grizzly.async.UDPAsyncQueueWriter;
43 |  |
     import com.sun.grizzly.util.CallbackHandlerSelectionKeyAttachment;
44 |  |
     import com.sun.grizzly.util.Copyable;
45 |  |
     import com.sun.grizzly.util.SelectionKeyOP;
46 |  |
     import com.sun.grizzly.util.State;
47 |  |
     import java.io.IOException;
48 |  |
     import java.net.BindException;
49 |  |
     import java.net.DatagramSocket;
50 |  |
     import java.net.InetSocketAddress;
51 |  |
     import java.net.SocketAddress;
52 |  |
     import java.net.SocketException;
53 |  |
     import java.nio.channels.DatagramChannel;
54 |  |
     import java.nio.channels.SelectableChannel;
55 |  |
     import java.nio.channels.SelectionKey;
56 |  |
     import java.nio.channels.Selector;
57 |  |
     import java.util.concurrent.Callable;
58 |  |
     import java.util.logging.Level;
59 |  |
60 |  |
     /**
61 |  |
      * A SelectorHandler handles all java.nio.channels.Selector operations.
62 |  |
      * One or more instance of a Selector are handled by SelectorHandler.
63 |  |
      * The logic for processing of SelectionKey interest (OP_ACCEPT,OP_READ, etc.)
64 |  |
      * is usually defined using an instance of SelectorHandler.
65 |  |
      *
66 |  |
      * This class represent a UDP implementation of a SelectorHandler.
67 |  |
      * This class first bind a datagramSocketChannel to a UDP port and then start
68 |  |
      * waiting for NIO events.
69 |  |
      *
70 |  |
      * @author Jeanfrancois Arcand
71 |  |
      */
72 |  |
     public class UDPSelectorHandler extends TCPSelectorHandler {
73 |  |
74 |  |
         private final static String NOT_SUPPORTED =
75 |  |
                 "Not supported by this SelectorHandler";
76 |  |
77 |  |
         /**
78 |  |
          * The datagramSocket instance.
79 |  |
          */
80 |  |
         protected DatagramSocket datagramSocket;
81 |  |
82 |  |
83 |  |
         /**
84 |  |
          * The DatagramChannel.
85 |  |
          */
86 |  |
         protected DatagramChannel datagramChannel;
87 |  |
88 |  |
89 |  |
         public UDPSelectorHandler() {
90 | 6 |
             this(Role.CLIENT_SERVER);
91 | 6 |
         }
92 |  |
93 |  |
94 |  |
         public UDPSelectorHandler(boolean isClient) {
95 | 0 |
             this(boolean2Role(isClient));
96 | 0 |
         }
97 |  |
98 |  |
99 |  |
         public UDPSelectorHandler(Role role) {
100 | 6 |
             super(role);
101 | 6 |
         }
102 |  |
103 |  |
104 |  |
         @Override
105 |  |
         public void copyTo(Copyable copy) {
106 | 0 |
             super.copyTo(copy);
107 | 0 |
             UDPSelectorHandler copyHandler = (UDPSelectorHandler) copy;
108 | 0 |
             copyHandler.datagramSocket = datagramSocket;
109 | 0 |
             copyHandler.datagramChannel= datagramChannel;
110 | 0 |
         }
111 |  |
112 |  |
         /**
113 |  |
          * Before invoking Selector.select(), make sure the ServerScoketChannel
114 |  |
          * has been created. If true, then register all SelectionKey to the Selector.
115 |  |
          */
116 |  |
         @Override
117 |  |
         public void preSelect(Context ctx) throws IOException {
118 | 51188 |
             initOpRegistriesIfRequired();
119 |  |
120 | 51188 |
             if (asyncQueueReader == null) {
121 | 6 |
                 asyncQueueReader = new UDPAsyncQueueReader(this);
122 |  |
             }
123 |  |
124 | 51188 |
             if (asyncQueueWriter == null) {
125 | 6 |
                 asyncQueueWriter = new UDPAsyncQueueWriter(this);
126 |  |
             }
127 |  |
128 | 51188 |
             if (selector == null){
129 |  |
                 try{
130 | 6 |
                     isShutDown.set(false);
131 |  |
132 | 6 |
                     connectorInstanceHandler = new ConnectorInstanceHandler.
133 |  |
                             ConcurrentQueueDelegateCIH(
134 |  |
                             getConnectorInstanceHandlerDelegate());
135 |  |
136 | 6 |
                     datagramChannel = DatagramChannel.open();
137 | 6 |
                     selector = Selector.open();
138 | 6 |
                     if (role != Role.CLIENT){
139 | 6 |
                         datagramSocket = datagramChannel.socket();
140 | 6 |
                         datagramSocket.setReuseAddress(reuseAddress);
141 | 6 |
                         if (inet == null)
142 | 6 |
                             datagramSocket.bind(new InetSocketAddress(port));
143 |  |
                         else
144 | 0 |
                             datagramSocket.bind(new InetSocketAddress(inet,port));
145 |  |
146 | 6 |
                         datagramChannel.configureBlocking(false);
147 | 6 |
                         datagramChannel.register( selector, SelectionKey.OP_READ );
148 |  |
149 | 6 |
                         datagramSocket.setSoTimeout(serverTimeout);
150 |  |
                     }
151 | 6 |
                     ctx.getController().notifyReady();
152 | 0 |
                 } catch (SocketException ex){
153 | 0 |
                     throw new BindException(ex.getMessage() + ": " + port);
154 | 6 |
                 }
155 |  |
156 |  |
             } else {
157 | 51182 |
                 processPendingOperations(ctx);
158 |  |
             }
159 | 51188 |
         }
160 |  |
161 |  |
162 |  |
         /**
163 |  |
          * Handle new OP_CONNECT ops.
164 |  |
          */
165 |  |
         @Override
166 |  |
         protected void onConnectOp(Context ctx,
167 |  |
                 SelectionKeyOP.ConnectSelectionKeyOP selectionKeyOp) throws IOException {
168 | 31 |
             SocketAddress remoteAddress = selectionKeyOp.getRemoteAddress();
169 | 31 |
             SocketAddress localAddress = selectionKeyOp.getLocalAddress();
170 | 31 |
             CallbackHandler callbackHandler = selectionKeyOp.getCallbackHandler();
171 |  |
172 | 31 |
             final DatagramChannel datagramChannel = DatagramChannel.open();
173 | 31 |
             datagramChannel.socket().setReuseAddress(reuseAddress);
174 | 31 |
             if (localAddress != null) {
175 | 0 |
                 datagramChannel.socket().bind(localAddress);
176 |  |
             }
177 | 31 |
             datagramChannel.configureBlocking(false);
178 | 31 |
             datagramChannel.connect(remoteAddress);
179 | 31 |
             SelectionKey key = datagramChannel.register(selector,
180 |  |
                     SelectionKey.OP_READ | SelectionKey.OP_WRITE);
181 | 31 |
             key.attach(CallbackHandlerSelectionKeyAttachment.create(key, callbackHandler));
182 | 31 |
             onConnectInterest(key, ctx);
183 | 31 |
         }
184 |  |
185 |  |
186 |  |
         /**
187 |  |
          * Shuntdown this instance by closing its Selector and associated channels.
188 |  |
          */
189 |  |
         @Override
190 |  |
         public void shutdown(){
191 |  |
             // If shutdown was called for this SelectorHandler
192 | 6 |
             if (isShutDown.getAndSet(true)) return;
193 |  |
194 | 6 |
             stateHolder.setState(State.STOPPED);
195 |  |
196 |  |
             try {
197 | 6 |
                 if ( datagramSocket != null )
198 | 6 |
                     datagramSocket.close();
199 | 0 |
             } catch (Throwable ex){
200 | 0 |
                 Controller.logger().log(Level.SEVERE,
201 |  |
                         "closeSocketException",ex);
202 | 6 |
             }
203 |  |
204 |  |
             try{
205 | 6 |
                 if ( datagramChannel != null)
206 | 6 |
                     datagramChannel.close();
207 | 0 |
             } catch (Throwable ex){
208 | 0 |
                 Controller.logger().log(Level.SEVERE,
209 |  |
                         "closeSocketException",ex);
210 | 6 |
             }
211 |  |
212 |  |
             try{
213 | 6 |
                 if ( selector != null)
214 | 6 |
                     selector.close();
215 | 0 |
             } catch (Throwable ex){
216 | 0 |
                 Controller.logger().log(Level.SEVERE,
217 |  |
                         "closeSocketException",ex);
218 | 6 |
             }
219 |  |
220 | 6 |
             if (asyncQueueReader != null) {
221 | 6 |
                 asyncQueueReader.close();
222 | 6 |
                 asyncQueueReader = null;
223 |  |
             }
224 |  |
225 | 6 |
             if (asyncQueueWriter != null) {
226 | 6 |
                 asyncQueueWriter.close();
227 | 6 |
                 asyncQueueWriter = null;
228 |  |
             }
229 | 6 |
         }
230 |  |
231 |  |
232 |  |
         /**
233 |  |
          * Handle OP_ACCEPT. Not used for UPD.
234 |  |
          */
235 |  |
         @Override
236 |  |
         public boolean onAcceptInterest(SelectionKey key, Context ctx) throws IOException{
237 | 0 |
             return false;
238 |  |
         }
239 |  |
240 |  |
241 |  |
         /**
242 |  |
          * {@inheritDoc}
243 |  |
          */
244 |  |
         @Override
245 |  |
         public Class<? extends SelectionKeyHandler> getPreferredSelectionKeyHandler() {
246 | 8 |
             return BaseSelectionKeyHandler.class;
247 |  |
         }
248 |  |
249 |  |
250 |  |
         /**
251 |  |
          * A token describing the protocol supported by an implementation of this
252 |  |
          * interface
253 |  |
          */
254 |  |
         @Override
255 |  |
         public Controller.Protocol protocol(){
256 | 84116 |
             return Controller.Protocol.UDP;
257 |  |
         }
258 |  |
259 |  |
         @Override
260 |  |
         public int getPortLowLevel() {
261 | 1 |
             if (datagramSocket != null) {
262 | 1 |
                 return datagramSocket.getLocalPort();
263 |  |
             }
264 |  |
265 | 0 |
             return -1;
266 |  |
         }
267 |  |
268 |  |
         @Override
269 |  |
         public int getSsBackLog() {
270 | 0 |
             throw new IllegalStateException(NOT_SUPPORTED);
271 |  |
         }
272 |  |
273 |  |
274 |  |
         @Override
275 |  |
         public void setSsBackLog(int ssBackLog) {
276 | 0 |
             throw new IllegalStateException(NOT_SUPPORTED);
277 |  |
         }
278 |  |
279 |  |
280 |  |
         @Override
281 |  |
         public boolean isTcpNoDelay() {
282 | 0 |
             throw new IllegalStateException(NOT_SUPPORTED);
283 |  |
         }
284 |  |
285 |  |
286 |  |
         @Override
287 |  |
         public void setTcpNoDelay(boolean tcpNoDelay) {
288 | 0 |
             throw new IllegalStateException(NOT_SUPPORTED);
289 |  |
         }
290 |  |
291 |  |
292 |  |
         @Override
293 |  |
         public int getLinger() {
294 | 0 |
            throw new IllegalStateException(NOT_SUPPORTED);
295 |  |
         }
296 |  |
297 |  |
298 |  |
         @Override
299 |  |
         public void setLinger(int linger) {
300 | 0 |
             throw new IllegalStateException(NOT_SUPPORTED);
301 |  |
         }
302 |  |
303 |  |
304 |  |
         @Override
305 |  |
         public int getSocketTimeout() {
306 | 0 |
             throw new IllegalStateException(NOT_SUPPORTED);
307 |  |
         }
308 |  |
309 |  |
310 |  |
         @Override
311 |  |
         public void setSocketTimeout(int socketTimeout) {
312 | 0 |
             throw new IllegalStateException(NOT_SUPPORTED);
313 |  |
         }
314 |  |
315 |  |
         @Override
316 |  |
         public void closeChannel(SelectableChannel channel) {
317 |  |
             try{
318 | 31 |
                 channel.close();
319 | 0 |
             } catch (IOException ex){
320 |  |
                 ; // LOG ME
321 | 31 |
             }
322 |  |
323 | 31 |
             if (asyncQueueReader != null) {
324 | 31 |
                 asyncQueueReader.onClose(channel);
325 |  |
             }
326 |  |
327 | 31 |
             if (asyncQueueWriter != null) {
328 | 31 |
                 asyncQueueWriter.onClose(channel);
329 |  |
             }
330 | 31 |
         }
331 |  |
332 |  |
         //--------------- ConnectorInstanceHandler -----------------------------
333 |  |
         @Override
334 |  |
         protected Callable<ConnectorHandler> getConnectorInstanceHandlerDelegate() {
335 | 6 |
             return new Callable<ConnectorHandler>() {
336 |  |
                 public ConnectorHandler call() throws Exception {
337 | 4 |
                     return new UDPConnectorHandler();
338 |  |
                 }
339 |  |
             };
340 |  |
         }
341 |  |
     }