package org.jacorb.events;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 1997-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import java.util.Enumeration;
import java.util.Vector;
import org.omg.CORBA.TCKind;
import org.omg.CosEventChannelAdmin.ConsumerAdmin;
import org.omg.CosEventChannelAdmin.ConsumerAdminHelper;
import org.omg.CosEventChannelAdmin.ProxyPullConsumer;
import org.omg.CosEventChannelAdmin.ProxyPullSupplier;
import org.omg.CosEventChannelAdmin.ProxyPushConsumer;
import org.omg.CosEventChannelAdmin.ProxyPushSupplier;
import org.omg.CosEventChannelAdmin.SupplierAdmin;
import org.omg.CosEventChannelAdmin.SupplierAdminHelper;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
/**
* Simple implementation of the event channel spec.
* The event channel acts as a factory for proxy push/pull consumers/suppliers
* and interacts with the implementation objects locally, i.e. using Java
* references only.
*
* @author Joerg v. Frantzius, Rainer Lischetzki, Gerald Brose, Jeff Carlson
*/
public class EventChannelImpl extends JacORBEventChannelPOA
{
private Vector pullSuppliers = new Vector();
private Vector pullConsumers = new Vector();
private Vector pushSuppliers = new Vector();
private Vector pushConsumers = new Vector();
private Vector pendingEvents = new Vector();
private org.omg.CORBA.Any nullAny = null;
private org.omg.CORBA.ORB myOrb = null;
private org.omg.PortableServer.POA myPoa = null;
/**
* EventChannel constructor.
*/
public EventChannelImpl(org.omg.CORBA.ORB orb, org.omg.PortableServer.POA poa)
{
myOrb = orb;
myPoa = poa;
_this_object(myOrb);
nullAny = myOrb.create_any();
nullAny.type(myOrb.get_primitive_tc( TCKind.tk_null));
try
{
this.myPoa = poa;
myPoa.the_POAManager().activate();
}
catch( Exception e )
{
e.printStackTrace();
}
}
/**
* send the ConsumerAdmin vectors off for destrcution.
*/
private void consumerAdminDestroy()
{
releaseList( pullSuppliers );
releaseList( pushSuppliers );
}
/**
* send the SupplierAdmin vectors off for destrcution.
*/
private void supplierAdminDestroy()
{
releaseList( pullConsumers );
releaseList( pushConsumers );
}
/**
* Iteratre a list and send the servant off to be destroyed.
*/
private void releaseList( Vector list )
{
for ( Enumeration e = list.elements(); e.hasMoreElements(); )
{
org.omg.PortableServer.Servant servant =
(org.omg.PortableServer.Servant)e.nextElement();
releaseServant( servant );
}
}
/**
* Destroy / deactivate the servant.
*/
private void releaseServant( org.omg.PortableServer.Servant servant )
{
try
{
servant._poa().deactivate_object( servant._object_id() );
}
catch (org.omg.PortableServer.POAPackage.WrongPolicy wpEx)
{
wpEx.printStackTrace();
}
catch (org.omg.PortableServer.POAPackage.ObjectNotActive onaEx)
{
onaEx.printStackTrace();
}
}
/**
* Destroy all objects which are managed by the POA.
*/
public void destroy()
{
consumerAdminDestroy();
supplierAdminDestroy();
releaseServant(this);
}
/**
* Return the consumerAdmin interface
*/
public ConsumerAdmin for_consumers()
{
try
{
return ConsumerAdminHelper.narrow(myPoa.servant_to_reference(this));
}
catch( Exception e )
{
e.printStackTrace();
return null;
}
}
/**
* Return the supplierAdmin interface
*/
public SupplierAdmin for_suppliers()
{
try
{
return SupplierAdminHelper.narrow(myPoa.servant_to_reference(this));
}
catch( Exception e )
{
e.printStackTrace();
return null;
}
}
/**
* Return a ProxyPullConsumer reference to be used to connect to a
* PullSupplier.
*/
public ProxyPullConsumer obtain_pull_consumer()
{
synchronized( pullConsumers )
{
ProxyPullConsumerImpl p = new ProxyPullConsumerImpl( this, _orb(), myPoa );
pullConsumers.addElement( p );
return p._this( myOrb );
}
}
/**
* Return a ProxyPullSupplier reference to be used to connect to a
* PullConsumer.
*/
public ProxyPullSupplier obtain_pull_supplier()
{
synchronized( pullSuppliers )
{
ProxyPullSupplierImpl p = new ProxyPullSupplierImpl ( this, _orb(), myPoa );
pullSuppliers.addElement( p );
return p._this( myOrb );
}
}
/**
* Return a ProxyPushConsumer reference to be used to connect to a
* PushSupplier.
*/
public ProxyPushConsumer obtain_push_consumer()
{
synchronized( pushConsumers )
{
ProxyPushConsumerImpl p = new ProxyPushConsumerImpl( this, _orb(), myPoa );
pushConsumers.addElement( p );
return p._this( myOrb );
}
}
/**
* Return a ProxyPushSupplier reference to be used to connect to a
* PushConsumer.
*/
public ProxyPushSupplier obtain_push_supplier()
{
synchronized( pushSuppliers )
{
ProxyPushSupplierImpl p = new ProxyPushSupplierImpl( this, _orb(), myPoa );
pushSuppliers.addElement( p );
return p._this( myOrb );
}
}
/**
* Send event to all registered consumers.
*/
protected void push_event( org.omg.CORBA.Any event )
{
ProxyPushSupplierImpl push = null;
ProxyPullSupplierImpl pull = null;
synchronized( pushSuppliers )
{
for(int i = (pushSuppliers.size() - 1); i >= 0; --i )
{
push = (ProxyPushSupplierImpl) pushSuppliers.elementAt( i );
try
{
push.push_to_consumer( event );
}
catch( org.omg.CORBA.COMM_FAILURE comm )
{
pushSuppliers.removeElementAt( i );
}
}
}
synchronized( pullSuppliers )
{
for (int i = (pullSuppliers.size() - 1); i >= 0; --i )
{
pull = (ProxyPullSupplierImpl)pullSuppliers.elementAt( i );
try
{
pull.push_to_supplier( event );
}
catch( org.omg.CORBA.COMM_FAILURE comm )
{
pullSuppliers.removeElementAt( i );
}
}
}
}
static public void main( String[] args )
{
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);
try
{
org.omg.PortableServer.POA poa =
org.omg.PortableServer.POAHelper.narrow(
orb.resolve_initial_references("RootPOA"));
EventChannelImpl channel = new EventChannelImpl(orb,poa);
poa.the_POAManager().activate();
org.omg.CORBA.Object o = poa.servant_to_reference(channel);
NamingContextExt nc =
NamingContextExtHelper.narrow(
orb.resolve_initial_references("NameService"));
String channelName = ( args.length > 0 ? args[0] : "Generic.channel" );
nc.bind(nc.to_name( channelName ), o);
orb.run();
}
catch( Exception e )
{
e.printStackTrace();
}
}
/**
* Override this method from the Servant baseclass. Fintan Bolton
* in his book "Pure CORBA" suggests that you override this method to
* avoid the risk that a servant object (like this one) could be
* activated by the <b>wrong</b> POA object.
*/
public org.omg.PortableServer.POA _default_POA()
{
return myPoa;
}
}