package org.jacorb.poa;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.jacorb.orb.Delegate;
import org.jacorb.orb.ORB;
import org.jacorb.orb.dsi.ServerRequest;
import org.jacorb.orb.giop.RequestInputStream;
import org.jacorb.orb.miop.MIOPListener;
import org.jacorb.orb.miop.MIOPProfile;
import org.jacorb.poa.AGM.TGTCWrapper;
import org.omg.CORBA.Policy;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.ETF.Factories;
import org.omg.ETF.Profile;
import org.omg.IOP.TAG_UIPMC;
import org.omg.PortableGroup.NotAGroupObject;
import org.omg.PortableGroup.TagGroupTaggedComponent;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAPackage.ObjectNotActive;
import org.omg.PortableServer.POAPackage.WrongAdapter;
import org.omg.PortableServer.POAPackage.WrongPolicy;
import org.omg.RTCORBA.ProtocolProperties;
import org.slf4j.Logger;
/**
* The Group Object Adapter.
*
* @author Alysson Neves Bessani
* @version 1.0
* @see org.jacorb.poa.POA
*/
public class GOA extends org.jacorb.poa.POA implements org.omg.PortableGroup.GOA
{
private static final long serialVersionUID = -806217810084253929L;
// Active Group Map
private AGM agm;
// Table for OIDs to port mappings
private Map<byte[], MIOPProfile> portTable;
private MIOPListener listener = null;
private Logger logger;
/**
* Creates a new instance of GOA
*
* @param orb
* @param name
* @param parent
* @param manager
* @param policies
*/
public GOA (ORB orb, String name, org.jacorb.poa.POA parent, POAManager manager,
Policy[] policies)
{
super (orb, name, parent, manager, policies);
Factories f = orb.getTransportManager ().getFactories (TAG_UIPMC.value);
logger = orb.getConfiguration ().getLogger("org.jacorb.poa");
if ( f != null)
{
listener = (MIOPListener)f.create_listener ((ProtocolProperties)null, 0, (short)0);
agm = new AGM();
portTable = new HashMap<byte[], MIOPProfile> ();
}
}
/**
* Removes a member servant from this group.
*
* @param ref the group ref
* @param oid the member servant oid
*
* @throws NotAGroupObject if ref is not a group reference
*/
public void disassociate_reference_with_id (org.omg.CORBA.Object ref, byte[] oid) throws NotAGroupObject
{
MIOPProfile profile = getMIOPProfile (ref);
removeGroupMember (profile, oid);
}
/**
* Add a member servant to this group
*
* @param ref the group ref
* @param oid the member servant oid
*
* @throws NotAGroupObject if ref is not a group reference
*/
public void associate_reference_with_id (org.omg.CORBA.Object ref, byte[] oid) throws NotAGroupObject
{
MIOPProfile profile = getMIOPProfile (ref);
addGroupMember (profile, oid);
}
/**
* Create an oid member for this group. It must be used to register a servant
* as member of the group with the activate_object_with_id() method.
*
* @param ref the group reference
* @return ths created oid already member of this group
*
* @throws NotAGroupObject if ref is not a group reference
*/
public byte[] create_id_for_reference (org.omg.CORBA.Object ref) throws NotAGroupObject
{
MIOPProfile profile = getMIOPProfile (ref);
// This method in POA is private, we must change
byte[] oid = generateObjectId ();
addGroupMember (profile, oid);
return oid;
}
/**
* Get the members of the group.
*
* @param ref the group ref
* @return the group members oid
*
* @throws NotAGroupObject if ref is not a group reference
*/
public byte[][] reference_to_ids (org.omg.CORBA.Object ref) throws NotAGroupObject
{
return agm.getMembersFromGroup (getMIOPProfile (ref).getTagGroup ());
}
/**
* Process the group request through the POA tree.
*
* @param tagGroup the target group logical identification
* @param request the request to be processed
*/
public void processGroupRequest (TagGroupTaggedComponent tagGroup, ServerRequest request)
{
// deliver the request for all members in this POA
byte[][] members = agm.getMembersFromGroup (tagGroup);
if (members.length > 0)
{
// get the ORB and the request buffer
ORB orb = getORB ();
byte[] buffer = request.getInputStream ().getBufferCopy ();
for (int i = 0; i < members.length; i++)
{
ServerRequest requestClone = new ServerRequest (orb, new RequestInputStream (orb, request.getConnection (),
buffer), request.getConnection ());
try
{
byte[] oid = members[i];
org.omg.CORBA.Object member = id_to_reference (oid);
Delegate delegate = (Delegate)((ObjectImpl)member)._get_delegate ();
requestClone.setObjectKey (delegate.getObjectKey ());
_invoke (requestClone);
}
catch (WrongAdapter ex)
{
logger.error ("Caught exception processing group request", ex);
}
catch (ObjectNotActive ex)
{
logger.error ("Caught exception processing group request", ex);
}
catch (WrongPolicy ex)
{
logger.error ("Caught exception processing group request", ex);
}
catch( org.omg.CORBA.SystemException ex)
{
logger.error ("Caught SystemException processing group request", ex);
}
catch( RuntimeException ex)
{
logger.error ("Caught unknown exception processing group request", ex);
}
}
}
// propagates the request to the children POAs
POA children[] = the_children ();
for (int i = 0; i < children.length; i++)
{
((GOA)children[i]).processGroupRequest (tagGroup, request);
}
}
/**
* Try to get the MIOP profile of an object reference.
*
* @param ref the group ref
* @return the MIOP profile of the ref
*
* @throws NotAGroupObject if the ref doesn't have a MIOP profile
*/
private MIOPProfile getMIOPProfile (org.omg.CORBA.Object ref) throws NotAGroupObject
{
Delegate delegate = (Delegate)((ObjectImpl)ref)._get_delegate ();
Profile profile = delegate.getParsedIOR ().getEffectiveProfile ();
if (profile instanceof MIOPProfile)
{
return (MIOPProfile)profile;
}
else
{
throw new NotAGroupObject (ref.toString ());
}
}
/**
* Add a member to this group.
*
* @param profile the group profile
* @param oid the member oid
*/
private final void addGroupMember (MIOPProfile profile, byte[] oid)
{
int nMembers = agm.addToGroup (profile.getTagGroup (), oid);
if ((nMembers == 1) && !listener.haveGroupConnection (profile.getUIPMCProfile ().the_port))
{
// if this guy is the first member of the group and there is a multicast listener
// port for that I will create it
listener.addGroupConnection (profile);
}
portTable.put (oid, profile);
}
/**
* Remove a member from this group.
*
* @param profile the group profile
* @param oid the member oid
*/
private final void removeGroupMember (MIOPProfile profile, byte[] oid)
{
if (agm.removeFromGroup (profile.getTagGroup (), oid) == 0)
{
// if this member was last in the group remove the group
// from multicast listener
listener.removeGroupConnection (profile.getUIPMCProfile ().the_port);
}
portTable.remove (oid);
}
/**
* This method is used only in deactivate_object method
* for group members deactivation
*
* @param oid the member oid
*/
void clearGroupRegistration (byte[] oid)
{
if (agm != null)
{
ArrayList<TGTCWrapper> groupsKeys = agm.getGroupsWithMember (oid);
for (int i = 0; i < groupsKeys.size(); i++)
{
if (agm.removeFromGroup (groupsKeys.get (i).tcgtc, oid) == 0)
{
// If this member was last in the group remove the group
// from the multicast listener
listener.removeGroupConnection (portTable.get (oid).getUIPMCProfile ().the_port);
}
}
}
}
}