001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.transport.socket.nio; 021 022import java.io.IOException; 023import java.net.InetSocketAddress; 024import java.net.SocketAddress; 025import java.nio.channels.DatagramChannel; 026import java.util.Collections; 027import java.util.Iterator; 028import java.util.concurrent.Executor; 029 030import org.apache.mina.core.polling.AbstractPollingIoConnector; 031import org.apache.mina.core.service.IoConnector; 032import org.apache.mina.core.service.IoProcessor; 033import org.apache.mina.core.service.SimpleIoProcessorPool; 034import org.apache.mina.core.service.TransportMetadata; 035import org.apache.mina.transport.socket.DatagramConnector; 036import org.apache.mina.transport.socket.DatagramSessionConfig; 037import org.apache.mina.transport.socket.DefaultDatagramSessionConfig; 038 039/** 040 * {@link IoConnector} for datagram transport (UDP/IP). 041 * 042 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 043 */ 044public final class NioDatagramConnector extends AbstractPollingIoConnector<NioSession, DatagramChannel> implements 045DatagramConnector { 046 047 /** 048 * Creates a new instance. 049 */ 050 public NioDatagramConnector() { 051 super(new DefaultDatagramSessionConfig(), NioProcessor.class); 052 } 053 054 /** 055 * Creates a new instance. 056 * 057 * @param processorCount The number of IoProcessor instance to create 058 */ 059 public NioDatagramConnector(int processorCount) { 060 super(new DefaultDatagramSessionConfig(), NioProcessor.class, processorCount); 061 } 062 063 /** 064 * Creates a new instance. 065 * 066 * @param processor The IoProcessor instance to use 067 */ 068 public NioDatagramConnector(IoProcessor<NioSession> processor) { 069 super(new DefaultDatagramSessionConfig(), processor); 070 } 071 072 /** 073 * Constructor for {@link NioDatagramConnector} with default configuration which will use a built-in 074 * thread pool executor to manage the given number of processor instances. The processor class must have 075 * a constructor that accepts ExecutorService or Executor as its single argument, or, failing that, a 076 * no-arg constructor. 077 * 078 * @param processorClass the processor class. 079 * @param processorCount the number of processors to instantiate. 080 * @see SimpleIoProcessorPool#SimpleIoProcessorPool(Class, Executor, int, java.nio.channels.spi.SelectorProvider) 081 * @since 2.0.0-M4 082 */ 083 public NioDatagramConnector(Class<? extends IoProcessor<NioSession>> processorClass, int processorCount) { 084 super(new DefaultDatagramSessionConfig(), processorClass, processorCount); 085 } 086 087 /** 088 * Constructor for {@link NioDatagramConnector} with default configuration with default configuration which will use a built-in 089 * thread pool executor to manage the default number of processor instances. The processor class must have 090 * a constructor that accepts ExecutorService or Executor as its single argument, or, failing that, a 091 * no-arg constructor. The default number of instances is equal to the number of processor cores 092 * in the system, plus one. 093 * 094 * @param processorClass the processor class. 095 * @see SimpleIoProcessorPool#SimpleIoProcessorPool(Class, Executor, int, java.nio.channels.spi.SelectorProvider) 096 * @see org.apache.mina.core.service.SimpleIoProcessorPool#DEFAULT_SIZE 097 * @since 2.0.0-M4 098 */ 099 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}