RoutingKey.java

/*
** Module   : RoutingKey.java
** Abstract : contains routing information
**
** Copyright (c) 2005-2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
** 001 SIY 20050120 ADD   @19506 Created initial version.
** 002 SIY 20050211 ADD   @19773 Added copy-constructor and replacement for
**                               the standard object reading/writing methods.
** 003 SIY 20050315 CHG   @20390 Organized imports and other minor cleanups.
** 004 SIY 20050329 CHG   @20549 Fixed comments, added constant for shutdown()
**                               entry point.
** 005 NVS 20050418 CHG   @20766 Added new public method getSpecial for
**                               creating special routing keys.
** 006 NVS 20060210 CHG   @24509 Added another special system routing key:
**                               INTERRUPT_SESSION.
** 007 GES 20060801 CHG   @28289 Converted to Externalizable to improve
**                               efficiency because Serializable has unneeded
**                               processing (for versioning...) that is
**                               executed on "inflation".
** 008 ECF 20071112 CHG   @35888 Refactored net package. Renamed
**                               TERMINATE_SESSION to TERMINATE_REMOTE.
**                               Changed ID-related method names to match
**                               coding standards.
** 009 ES  20240619              Added another special system routing key:
**                               SERVER_INTERRUPT.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.net;

import java.io.*;

/**
 * RoutingKey holds all information related message routing, both external
 * routing (source and destination node addresses) and internal routing
 * (exported entry point IDs).
 * 
 * @author SIY
 */
