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.util.LinkedList;
  47: import java.util.ListIterator;
  48: 
  49: public abstract class AbstractSelectableChannel extends SelectableChannel
  50: {
  51:   private boolean blocking = true;
  52:   private Object LOCK = new Object();
  53:   private SelectorProvider provider;
  54:   private LinkedList keys = new LinkedList();
  55: 
  56:   /**
  57:    * Initializes the channel
  58:    *
  59:    * @param provider the provider that created this channel
  60:    */
  61:   protected AbstractSelectableChannel(SelectorProvider provider)
  62:   {
  63:     this.provider = provider;
  64:   }
  65: 
  66:   /**
  67:    * Retrieves the object upon which the configureBlocking and register
  68:    * methods synchronize.
  69:    *
  70:    * @return the blocking lock
  71:    */
  72:   public final Object blockingLock()
  73:   {
  74:     return LOCK;
  75:   }
  76: 
  77:   /**
  78:    * Adjusts this channel's blocking mode.
  79:    *
  80:    * @param blocking true if blocking should be enabled, false otherwise
  81:    *
  82:    * @return this channel
  83:    *
  84:    * @exception IOException If an error occurs
  85:    */
  86:   public final SelectableChannel configureBlocking(boolean blocking)
  87:     throws IOException
  88:   {
  89:     synchronized (blockingLock())
  90:       {
  91:     if (this.blocking != blocking)
  92:       {
  93:         implConfigureBlocking(blocking);
  94:         this.blocking = blocking;
  95:       }
  96:       }
  97: 
  98:     return this;
  99:   }
 100: 
 101:   /**
 102:    * Closes this channel.
 103:    *
 104:    * @exception IOException If an error occurs
 105:    */
 106:   protected final void implCloseChannel() throws IOException
 107:   {
 108:     implCloseSelectableChannel();
 109:   }
 110: 
 111:   /**
 112:    * Closes this selectable channel.
 113:    *
 114:    * @exception IOException If an error occurs
 115:    */
 116:   protected abstract void implCloseSelectableChannel()
 117:     throws IOException;
 118: 
 119:   /**
 120:    * Adjusts this channel's blocking mode.
 121:    *
 122:    * @param blocking true if blocking should be enabled, false otherwise
 123:    *
 124:    * @exception IOException If an error occurs
 125:    */
 126:   protected abstract void implConfigureBlocking(boolean blocking)
 127:     throws IOException;
 128: 
 129:   /**
 130:    * Tells whether or not every I/O operation on this channel will block
 131:    * until it completes.
 132:    *
 133:    * @return true of this channel is blocking, false otherwise
 134:    */
 135:   public final boolean isBlocking()
 136:   {
 137:     return blocking;
 138:   }
 139: 
 140:   /**
 141:    * Tells whether or not this channel is currently registered with
 142:    * any selectors.
 143:    *
 144:    * @return true if this channel is registered, false otherwise
 145:    */
 146:   public final boolean isRegistered()
 147:   {
 148:     return ! keys.isEmpty();
 149:   }
 150: 
 151:   /**
 152:    * Retrieves the key representing the channel's registration with the
 153:    * given selector.
 154:    *
 155:    * @param selector the selector to get a selection key for
 156:    *
 157:    * @return the selection key this channel is registered with
 158:    */
 159:   public final SelectionKey keyFor(Selector selector)
 160:   {
 161:     if (! isOpen())
 162:       return null;
 163: 
 164:     try
 165:       {
 166:     synchronized (blockingLock())
 167:       {
 168:         return locate(selector);
 169:       }
 170:       }
 171:     catch (Exception e)
 172:       {
 173:     return null;
 174:       }
 175:   }
 176: 
 177:   /**
 178:    * Returns the provider that created this channel.
 179:    *
 180:    * @return the selector provider that created this channel
 181:    */
 182:   public final SelectorProvider provider()
 183:   {
 184:     return provider;
 185:   }
 186: 
 187:   private SelectionKey locate(Selector selector)
 188:   {
 189:     ListIterator it = keys.listIterator();
 190: 
 191:     while (it.hasNext())
 192:       {
 193:     SelectionKey key = (SelectionKey) it.next();
 194: 
 195:     if (key.selector() == selector)
 196:       return key;
 197:       }
 198: 
 199:     return null;
 200:   }
 201: 
 202:   /**
 203:    * Registers this channel with the given selector, returning a selection key.
 204:    *
 205:    * @param selin the seletor to use
 206:    * @param ops the interested operations
 207:    * @param att an attachment for the returned selection key
 208:    *
 209:    * @return the registered selection key
 210:    * 
 211:    * @exception ClosedChannelException If the channel is already closed.
 212:    */
 213:   public final SelectionKey register(Selector selin, int ops, Object att)
 214:     throws ClosedChannelException
 215:   {
 216:     if (! isOpen())
 217:       throw new ClosedChannelException();
 218: 
 219:     if ((ops & ~validOps()) != 0)
 220:       throw new IllegalArgumentException();
 221:     
 222:     SelectionKey key = null;
 223:     AbstractSelector selector = (AbstractSelector) selin;
 224: 
 225:     synchronized (blockingLock())
 226:       {
 227:     key = locate(selector);
 228: 
 229:     if (key != null && key.isValid())
 230:       {
 231:         if (att != null)
 232:           key.attach(att);
 233:       }
 234:     else
 235:       {
 236:         key = selector.register(this, ops, att);
 237: 
 238:         if (key != null)
 239:           addSelectionKey(key);
 240:       }
 241:       }
 242: 
 243:     return key;
 244:   }
 245: 
 246:   void addSelectionKey(SelectionKey key)
 247:   {
 248:     keys.add(key);
 249:   }
 250: 
 251:   // This method gets called by AbstractSelector.deregister().
 252:   void removeSelectionKey(SelectionKey key)
 253:   {
 254:     keys.remove(key);
 255:   }
 256: }