blob: 3bfd549948ed50795ae2d0c4b4420e28638e1387 [file] [log] [blame]
/* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.etch.util.core.nio;
import java.io.EOFException;
import java.io.IOException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
/**
* Abstract implementation of Handler.
* @param <T>
*/
public class AbstractHandler<T extends SelectableChannel>
implements Handler<T>
{
/**
* @param channel
*/
public AbstractHandler( T channel )
{
this.channel = channel;
}
private final T channel;
public final T channel()
{
return channel;
}
public final void registered( Selector selector, SelectionKey key )
{
this.selector = selector;
this.key = key;
registered();
}
private Selector selector;
private SelectionKey key;
/**
* @return the Selector of the handler.
*/
public final Selector selector()
{
return selector;
}
public final SelectionKey key()
{
return key;
}
/**
* Notifies the handler that it has been registered with a selector.
*/
protected void registered()
{
// nothing to do.
}
public final int getLastInterestOps()
{
return lastInterestOps;
}
public final void setLastInterestOps( int ops )
{
lastInterestOps = ops;
}
private int lastInterestOps;
public final void selected() throws Exception
{
SelectionKey k = key;
if (k == null)
return;
int ops = k.readyOps();
if ((ops & SelectionKey.OP_ACCEPT) != 0)
{
doAccept();
return;
}
if ((ops & SelectionKey.OP_CONNECT) != 0)
{
doConnect();
return;
}
if ((ops & SelectionKey.OP_READ) != 0)
doRead();
if ((ops & SelectionKey.OP_WRITE) != 0)
doWrite();
}
protected void doAccept() throws Exception
{
throw new IOException( "doAccept not implemented" );
}
protected void doConnect() throws Exception
{
throw new IOException( "doConnect not implemented" );
}
protected void doRead() throws Exception
{
throw new IOException( "doRead not implemented" );
}
protected void doWrite() throws Exception
{
throw new IOException( "doWrite not implemented" );
}
public final int getInterestOps() throws Exception
{
if (canAccept())
return SelectionKey.OP_ACCEPT;
if (canConnect())
return SelectionKey.OP_CONNECT;
int ops = canRead() ? SelectionKey.OP_READ : 0;
if (canWrite())
ops |= SelectionKey.OP_WRITE;
return ops;
}
/**
* @return true if this handler can accept. Called from
* {@link #getInterestOps()}.
* @throws Exception
*/
protected boolean canAccept() throws Exception
{
return false;
}
/**
* @return true if this handler can connect. Called from
* {@link #getInterestOps()}.
* @throws Exception
*/
protected boolean canConnect() throws Exception
{
return false;
}
/**
* @return true if this handler can read. Called from
* {@link #getInterestOps()}.
* @throws Exception
*/
protected boolean canRead() throws Exception
{
return false;
}
/**
* @return true if this handler can write. Called from
* {@link #getInterestOps()}.
* @throws Exception
*/
protected boolean canWrite() throws Exception
{
return false;
}
/**
* Updates the interest ops of the channel.
*/
public final void updateInterestOps()
{
Selector s = selector;
if (s == null)
throw new IllegalStateException( "selector == null" );
s.updateInterestOps( this );
}
/**
* Cancels the registration of this handler.
*/
public final void cancel()
{
Selector s = selector;
if (s != null)
s.cancel( this );
else
canceled( null );
}
public void canceled( Exception e )
{
try
{
if (e != null)
reportException( e );
if (key != null)
key.cancel();
channel.close();
}
catch ( Exception e1 )
{
reportException( e1 );
}
finally
{
selector = null;
key = null;
}
}
public void reportException( Exception e )
{
if (e instanceof IOException)
{
if (e instanceof EOFException)
return;
String msg = e.getMessage();
if (msg != null)
{
if (msg.equals( "An existing connection was forcibly closed by the remote host" ))
return;
}
}
System.err.printf( "%s: caught exception: %s\n", this, e );
e.printStackTrace();
}
}