You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2003/12/06 07:12:30 UTC
svn commit: rev 1368 - in incubator/directory/ldap/trunk/eve/frontend/listener: . impl impl/src impl/src/java impl/src/java/org impl/src/java/org/apache impl/src/java/org/apache/eve impl/src/java/org/apache/eve/listener spi spi/src spi/src/java spi/src/java/org spi/src/java/org/apache spi/src/java/org/apache/eve spi/src/java/org/apache/eve/listener
Author: akarasulu
Date: Fri Dec 5 22:12:30 2003
New Revision: 1368
Added:
incubator/directory/ldap/trunk/eve/frontend/listener/
incubator/directory/ldap/trunk/eve/frontend/listener/impl/
incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/
incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/java/
incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/java/org/
incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/java/org/apache/
incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/java/org/apache/eve/
incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/java/org/apache/eve/listener/
incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/java/org/apache/eve/listener/NonBlockingListenerManager.java
incubator/directory/ldap/trunk/eve/frontend/listener/spi/
incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/
incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/
incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/
incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/
incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/eve/
incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/eve/listener/
incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/eve/listener/ListenerManager.java
incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/eve/listener/ServerListener.java
Log:
Adding the listener code.
Added: incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/java/org/apache/eve/listener/NonBlockingListenerManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/eve/frontend/listener/impl/src/java/org/apache/eve/listener/NonBlockingListenerManager.java Fri Dec 5 22:12:30 2003
@@ -0,0 +1,304 @@
+/*
+
+ ============================================================================
+ The Apache Software License, Version 1.1
+ ============================================================================
+
+ Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modifica-
+ tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. The end-user documentation included with the redistribution, if any, must
+ include the following acknowledgment: "This product includes software
+ developed by the Apache Software Foundation (http://www.apache.org/)."
+ Alternately, this acknowledgment may appear in the software itself, if
+ and wherever such third-party acknowledgments normally appear.
+
+ 4. The names "Jakarta", "Apache Directory Project", "Apache Eve" and
+ "Apache Software Foundation" must not be used to endorse or promote
+ products derived from this software without prior written
+ permission. For written permission, please contact apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. For more information on the
+ Apache Software Foundation, please see <http://www.apache.org/>.
+
+*/
+package org.apache.eve.listener ;
+
+
+import java.util.EventObject;
+import java.util.Set ;
+import java.util.HashSet ;
+import java.util.Iterator ;
+import java.io.IOException ;
+import java.net.InetSocketAddress ;
+
+import java.nio.channels.Selector ;
+import java.nio.channels.SelectionKey ;
+import java.nio.channels.SocketChannel ;
+import java.nio.channels.ServerSocketChannel ;
+
+import org.apache.avalon.framework.activity.Startable ;
+import org.apache.avalon.framework.activity.Initializable ;
+import org.apache.avalon.framework.logger.AbstractLogEnabled ;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.Serviceable ;
+
+import org.apache.eve.event.DisconnectSubscriber;
+import org.apache.eve.event.EventRouter ;
+import org.apache.eve.event.ConnectEvent ;
+import org.apache.eve.event.DisconnectEvent ;
+
+
+/**
+ * A listener manager that uses non-blocking NIO based constructs to detect
+ * client connections on server socket listeners.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author$
+ * @version $Revision$
+ */
+public class NonBlockingListenerManager extends AbstractLogEnabled
+ implements
+ DisconnectSubscriber,
+ ListenerManager,
+ Initializable,
+ Serviceable,
+ Startable,
+ Runnable
+{
+ /** the thread driving this Runnable */
+ private Thread m_thread = null ;
+ /** parameter used to politely stop running thread */
+ private Boolean m_hasStarted = null ;
+ /** event manager used to decouple source to sink relationships */
+ private EventRouter m_router ;
+ /** selector used to select a acceptable socket channel */
+ private Selector m_selector = null ;
+ /** the client keys for accepted connections */
+ private Set m_clients = new HashSet() ;
+
+
+ /**
+ * @see org.apache.eve.listener.ListenerManager#register(org.apache.eve.
+ * listener.ServerListener)
+ */
+ public void register( ServerListener a_listener ) throws IOException
+ {
+ ServerSocketChannel l_channel = ServerSocketChannel.open() ;
+ InetSocketAddress l_address = new InetSocketAddress(
+ a_listener.getAddress(),
+ a_listener.getPort() ) ;
+ l_channel.socket().bind( l_address, a_listener.getBacklog() ) ;
+ l_channel.configureBlocking( false ) ;
+ l_channel.register( m_selector, SelectionKey.OP_ACCEPT, a_listener ) ;
+ }
+
+
+ /**
+ * @see org.apache.eve.listener.ListenerManager#unregister(org.apache.eve.
+ * listener.ServerListener)
+ */
+ public void unregister( ServerListener a_listener ) throws IOException
+ {
+ SelectionKey l_key = null ;
+ Iterator l_keys = m_selector.keys().iterator() ;
+
+ while ( l_keys.hasNext() )
+ {
+ l_key = ( SelectionKey ) l_keys.next() ;
+ if ( l_key.attachment().equals( a_listener ) )
+ {
+ break ;
+ }
+ }
+
+ l_key.channel().close() ;
+ l_key.cancel() ;
+ }
+
+
+ // ------------------------------------------------------------------------
+ // DisconnectSubscriber Implementation
+ // ------------------------------------------------------------------------
+
+
+ /**
+ * Disconnects a client by removing the clientKey from the listener.
+ *
+ * @param an_event the disconnect event
+ */
+ public void inform( DisconnectEvent an_event )
+ {
+ m_clients.remove( an_event.getClientKey() ) ;
+
+ try
+ {
+ an_event.getClientKey().expire() ;
+ }
+ catch ( IOException e )
+ {
+ getLogger().error( "Could not properly expire client & close", e ) ;
+ }
+ }
+
+
+ public void inform( EventObject an_event )
+ {
+ inform( ( DisconnectEvent ) an_event ) ;
+ }
+
+
+ // ------------------------------------------------------------------------
+ // Runnable Implementation
+ // ------------------------------------------------------------------------
+
+
+ /**
+ * @see java.lang.Runnable#run()
+ */
+ public void run()
+ {
+ while ( m_hasStarted.booleanValue() )
+ {
+ int l_count = 0 ;
+
+ try
+ {
+ if ( 0 == ( l_count = m_selector.select( 100 ) ) )
+ {
+ continue ;
+ }
+ }
+ catch( IOException e )
+ {
+ getLogger().error( "Failure on select()", e ) ;
+ continue ;
+ }
+
+
+ Iterator l_list = m_selector.selectedKeys().iterator() ;
+ while ( l_list.hasNext() )
+ {
+ SelectionKey l_key = ( SelectionKey ) l_list.next() ;
+
+ if ( l_key.isAcceptable() )
+ {
+ SocketChannel l_channel = null ;
+ ServerSocketChannel l_server = ( ServerSocketChannel )
+ l_key.channel() ;
+
+ try
+ {
+ l_channel = l_server.accept() ;
+ }
+ catch ( IOException e )
+ {
+ getLogger().error( "Failure on accept()", e ) ;
+ continue ;
+ }
+
+ ClientKey l_clientKey =
+ new ClientKey( l_channel.socket() ) ;
+ ConnectEvent l_event =
+ new ConnectEvent( this, l_clientKey ) ;
+ m_router.publish( l_event ) ;
+ }
+ }
+ }
+ }
+
+
+ // ------------------------------------------------------------------------
+ // Life Cycle Methods
+ // ------------------------------------------------------------------------
+
+
+ /**
+ * Starts up this module.
+ *
+ * @see org.apache.avalon.framework.activity.Startable#start()
+ */
+ public void start() throws Exception
+ {
+ synchronized( m_hasStarted )
+ {
+ if ( m_hasStarted.booleanValue() )
+ {
+ throw new IllegalStateException( "Already started!" ) ;
+ }
+
+ m_hasStarted = new Boolean( true ) ;
+ m_thread = new Thread( this ) ;
+ m_thread.start() ;
+ }
+ }
+
+
+ /**
+ * Blocks calling thread until this module gracefully stops.
+ *
+ * @see org.apache.avalon.framework.activity.Startable#stop()
+ */
+ public void stop() throws Exception
+ {
+ synchronized( m_hasStarted )
+ {
+ m_hasStarted = new Boolean( false ) ;
+
+ while ( m_thread.isAlive() )
+ {
+ Thread.sleep( 100 ) ;
+ }
+ }
+ }
+
+
+ /**
+ * @avalon.dependency type="org.apache.eve.EventRouter"
+ * key="event-router" version="1.0"
+ * @see org.apache.avalon.framework.service.Serviceable#service(
+ * org.apache.avalon.framework.service.ServiceManager)
+ */
+ public void service( ServiceManager a_manager )
+ throws ServiceException
+ {
+ m_router = ( EventRouter ) a_manager.lookup( "event-router" ) ;
+ }
+
+
+ /**
+ * @see org.apache.avalon.framework.activity.Initializable#initialize()
+ */
+ public void initialize() throws Exception
+ {
+ m_hasStarted = new Boolean( false ) ;
+ m_selector = Selector.open() ;
+ m_router.subscribe( DisconnectEvent.class, null, this ) ;
+ }
+}
Added: incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/eve/listener/ListenerManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/eve/listener/ListenerManager.java Fri Dec 5 22:12:30 2003
@@ -0,0 +1,82 @@
+/*
+
+ ============================================================================
+ The Apache Software License, Version 1.1
+ ============================================================================
+
+ Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modifica-
+ tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. The end-user documentation included with the redistribution, if any, must
+ include the following acknowledgment: "This product includes software
+ developed by the Apache Software Foundation (http://www.apache.org/)."
+ Alternately, this acknowledgment may appear in the software itself, if
+ and wherever such third-party acknowledgments normally appear.
+
+ 4. The names "Eve Directory Server", "Apache Directory Project", "Apache Eve"
+ and "Apache Software Foundation" must not be used to endorse or promote
+ products derived from this software without prior written
+ permission. For written permission, please contact apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. For more information on the
+ Apache Software Foundation, please see <http://www.apache.org/>.
+
+*/
+package org.apache.eve.listener ;
+
+
+import java.io.IOException ;
+
+import org.apache.eve.event.DisconnectSubscriber ;
+
+
+/**
+ * Manages a set of server listeners.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author$
+ * @version $Revision$
+ */
+public interface ListenerManager extends DisconnectSubscriber
+{
+ /**
+ * Registers a server listener.
+ *
+ * @param a_listener the listener to register
+ * @throws IOException if there is a problem binding a listener
+ */
+ public void register( ServerListener a_listener ) throws IOException ;
+
+ /**
+ * Unregisters a server listener.
+ *
+ * @param a_listener the listener to unregister
+ * @throws IOException if there is a problem binding a listener
+ */
+ public void unregister( ServerListener a_listener ) throws IOException ;
+}
Added: incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/eve/listener/ServerListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/eve/frontend/listener/spi/src/java/org/apache/eve/listener/ServerListener.java Fri Dec 5 22:12:30 2003
@@ -0,0 +1,91 @@
+/*
+
+ ============================================================================
+ The Apache Software License, Version 1.1
+ ============================================================================
+
+ Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modifica-
+ tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. The end-user documentation included with the redistribution, if any, must
+ include the following acknowledgment: "This product includes software
+ developed by the Apache Software Foundation (http://www.apache.org/)."
+ Alternately, this acknowledgment may appear in the software itself, if
+ and wherever such third-party acknowledgments normally appear.
+
+ 4. The names "Eve Directory Server", "Apache Directory Project", "Apache Eve"
+ and "Apache Software Foundation" must not be used to endorse or promote
+ products derived from this software without prior written
+ permission. For written permission, please contact apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. For more information on the
+ Apache Software Foundation, please see <http://www.apache.org/>.
+
+*/
+package org.apache.eve.listener ;
+
+
+
+/**
+ * A server listener specification interface.
+ */
+public interface ServerListener
+{
+ /** role of this service interface */
+ public static final String ROLE = ServerListener.class.getName() ;
+
+ /**
+ * Gets the server socket backlog for this ServerListener
+ *
+ * @return client connection backlog
+ */
+ public int getBacklog() ;
+
+ /**
+ * Gets the TCP port number this ServerListener listens on.
+ *
+ * @return the tcp port number
+ */
+ public int getPort() ;
+
+ /**
+ * Gets the ip interface address this ServerListener listens on.
+ *
+ * @return the ip address octets as a String i.e. 127.0.0.1
+ */
+ public String getAddress() ;
+
+ /**
+ * Gets the LDAP URL for this ServerListener using the specified ip address
+ * and the tcp port number listened to. The ipaddress is resolved to a host
+ * name.
+ *
+ * @return the LDAP URL like so ldap://localhost:389
+ */
+ public String getURL() ;
+}