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.
*/
/**
* Implementation of COSEventChannelAdmin interface; ProxyPullConsumer.
* This defines connect_pull_supplier() and disconnect_pull_consumer().
*
* 2002/23/08 JFC OMG EventService Specification 1.1 page 2-7 states:
* "Registration is a two step process. An event-generating application
* first obtains a proxy consumer from a channel, then 'connects' to the
* proxy consumer by providing it with a supplier. ... The reason for
* the two step registration process..."
* Modifications to support the above have been made as well as to support
* section 2.1.5 "Disconnection Behavior" on page 2-4.
*
* @author Jeff Carlson
* @author Joerg v. Frantzius
* @author Rainer Lischetzki
* @author Gerald Brose
*/
public class ProxyPullConsumerImpl
extends org.omg.CosEventChannelAdmin.ProxyPullConsumerPOA
implements Runnable
{
private EventChannelImpl myEventChannel;
private org.omg.CosEventComm.PullSupplier myPullSupplier;
private org.omg.PortableServer.POA myPoa = null;
private boolean connected = false;
/**
* Constructor - gets called by the EventChannel
*/
protected ProxyPullConsumerImpl ( EventChannelImpl ec,
org.omg.CORBA.ORB orb,
org.omg.PortableServer.POA poa )
{
myEventChannel = ec;
myPoa = poa;
connected = false;
_this_object( orb );
}
/**
* ProxyPullConsumer Interface:
* As stated by the EventService specification 1.1 section 2.3.6:
* "If a <b>ProxyPullSupplier</b> is already connected to a <b>PullConsumer</b>,
* then the <b>AlreadyConnected</b> exception is raised."
* and
* "Implementations shall raise the CORBA standard <b>BAD_PARAM</b> exception if
* a nil object reference is passed to the <b>connect_pull_supplier</b> operation.
* and
* "An implementation of a <b>ProxyPullConsumer</b> may put additional
* requirements on the interface supported by the pull supplier. If t he pull
* supplier does not meet those requirements, the <b>ProxyPullConsumer</b>
* raises the <b>TypeError</b> exception. (See section 2.5.2 on page 2-15
* for an example)"
*/
public void connect_pull_supplier ( org.omg.CosEventComm.PullSupplier pullSupplier )
throws org.omg.CosEventChannelAdmin.AlreadyConnected,
org.omg.CosEventChannelAdmin.TypeError
{
if ( connected ) { throw new org.omg.CosEventChannelAdmin.AlreadyConnected(); }
if ( pullSupplier == null ) { throw new org.omg.CORBA.BAD_PARAM(); }
myPullSupplier = pullSupplier;
connected = true;
new Thread(this).start();
}
/**
* See EventService v 1.1 specification section 2.1.4.
* 'disconnect_pull_consumer terminates the event communication; it releases
* resources used at the consumer to support event communication. Calling
* this causes the implementation to call disconnect_pull_supplier operation
* on the corresponding PullSupplier interface (if that iterface is known).'
* See EventService v 1.1 specification section 2.1.5. This method should
* adhere to the spec as it a) causes a call to the corresponding disconnect
* on the connected supplier, b) 'If a consumer or supplier has received a
* disconnect call and subsequently receives another disconnect call, it
* shall raise a CORBA::OBJECT_NOT_EXIST exception.
*/
public void disconnect_pull_consumer()
{
if ( connected )
{
if ( myPullSupplier != null )
{
myPullSupplier.disconnect_pull_supplier();
myPullSupplier = null;
}
connected = false;
}
else
{
throw new org.omg.CORBA.OBJECT_NOT_EXIST();
}
}
/**
* Start being a good PullConsumer and ask for loads of events.
*/
public void run()
{
org.omg.CORBA.BooleanHolder hasEvent = new org.omg.CORBA.BooleanHolder();
org.omg.CORBA.Any event = null;
while( connected )
{
synchronized(this)
{
try
{
event = myPullSupplier.try_pull( hasEvent );
}
catch( org.omg.CORBA.UserException userEx )
{
connected = false;
// userEx.printStackTrace();
return;
}
catch( org.omg.CORBA.SystemException sysEx )
{
connected = false;
// sysEx.printStackTrace();
return;
}
if ( hasEvent.value )
{
myEventChannel.push_event( event );
}
// Let other threads get some time on the CPU in case we're
// in a cooperative environment.
Thread.yield();
}
}
}
/**
* 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;
}
}