Source for java.nio.channels.spi.AbstractSelectableChannel

   1: /* AbstractSelectableChannel.java
   2:    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.nio.channels.spi;
  40: 
  41: import java.io.IOException;
  42: import java.nio.channels.ClosedChannelException;
  43: import java.nio.channels.SelectableChannel;
  44: import java.nio.channels.SelectionKey;
  45: import java.nio.channels.Selector;
  46: import java.nio.channels.IllegalBlockingModeException;
  47: import java.util.LinkedList;
  48: import java.util.ListIterator;
  49: 
  50: public abstract class AbstractSelectableChannel extends SelectableChannel
  51: {
  52:   private boolean blocking = true;
  53:   private Object LOCK = new Object();
  54:   private SelectorProvider provider;
  55:   private LinkedList keys = new LinkedList();
  56: 
  57:   /**
  58:    * Initializes the channel
  59:    *
  60:    * @param provider the provider that created this channel
  61:    */
  62:   protected AbstractSelectableChannel(SelectorProvider provider)
  63:   {
  64:     this.provider = provider;
  65:   }
  66: 
  67:   /**
  68:    * Retrieves the object upon which the configureBlocking and register
  69:    * methods synchronize.
  70:    *
  71:    * @return the blocking lock
  72:    */
  73:   public final Object blockingLock()
  74:   {
  75:     return LOCK;
  76:   }
  77: 
  78:   /**
  79:    * Adjusts this channel's blocking mode.
  80:    *
  81:    * @param blocking true if blocking should be enabled, false otherwise
  82:    *
  83:    * @return this channel
  84:    *
  85:    * @exception IOException If an error occurs
  86:    */
  87:   public final SelectableChannel configureBlocking(boolean blocking)
  88:     throws IOException
  89:   {
  90:     synchronized (blockingLock())
  91:       {
  92:     if (this.blocking != blocking)
  93:       {
  94:         implConfigureBlocking(blocking);
  95:         this.blocking = blocking;
  96:       }
  97:       }
  98: 
  99:     return this;
 100:   }
 101: 
 102:   /**
 103:    * Closes this channel.
 104:    *
 105:    * @exception IOException If an error occurs
 106:    */
 107:   protected final void implCloseChannel() throws IOException
 108:   {
 109:     implCloseSelectableChannel();
 110:   }
 111: 
 112:   /**
 113:    * Closes this selectable channel.
 114:    *
 115:    * @exception IOException If an error occurs
 116:    */
 117:   protected abstract void implCloseSelectableChannel()
 118:     throws IOException;
 119: 
 120:   /**
 121:    * Adjusts this channel's blocking mode.
 122:    *
 123:    * @param blocking true if blocking should be enabled, false otherwise
 124:    *
 125:    * @exception IOException If an error occurs
 126:    */
 127:   protected abstract void implConfigureBlocking(boolean blocking)
 128:     throws IOException;
 129: 
 130:   /**
 131:    * Tells whether or not every I/O operation on this channel will block
 132:    * until it completes.
 133:    *
 134:    * @return true of this channel is blocking, false otherwise
 135:    */
 136:   public final boolean isBlocking()
 137:   {
 138:     return blocking;
 139:   }
 140: 
 141:   /**
 142:    * Tells whether or not this channel is currently registered with
 143:    * any selectors.
 144:    *
 145:    * @return true if this channel is registered, false otherwise
 146:    */
 147:   public final boolean isRegistered()
 148:   {
 149:     return ! keys.isEmpty();
 150:   }
 151: 
 152:   /**
 153:    * Retrieves the key representing the channel's registration with the
 154:    * given selector.
 155:    *
 156:    * @param selector the selector to get a selection key for
 157:    *
 158:    * @return the selection key this channel is registered with
 159:    */
 160:   public final SelectionKey keyFor(Selector selector)
 161:   {
 162:     if (! isOpen())
 163:       return null;
 164: 
 165:     try
 166:       {
 167:     synchronized (blockingLock())
 168:       {
 169:         return locate(selector);
 170:       }
 171:       }
 172:     catch (Exception e)
 173:       {
 174:     return null;
 175:       }
 176:   }
 177: 
 178:   /**
 179:    * Returns the provider that created this channel.
 180:    *
 181:    * @return the selector provider that created this channel
 182:    */
 183:   public final SelectorProvider provider()
 184:   {
 185:     return provider;
 186:   }
 187: 
 188:   private SelectionKey locate(Selector selector)
 189:   {
 190:     ListIterator it = keys.listIterator();
 191: 
 192:     while (it.hasNext())
 193:       {
 194:     SelectionKey key = (SelectionKey) it.next();
 195: 
 196:     if (key.selector() == selector)
 197:       return key;
 198:       }
 199: 
 200:     return null;
 201:   }
 202: 
 203:   /**
 204:    * Registers this channel with the given selector, returning a selection key.
 205:    *
 206:    * @param selin the seletor to use
 207:    * @param ops the interested operations
 208:    * @param att an attachment for the returned selection key
 209:    *
 210:    * @return the registered selection key
 211:    * 
 212:    * @exception ClosedChannelException If the channel is already closed.
 213:    * @exception IllegalBlockingModeException If the channel is configured in
 214:    * blocking mode.
 215:    */
 216:   public final SelectionKey register(Selector selin, int ops, Object att)
 217:     throws ClosedChannelException
 218:   {
 219:     if (! isOpen())
 220:       throw new ClosedChannelException();
 221: 
 222:     if ((ops & ~validOps()) != 0)
 223:       throw new IllegalArgumentException();
 224:     
 225:     SelectionKey key = null;
 226:     AbstractSelector selector = (AbstractSelector) selin;
 227: 
 228:     synchronized (blockingLock())
 229:       {
 230:     if (blocking)
 231:       throw new IllegalBlockingModeException();
 232: 
 233:     key = locate(selector);
 234: 
 235:     if (key != null && key.isValid())
 236:       {
 237:         if (att != null)
 238:           key.attach(att);
 239:       }
 240:     else
 241:       {
 242:         key = selector.register(this, ops, att);
 243: 
 244:         if (key != null)
 245:           addSelectionKey(key);
 246:       }
 247:       }
 248: 
 249:     return key;
 250:   }
 251: 
 252:   void addSelectionKey(SelectionKey key)
 253:   {
 254:     keys.add(key);
 255:   }
 256: 
 257:   // This method gets called by AbstractSelector.deregister().
 258:   void removeSelectionKey(SelectionKey key)
 259:   {
 260:     keys.remove(key);
 261:   }
 262: }