package org.jacorb.notification.servant;
/*
* 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.ArrayList;
import java.util.List;
import org.jacorb.config.*;
import org.jacorb.notification.EventTypeWrapper;
import org.jacorb.notification.MessageFactory;
import org.jacorb.notification.OfferManager;
import org.jacorb.notification.SubscriptionManager;
import org.jacorb.notification.conf.Default;
import org.jacorb.notification.engine.TaskProcessor;
import org.jacorb.notification.interfaces.FilterStage;
import org.jacorb.notification.interfaces.Message;
import org.jacorb.notification.interfaces.MessageConsumer;
import org.jacorb.notification.interfaces.MessageSupplier;
import org.jacorb.notification.util.PropertySet;
import org.jacorb.notification.util.PropertySetAdapter;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.ORB;
import org.omg.CosNotification.EventType;
import org.omg.CosNotification.Priority;
import org.omg.CosNotification.StartTimeSupported;
import org.omg.CosNotification.StopTimeSupported;
import org.omg.CosNotification.StructuredEvent;
import org.omg.CosNotification.Timeout;
import org.omg.CosNotifyChannelAdmin.ObtainInfoMode;
import org.omg.CosNotifyChannelAdmin.SupplierAdmin;
import org.omg.CosNotifyComm.InvalidEventType;
import org.omg.CosNotifyComm.NotifyPublishOperations;
import org.omg.CosNotifyComm.NotifySubscribe;
import org.omg.CosNotifyComm.NotifySubscribeHelper;
import org.omg.CosNotifyComm.NotifySubscribeOperations;
import org.omg.PortableServer.POA;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @jmx.mbean extends = "AbstractProxyMBean"
* @jboss.xmbean
*
* @author Alphonse Bendt
*/
public abstract class AbstractProxyConsumer extends AbstractProxy implements IProxyConsumer,
NotifyPublishOperations, AbstractProxyConsumerMBean
{
private final static EventType[] EMPTY_EVENT_TYPE_ARRAY = new EventType[0];
// //////////////////////////////////////
private final MessageFactory messageFactory_;
// TODO check StartTime, StopTime, TimeOut: naming and usage is inconsistent.
private final AtomicBoolean isStartTimeSupported_ = new AtomicBoolean(true);
private final AtomicBoolean isStopTimeSupported_ = new AtomicBoolean(true);
private List subsequentDestinations_;
private NotifySubscribeOperations proxySubscriptionListener_;
private NotifySubscribe subscriptionListener_;
protected final SupplierAdmin supplierAdmin_;
private int messageCounter_ = 0;
// //////////////////////////////////////
protected AbstractProxyConsumer(IAdmin admin, ORB orb, POA poa, Configuration conf,
TaskProcessor taskProcessor, MessageFactory messageFactory,
SupplierAdmin supplierAdmin, OfferManager offerManager,
SubscriptionManager subscriptionManager)
{
super(admin, orb, poa, conf, taskProcessor, offerManager, subscriptionManager);
supplierAdmin_ = supplierAdmin;
messageFactory_ = messageFactory;
configureStartTimeSupported();
configureStopTimeSupported();
qosSettings_.addPropertySetListener(new String[] { Priority.value, Timeout.value,
StartTimeSupported.value, StopTimeSupported.value }, reconfigureQoS_);
}
protected MessageFactory getMessageFactory()
{
return messageFactory_;
}
public final List getSubsequentFilterStages()
{
return subsequentDestinations_;
}
public void setSubsequentDestinations(List list)
{
subsequentDestinations_ = list;
}
private PropertySetAdapter reconfigureQoS_ = new PropertySetAdapter()
{
public void actionPropertySetChanged(PropertySet source)
{
configureStartTimeSupported();
configureStopTimeSupported();
}
};
private void configureStartTimeSupported()
{
try
{
isStartTimeSupported_.set(qosSettings_.get(StartTimeSupported.value).extract_boolean());
} catch (Exception e)
{
isStartTimeSupported_.set(Default.DEFAULT_START_TIME_SUPPORTED.equals("on"));
}
if (logger_.isInfoEnabled())
{
logger_.info("set QoS: StartTimeSupported=" + isStartTimeSupported_);
}
}
private void configureStopTimeSupported()
{
logger_.debug("QoSSettings: " + qosSettings_);
try
{
isStopTimeSupported_.set(qosSettings_.get(StopTimeSupported.value).extract_boolean());
} catch (Exception e)
{
isStopTimeSupported_.set(Default.DEFAULT_STOP_TIME_SUPPORTED.equals("on"));
}
if (logger_.isInfoEnabled())
{
logger_.info("set QoS: StopTimeSupported=" + isStopTimeSupported_);
}
}
protected void schedulePullTask(MessageSupplier target)
{
getTaskProcessor().scheduleTimedPullTask(target);
}
/**
* check if a Message is acceptable to the QoS Settings of this ProxyConsumer
*/
protected void checkMessageProperties(Message m)
{
// No Op
// TODO implement
}
public FilterStage getFirstStage()
{
return this;
}
/**
* @jmx.managed-attribute description = "Does this ProxyConsumer support the per Message Option TimeOut"
* access = "read-only"
*/
public boolean getStopTimeSupported()
{
return isStopTimeSupported_.get();
}
/**
* @jmx.managed-attribute description = "Does this ProxyConsumer support the per Message Option StartTime"
* access = "read-only"
*/
public boolean getStartTimeSupported()
{
return isStartTimeSupported_.get();
}
public final SupplierAdmin MyAdmin()
{
return supplierAdmin_;
}
public final MessageConsumer getMessageConsumer()
{
throw new UnsupportedOperationException();
}
public final boolean hasMessageConsumer()
{
return false;
}
public void offer_change(EventType[] added, EventType[] removed) throws InvalidEventType
{
offerManager_.offer_change(added, removed);
}
public final EventType[] obtain_subscription_types(ObtainInfoMode obtainInfoMode)
{
final EventType[] _subscriptionTypes;
switch (obtainInfoMode.value()) {
case ObtainInfoMode._ALL_NOW_UPDATES_ON:
// attach the listener first, then return the current
// subscription types. order is important so that no
// updates are lost.
registerListener();
_subscriptionTypes = subscriptionManager_.obtain_subscription_types();
break;
case ObtainInfoMode._ALL_NOW_UPDATES_OFF:
_subscriptionTypes = subscriptionManager_.obtain_subscription_types();
removeListener();
break;
case ObtainInfoMode._NONE_NOW_UPDATES_ON:
_subscriptionTypes = EMPTY_EVENT_TYPE_ARRAY;
registerListener();
break;
case ObtainInfoMode._NONE_NOW_UPDATES_OFF:
_subscriptionTypes = EMPTY_EVENT_TYPE_ARRAY;
removeListener();
break;
default:
throw new IllegalArgumentException("Illegal ObtainInfoMode: ObtainInfoMode."
+ obtainInfoMode.value());
}
return _subscriptionTypes;
}
private void registerListener()
{
if (proxySubscriptionListener_ == null)
{
final NotifySubscribeOperations _listener = getSubscriptionListener();
if (_listener != null)
{
proxySubscriptionListener_ = new NotifySubscribeOperations()
{
public void subscription_change(EventType[] added, EventType[] removed)
{
try
{
_listener.subscription_change(added, removed);
} catch (NO_IMPLEMENT e)
{
logger_.info("disable subscription_change for Supplier", e);
removeListener();
} catch (InvalidEventType e)
{
if (logger_.isDebugEnabled())
{
logger_.debug("subscription_change("
+ EventTypeWrapper.toString(added) + ", "
+ EventTypeWrapper.toString(removed) + ") failed", e);
}
else
{
logger_.error("invalid event type", e);
}
} catch (Exception e)
{
logger_.error("subscription change failed", e);
}
}
};
subscriptionManager_.addListener(proxySubscriptionListener_);
}
}
}
/**
* removes the listener. subscription_change will no more be issued to the connected Supplier
*/
protected void removeListener()
{
if (proxySubscriptionListener_ != null)
{
subscriptionManager_.removeListener(proxySubscriptionListener_);
proxySubscriptionListener_ = null;
}
}
protected final void clientDisconnected()
{
subscriptionListener_ = null;
}
protected void connectClient(org.omg.CORBA.Object client)
{
super.connectClient(client);
try
{
subscriptionListener_ = NotifySubscribeHelper.narrow(client);
logger_.debug("successfully narrowed connecting Supplier to NotifySubscribe");
} catch (Exception e)
{
logger_.info("connecting Supplier does not support subscription_change");
}
}
final NotifySubscribeOperations getSubscriptionListener()
{
return subscriptionListener_;
}
protected void processMessage(Message mesg)
{
getTaskProcessor().processMessage(mesg);
messageCounter_++;
}
/**
* @jmx.managed-attribute description = "Total number of Messages received by this ProxyConsumer"
* access = "read-only"
*/
public final int getMessageCount()
{
return messageCounter_;
}
protected Message[] newMessages(StructuredEvent[] events)
{
final List _result = new ArrayList(events.length);
final MessageFactory _messageFactory = getMessageFactory();
for (int i = 0; i < events.length; ++i)
{
final Message _newMessage = _messageFactory.newMessage(events[i], this);
checkMessageProperties(_newMessage);
_result.add(_newMessage);
}
return (Message[]) _result.toArray(new Message[_result.size()]);
}
}