/* AbstractSelectableChannel.java
   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.nio.channels.spi;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.LinkedList;
import java.util.ListIterator;

public abstract class AbstractSelectableChannel extends SelectableChannel
{
  private boolean blocking = true;
  private Object LOCK = new Object();
  private SelectorProvider provider;
  private LinkedList keys = new LinkedList();

  /**
   * Initializes the channel
   *
   * @param provider the provider that created this channel
   */
  protected AbstractSelectableChannel(SelectorProvider provider)
  {
    this.provider = provider;
  }

  /**
   * Retrieves the object upon which the configureBlocking and register
   * methods synchronize.
   *
   * @return the blocking lock
   */
  public final Object blockingLock()
  {
    return LOCK;
  }

  /**
   * Adjusts this channel's blocking mode.
   *
   * @param blocking true if blocking should be enabled, false otherwise
   *
   * @return this channel
   *
   * @exception IOException If an error occurs
   */
  public final SelectableChannel configureBlocking(boolean blocking)
    throws IOException
  {
    synchronized (blockingLock())
      {
	if (this.blocking != blocking)
	  {
	    implConfigureBlocking(blocking);
	    this.blocking = blocking;
	  }
      }

    return this;
  }

  /**
   * Closes this channel.
   *
   * @exception IOException If an error occurs
   */
  protected final void implCloseChannel() throws IOException
  {
    implCloseSelectableChannel();
  }

  /**
   * Closes this selectable channel.
   *
   * @exception IOException If an error occurs
   */
  protected abstract void implCloseSelectableChannel()
    throws IOException;

  /**
   * Adjusts this channel's blocking mode.
   *
   * @param blocking true if blocking should be enabled, false otherwise
   *
   * @exception IOException If an error occurs
   */
  protected abstract void implConfigureBlocking(boolean blocking)
    throws IOException;

  /**
   * Tells whether or not every I/O operation on this channel will block
   * until it completes.
   *
   * @return true of this channel is blocking, false otherwise
   */
  public final boolean isBlocking()
  {
    return blocking;
  }

  /**
   * Tells whether or not this channel is currently registered with
   * any selectors.
   *
   * @return true if this channel is registered, false otherwise
   */
  public final boolean isRegistered()
  {
    return ! keys.isEmpty();
  }

  /**
   * Retrieves the key representing the channel's registration with the
   * given selector.
   *
   * @param selector the selector to get a selection key for
   *
   * @return the selection key this channel is registered with
   */
  public final SelectionKey keyFor(Selector selector)
  {
    if (! isOpen())
      return null;

    try
      {
	synchronized (blockingLock())
	  {
	    return locate(selector);
	  }
      }
    catch (Exception e)
      {
	return null;
      }
  }

  /**
   * Returns the provider that created this channel.
   *
   * @return the selector provider that created this channel
   */
  public final SelectorProvider provider()
  {
    return provider;
  }

  private SelectionKey locate(Selector selector)
  {
    ListIterator it = keys.listIterator();

    while (it.hasNext())
      {
	SelectionKey key = (SelectionKey) it.next();

	if (key.selector() == selector)
	  return key;
      }

    return null;
  }

  /**
   * Registers this channel with the given selector, returning a selection key.
   *
   * @param selin the seletor to use
   * @param ops the interested operations
   * @param att an attachment for the returned selection key
   *
   * @return the registered selection key
   * 
   * @exception ClosedChannelException If the channel is already closed.
   */
  public final SelectionKey register(Selector selin, int ops, Object att)
    throws ClosedChannelException
  {
    if (! isOpen())
      throw new ClosedChannelException();

    if ((ops & ~validOps()) != 0)
      throw new IllegalArgumentException();
    
    SelectionKey key = null;
    AbstractSelector selector = (AbstractSelector) selin;

    synchronized (blockingLock())
      {
	key = locate(selector);

	if (key != null && key.isValid())
	  {
	    if (att != null)
	      key.attach(att);
	  }
	else
	  {
	    key = selector.register(this, ops, att);

	    if (key != null)
	      addSelectionKey(key);
	  }
      }

    return key;
  }

  void addSelectionKey(SelectionKey key)
  {
    keys.add(key);
  }

  // This method gets called by AbstractSelector.deregister().
  void removeSelectionKey(SelectionKey key)
  {
    keys.remove(key);
  }
}