public final class RoutingKey
implements Externalizable
{
   /** getRoutingKey() special entry point */
   public static final int GET_ROUTING_KEY = -1;

   /** authenticateRemote() special entry point */
   public static final int AUTHENTICATE_REMOTE = -2;

   /** terminateRemote() special entry point */
   public static final int TERMINATE_REMOTE = -3;

   /** shutdown() special entry point */
   public static final int SHUTDOWN_PACKAGE = -4;

   /** interruptSession() special entry point */
   public static final int INTERRUPT_SESSION = -5;
   
   /** serverInterrupt() special entry point */
   public static final int SERVER_INTERRUPT = -6;

   /** Security context ID */
   private int contextID;

   /** Destination node address */
   private int destination;

   /** Method group ID */
   private int groupID;

   /** Method in the group ID */
   private int methodID;

   /** Source node address */
   private int source;

   /**
    * Construct a default <code>RoutingKey</code> instance. By convention it
    * points to the getRoutingKey() special entry point (exported by
    * <code>Dispatcher</code>).
    */
   public RoutingKey()
   {
      this(GET_ROUTING_KEY);
   }

   /**
    * Construct a <code>RoutingKey</code> instance for special entry point.
    * 
    * @param    special
    *           This is an ID which will be assigned to groupID and methodID.
    */
   RoutingKey(int special)
   {
      this(special, special, 0, 0, 0);
   }

   /**
    * Construct an instance with specified groupID and methodID. This
    * constructor is used by <code>Dispatcher</code> for generation of valid
    * RoutingKey instances for exported entry points created by the
    * application (unlike special entry points which are created
    * artificially).
    * 
    * @param    groupID
    *           Method group ID.
    * @param    methodID
    *           Method ID.
    */
   RoutingKey(int groupID, int methodID)
   {
      this(groupID, methodID, 0, 0, 0);
   }

   /**
    * Construct a key from other routing key.
    * 
    * @param    other
    *           Instance which is used as a source.
    */
   RoutingKey(RoutingKey other)
   {
      if (other != null)
      {
         source      = other.source;
         destination = other.destination;
         groupID     = other.groupID;
         methodID    = other.methodID;
         contextID   = other.contextID;
      }
   }

   /**
    * Construct a complete instance. Used internally by other constructors.
    * 
    * @param    group
    *           Method group ID.
    * @param    method
    *           Method ID.
    * @param    context
    *           Security context ID.
    * @param    src
    *           Source node address.
    * @param    dst
    *           Destination node address.
    */
   private RoutingKey(int group, int method, int context, int src, int dst)
   {
      source      = src;
      destination = dst;
      groupID     = group;
      methodID    = method;
      contextID   = context;
   }

   /**
    * Creates a special routing key from "system" group.
    * 
    * @param    special
    *           This is an ID which will be assigned to groupID and methodID.
    *           Must be one of the following:
    *           <ul>
    *              <li>GET_ROUTING_KEY - equivalent of the default 
    *                  constructor;
    *              <li>SHUTDOWN_PACKAGE
    *           </ul>
    * 
    * @return   The newly created instance of RoutingKey or <code>null</code>
    *           if the parameter is invalid.
    */
   public static RoutingKey getSpecial(int special)
   {
      if (special != GET_ROUTING_KEY && special != SHUTDOWN_PACKAGE)
         return null;

      return new RoutingKey(special, special, 0, 0, 0);
   }

   /**
    * Compare two instances.
    * 
    * @param    obj
    *           An object to compare with.
    *
    * @return   <code>true</code> if the two keys are identical.
    */
   public boolean equals(Object obj)
   {
      if (this == obj)
         return true;

      if (obj instanceof RoutingKey)
      {
         RoutingKey key = (RoutingKey) obj;

         if (getGroupID() != key.getGroupID())
            return false;

         if (getMethodID() != key.getMethodID())
            return false;

         return true;
      }

      return false;
   }

   /**
    * Provide access to the destination node address.
    * 
    * @return   The destination node address.
    */
   public int getDestinationAddress()
   {
      return destination;
   }

   /**
    * Provide access to the source node address.
    * 
    * @return   The source node address.
    */
   public int getSourceAddress()
   {
      return source;
   }

   /**
    * Generate a hash code for use by HashMap.
    * 
    * @return   The hash code.
    */
   public int hashCode()
   {
      return ((groupID << 16) | methodID);
   }

   /**
    * Assign new destination node address.
    * 
    * @param    dst
    *           The destination node address.
    */
   public void setDestinationAddress(int dst)
   {
      destination = dst;
   }

   /**
    * Assign new source node address.
    * 
    * @param    src
    *           The source node address.
    */
   public void setSourceAddress(int src)
   {
      source = src;
   }

   /**
    * Replacement for the default object reading method. It is meant to be
    * be called by containing objects rather than by the J2SE infrastructure
    * but the standard signature and name are used.
    * 
    * @param    in
    *           Input source from which fields will be restored.
    * 
    * @throws   IOException
    *           In case of I/O errors.
    * @throws   ClassNotFoundException
    *           If the payload can't be instantiated.
    */
   public void readExternal(ObjectInput in)
   throws IOException,
          ClassNotFoundException
   {
      source      = in.readInt();
      destination = in.readInt();
      groupID     = in.readInt();
      methodID    = in.readInt();
      contextID   = in.readInt();
   }

   /**
    * Replacement for the default object writing method. It is meant to be
    * be called by containing objects rather than by the J2SE infrastructure
    * but the standard signature and name are used.
    * 
    * @param    out
    *           The output destination to which fields will be saved.
    *
    * @throws   IOException
    *           In case of I/O errors.
    */
   public void writeExternal(ObjectOutput out)
   throws IOException
   {
      out.writeInt(source);
      out.writeInt(destination);
      out.writeInt(groupID);
      out.writeInt(methodID);
      out.writeInt(contextID);
   }
   
   /**
    * Provide access to the security context ID.
    * 
    * @return   The security context ID.
    */
   int getContextID()
   {
      return contextID;
   }

   /**
    * Provide access to the method's group ID.
    * 
    * @return   The group ID.
    */
   int getGroupID()
   {
      return groupID;
   }

   /**
    * Provide access to the method ID.
    * 
    * @return   The method ID.
    */
   int getMethodID()
   {
      return methodID;
   }

   /**
    * Assign new security context ID
    * 
    * @param    contextID
    *           New security context ID.
    */
   void setContextID(int contextID)
   {
      this.contextID = contextID;
   }

   /**
    * Swap source and destination addresses. Convenient method when request
    * message instance is used to prepare an reply message.
    */
   void swapAddresses()
   {
      int tmp = source;

      source = destination;
      destination = tmp;
   }
}