Package jade.mtp.iiop

Source Code of jade.mtp.iiop.IIOPAddress$BigEndianCodec

/*****************************************************************
JADE - Java Agent DEvelopment Framework is a framework to develop
multi-agent systems in compliance with the FIPA specifications.
Copyright (C) 2000 CSELT S.p.A.

The updating of this file to JADE 2.0 has been partially supported by the IST-1999-10211 LEAP Project

GNU Lesser General Public License

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation,
version 2.1 of the License.

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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA  02111-1307, USA.
*****************************************************************/

package jade.mtp.iiop;


import java.io.*;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Date;
import java.util.Calendar;
import java.util.StringTokenizer;
import java.util.NoSuchElementException;

import org.omg.CORBA.*;
import org.omg.CosNaming.*;

import FIPA.*; // OMG IDL Stubs

import jade.core.AID;
import jade.core.Profile;

import jade.mtp.InChannel;
import jade.mtp.OutChannel;
import jade.mtp.MTP;
import jade.mtp.MTPException;
import jade.mtp.TransportAddress;
import jade.domain.FIPAAgentManagement.Envelope;
import jade.domain.FIPAAgentManagement.ReceivedObject;
import jade.domain.FIPAAgentManagement.Property;
//FIXME: if we add the method getSize() to all the slots whose value is a set
// (e.g. intendedReceiver, userdefProperties, ...) we can improve a lot
// performance in marshalling and unmarshalling.

/**
   Implementation of <code><b>fipa.mts.mtp.iiop.std</b></code>
   specification for delivering ACL messages over the OMG IIOP
   transport protocol.

   @author Giovanni Rimassa - Universita' di Parma
   @version $Date: 2008-10-09 14:04:02 +0200 (gio, 09 ott 2008) $ $Revision: 6051 $
*/
public class MessageTransportProtocol implements MTP {


  private static class MTSImpl extends FIPA._MTSImplBase {

    private final InChannel.Dispatcher dispatcher;

    public MTSImpl(InChannel.Dispatcher disp) {
      dispatcher = disp;
    }

    public void message(FipaMessage aFipaMessage) {
      FIPA.Envelope[] envelopes = aFipaMessage.messageEnvelopes;
      byte[] payload = aFipaMessage.messageBody;
     
      Envelope env = new Envelope();

      // Read all the envelopes sequentially, so that later slots
      // overwrite earlier ones.
      for(int e = 0; e < envelopes.length; e++) {
  FIPA.Envelope IDLenv = envelopes[e];

  // Read in the 'to' slot
  if(IDLenv.to.length > 0)
    env.clearAllTo();
  for(int i = 0; i < IDLenv.to.length; i++) {
    AID id = unmarshalAID(IDLenv.to[i]);
    env.addTo(id);
  }

  // Read in the 'from' slot
  if(IDLenv.from.length > 0) {
    AID id = unmarshalAID(IDLenv.from[0]);
    env.setFrom(id);
  }

  // Read in the 'intended-receiver' slot
  if(IDLenv.intendedReceiver.length > 0)
    env.clearAllIntendedReceiver();
  for(int i = 0; i < IDLenv.intendedReceiver.length; i++) {
    AID id = unmarshalAID(IDLenv.intendedReceiver[i]);
    env.addIntendedReceiver(id);
  }

  // Read in the 'encrypted' slot
  //if(IDLenv.encrypted.length > 0)
  //  env.clearAllEncrypted();
  //for(int i = 0; i < IDLenv.encrypted.length; i++) {
  //  String word = IDLenv.encrypted[i];
  //  env.addEncrypted(word);
  //}

  // Read in the other slots
  if(IDLenv.comments.length() > 0)
    env.setComments(IDLenv.comments);
  if(IDLenv.aclRepresentation.length() > 0)
    env.setAclRepresentation(IDLenv.aclRepresentation);
  if(IDLenv.payloadLength > 0)
    env.setPayloadLength(new Long(IDLenv.payloadLength));
  if(IDLenv.payloadEncoding.length() > 0)
    env.setPayloadEncoding(IDLenv.payloadEncoding);
  if(IDLenv.date.length > 0) {
    Date d = unmarshalDateTime(IDLenv.date[0]);
    env.setDate(d);
  }

  // Read in the 'received' stamp
  if(IDLenv.received.length > 0)
    env.addStamp(unmarshalReceivedObj(IDLenv.received[0]));

  // Read in the 'user-defined properties' slot
  if(IDLenv.userDefinedProperties.length > 0)
    env.clearAllProperties();
  for(int i = 0; i < IDLenv.userDefinedProperties.length; i++) {
    env.addProperties(unmarshalProperty(IDLenv.userDefinedProperties[i]));
  }
      }
     
      //String tmp = "\n\n"+(new  java.util.Date()).toString()+"   RECEIVED IIOP MESSAGE"+ "\n" + env.toString() + "\n" + new String(payload);
      //System.out.println(tmp);
  
      
      //MessageTransportProtocol.log(tmp); //Write in a log file for iiop incoming message
     
      // Dispatch the message
      dispatcher.dispatchMessage(env, payload);

    }


    private AID unmarshalAID(FIPA.AgentID id) {
      AID result = new AID();
      result.setName(id.name);
      for(int i = 0; i < id.addresses.length; i++)
  result.addAddresses(id.addresses[i]);
      for(int i = 0; i < id.resolvers.length; i++)
  result.addResolvers(unmarshalAID(id.resolvers[i]));
      return result;
    }

    private Date unmarshalDateTime(FIPA.DateTime d) {
      Date result = new Date();
      return result;
    }

    private Property unmarshalProperty(FIPA.Property p) {
      return new Property(p.keyword, p.value.extract_Value());
    }

    private ReceivedObject unmarshalReceivedObj(FIPA.ReceivedObject ro) {
      ReceivedObject result = new ReceivedObject();
      result.setBy(ro.by);
      result.setFrom(ro.from);
      result.setDate(unmarshalDateTime(ro.date));
      result.setId(ro.id);
      result.setVia(ro.via);
      return result;
    }

  } // End of MTSImpl class


  private static final String[] PROTOCOLS = new String[] { "IOR", "corbaloc", "corbaname" };

  private final ORB myORB;
  private MTSImpl server;
  private static PrintWriter logFile;
 
  public MessageTransportProtocol() {
    myORB = ORB.init(new String[0], null);
   
  }

  public TransportAddress activate(InChannel.Dispatcher disp, Profile p) throws MTPException {
    server = new MTSImpl(disp);
    myORB.connect(server);
    IIOPAddress iiop = new IIOPAddress(myORB, server);

    /* //Open log file
    String fileName = "iiop"+iiop.getHost()+iiop.getPort()+".log";
    try{
      logFile = new PrintWriter(new FileWriter(fileName,true));
    }catch(java.io.IOException e){e .printStackTrace();}
    */
    return iiop;
   
  }

  public void activate(InChannel.Dispatcher disp, TransportAddress ta, Profile p) throws MTPException {
      //    throw new MTPException("User supplied transport address not supported.");

      // Do not throw, but modify the supplied address instead.
      IIOPAddress iia = (IIOPAddress)ta;
      IIOPAddress generated = (IIOPAddress)activate(disp, p);
      iia.initFromIOR(generated.getIOR());
  }

  public void deactivate(TransportAddress ta) throws MTPException {
    myORB.disconnect(server);
  }

  public void deactivate() throws MTPException {
    myORB.disconnect(server);
  }

  public void deliver(String addr, Envelope env, byte[] payload) throws MTPException {
    try {
      TransportAddress ta = strToAddr(addr);
      IIOPAddress iiopAddr = (IIOPAddress)ta;
      FIPA.MTS objRef = iiopAddr.getObject();

      // verifies if the server object really exists (useful if the IOR is
      // valid, i.e corresponds to a good object) (e.g. old IOR)
      // FIXME. To check if this call slows down performance
      if (objRef._non_existent())
        throw new MTPException("Bad IIOP server object reference:" + objRef.toString());

      // Fill in the 'to' field of the IDL envelope
      Iterator itTo = env.getAllTo();
      List to = new ArrayList();
      while(itTo.hasNext()) {
  AID id = (AID)itTo.next();
  to.add(marshalAID(id));
      }

      FIPA.AgentID[] IDLto = new FIPA.AgentID[to.size()];
      for(int i = 0; i < to.size(); i++)
  IDLto[i] = (FIPA.AgentID)to.get(i);


      // Fill in the 'from' field of the IDL envelope
      AID from = env.getFrom();
      FIPA.AgentID[] IDLfrom = new FIPA.AgentID[] { marshalAID(from) };


      // Fill in the 'intended-receiver' field of the IDL envelope
      Iterator itIntendedReceiver = env.getAllIntendedReceiver();
      List intendedReceiver = new ArrayList();
      while(itIntendedReceiver.hasNext()) {
  AID id = (AID)itIntendedReceiver.next();
  intendedReceiver.add(marshalAID(id));
      }

      FIPA.AgentID[] IDLintendedReceiver = new FIPA.AgentID[intendedReceiver.size()];
      for(int i = 0; i < intendedReceiver.size(); i++)
  IDLintendedReceiver[i] = (FIPA.AgentID)intendedReceiver.get(i);


      // Fill in the 'encrypted' field of the IDL envelope
      //Iterator itEncrypted = env.getAllEncrypted();
      //List encrypted = new ArrayList();
      //while(itEncrypted.hasNext()) {
  //String word = (String)itEncrypted.next();
  //encrypted.add(word);
      //}

      String[] IDLencrypted = new String[0];
      //String[] IDLencrypted = new String[encrypted.size()];
      //for(int i = 0; i < encrypted.size(); i++)
  //IDLencrypted[i] = (String)encrypted.get(i);


      // Fill in the other fields of the IDL envelope ...
     
      String IDLcomments = (env.getComments() != null)?env.getComments():"";
      String IDLaclRepresentation = env.getAclRepresentation();
      Long payloadLength = env.getPayloadLength();
      int IDLpayloadLength = payloadLength.intValue();
      String IDLpayloadEncoding = (env.getPayloadEncoding() != null)?env.getPayloadEncoding():"";
      FIPA.DateTime[] IDLdate = new FIPA.DateTime[] { marshalDateTime(env.getDate()) };
      FIPA.Property[][] IDLtransportBehaviour = new FIPA.Property[][] { };

      // Fill in the 'userdefined-properties' field of the IDL envelope
      Iterator itUserDefProps = env.getAllProperties();
      List userDefProps = new ArrayList();
      while(itUserDefProps.hasNext()) {
  Property p = (Property)itUserDefProps.next();
  userDefProps.add(marshalProperty(p));
      }
      FIPA.Property[] IDLuserDefinedProperties = new FIPA.Property[userDefProps.size()];
      for(int i = 0; i < userDefProps.size(); i++)
  IDLuserDefinedProperties[i] = (FIPA.Property)userDefProps.get(i);

      // Fill in the list of 'received' stamps
      /* FIXME: Maybe several IDL Envelopes should be generated, one for every 'received' stamp...
      ReceivedObject[] received = env.getStamps();
      FIPA.ReceivedObject[] IDLreceived = new FIPA.ReceivedObject[received.length];
      for(int i = 0; i < received.length; i++)
  IDLreceived[i] = marshalReceivedObj(received[i]);
      */

      // FIXME: For now, only the current 'received' object is considered...
      ReceivedObject received = env.getReceived();
      FIPA.ReceivedObject[] IDLreceived;
      if(received != null)
  IDLreceived = new FIPA.ReceivedObject[] { marshalReceivedObj(received) };
      else
  IDLreceived = new FIPA.ReceivedObject[] { };

      FIPA.Envelope IDLenv = new FIPA.Envelope(IDLto,
                 IDLfrom,
                 IDLcomments,
                 IDLaclRepresentation,
                 IDLpayloadLength,
                 IDLpayloadEncoding,
                 IDLdate,
                 IDLencrypted,
                 IDLintendedReceiver,
                 IDLreceived,
                 IDLtransportBehaviour,
                 IDLuserDefinedProperties);

      FipaMessage msg = new FipaMessage(new FIPA.Envelope[] { IDLenv }, payload);

      //String tmp = "\n\n"+(new  java.util.Date()).toString()+"   SENT IIOP MESSAGE"+ "\n" + env.toString() + "\n" + new String(payload);
      //System.out.println(tmp);
 
  //MessageTransportProtocol.log(tmp); // write in a log file for sent iiop message
   
  objRef.message(msg);
    }
    catch(ClassCastException cce) {
      cce.printStackTrace();
      throw new MTPException("Address mismatch: this is not a valid IIOP address.");
    }
catch(Exception cce2) {
      cce2.printStackTrace();
      throw new MTPException("Address mismatch: this is not a valid IIOP address.");
    }

  }

  public TransportAddress strToAddr(String rep) throws MTPException {
    return new IIOPAddress(myORB, rep); // FIXME: Should cache object references
  }

  public String addrToStr(TransportAddress ta) throws MTPException {
    try {
      IIOPAddress addr = (IIOPAddress)ta;
      return addr.getIOR();
    }
    catch(ClassCastException cce) {
      throw new MTPException("Address mismatch: this is not a valid IIOP address.");
    }
  }

  public String getName() {
    return jade.domain.FIPANames.MTP.IIOP;
  }

  public String[] getSupportedProtocols() {
    return PROTOCOLS;
  }

  private FIPA.Property marshalProperty(jade.domain.FIPAAgentManagement.Property p) {
    org.omg.CORBA.Any value = myORB.create_any();
    java.lang.Object v = p.getValue();
    if (v instanceof java.io.Serializable) {
      value.insert_Value((Serializable) v);
    }
    else {
      if (v != null) {
        value.insert_Value(v.toString());
      }
    }
    return new FIPA.Property(p.getName(), value);
  }

  private FIPA.AgentID marshalAID(AID id) {
    String name = id.getName();
    String[] addresses = id.getAddressesArray();
    AID[] resolvers = id.getResolversArray();
    FIPA.Property[] userDefinedProperties = new FIPA.Property[] { };
    int numOfResolvers = resolvers.length;
    FIPA.AgentID result = new FIPA.AgentID(name, addresses, new AgentID[numOfResolvers], userDefinedProperties);
    for(int i = 0; i < numOfResolvers; i++) {
      result.resolvers[i] = marshalAID(resolvers[i]); // Recursively marshal all resolvers, which are, in turn, AIDs.
    }

    return result;

  }

  private FIPA.DateTime marshalDateTime(Date d) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(d);
    short year = (short)cal.get(Calendar.YEAR);
    short month = (short)cal.get(Calendar.MONTH);
    short day = (short)cal.get(Calendar.DAY_OF_MONTH);
    short hour = (short)cal.get(Calendar.HOUR_OF_DAY);
    short minutes = (short)cal.get(Calendar.MINUTE);
    short seconds = (short)cal.get(Calendar.SECOND);
    short milliseconds = 0; // FIXME: This is truncated to the second
    char typeDesignator = ' '; // FIXME: Uses local timezone ?
    FIPA.DateTime result = new FIPA.DateTime(year,
               month,
               day,
               hour,
               minutes,
               seconds,
               milliseconds,
               typeDesignator);
    return result;
  }

  private FIPA.ReceivedObject marshalReceivedObj(ReceivedObject ro) {
    FIPA.ReceivedObject result = new FIPA.ReceivedObject();
    result.by = ro.getBy();
    result.from = ro.getFrom();
    result.date = marshalDateTime(ro.getDate());
    result.id = ro.getId();
    result.via = ro.getVia();
    return result;
  }

//Method to write on a file the iiop message log file
/*public static synchronized void log(String str) {
  logFile.println(str); 
  logFile.flush();
    }*/

} // End of class MessageTransportProtocol

/**
This class represents an IIOP address.
Three syntaxes are allowed for an IIOP address (all case-insensitive):
<code>
IIOPAddress ::= "ior:" (HexDigit HexDigit+)
              | "corbaname://" NSHost ":" NSPort "/" NSObjectID "#" objectName
              | "corbaloc:" HostName ":" portNumber "/" objectID
</code>
Notice that, in the third case, BIG_ENDIAN is assumed by default. In the first and second case, instead, the endianess information is contained within the IOR definition.
**/
  class IIOPAddress implements TransportAddress {

    public static final byte BIG_ENDIAN = 0;
    public static final byte LITTLE_ENDIAN = 1;

    private static final String FIPA_2000_TYPE_ID = "IDL:FIPA/MTS:1.0";
    private static final String NS_TYPE_ID = "IDL:omg.org/CosNaming/NamingContext";
    private static final int TAG_INTERNET_IOP = 0;
    private static final byte IIOP_MAJOR = 1;
    private static final byte IIOP_MINOR = 0;

    private static final byte ASCII_PERCENT = getASCIIByte("%");
    private static final byte ASCII_UPPER_A = getASCIIByte("A");
    private static final byte ASCII_UPPER_Z = getASCIIByte("Z");
    private static final byte ASCII_LOWER_A = getASCIIByte("a");
    private static final byte ASCII_LOWER_Z = getASCIIByte("z");
    private static final byte ASCII_ZERO = getASCIIByte("0");
    private static final byte ASCII_NINE = getASCIIByte("9");

    private static final byte ASCII_MINUS = getASCIIByte("-");
    private static final byte ASCII_UNDERSCORE = getASCIIByte("_");
    private static final byte ASCII_DOT = getASCIIByte(".");
    private static final byte ASCII_BANG = getASCIIByte("!");
    private static final byte ASCII_TILDE = getASCIIByte("~");
    private static final byte ASCII_STAR = getASCIIByte("*");
    private static final byte ASCII_QUOTE = getASCIIByte("'");
    private static final byte ASCII_OPEN_BRACKET = getASCIIByte("(");
    private static final byte ASCII_CLOSED_BRACKET = getASCIIByte("$");

    private static final char[] HEX = {
      '0','1','2','3','4','5','6','7',
      '8','9','a','b','c','d','e','f'
    };

    private static final byte getASCIIByte(String ch) {
      try {
  return (ch.getBytes("US-ASCII"))[0];
      }
      catch(UnsupportedEncodingException uee) {
  return 0;
      }
    }


    private final ORB orb;

    private String ior;
    private String host;
    private short port;
    private String objectKey;
    private String anchor;

    private CDRCodec codecStrategy;

    public IIOPAddress(ORB anOrb, FIPA.MTS objRef) throws MTPException {
      this(anOrb, anOrb.object_to_string(objRef));
    }

    public IIOPAddress(ORB anOrb, String s) throws MTPException {
      orb = anOrb;
      if(s.toLowerCase().startsWith("ior:"))
  initFromIOR(s);
      else if(s.toLowerCase().startsWith("corbaloc:"))
  initFromURL(s, BIG_ENDIAN);
      else if(s.toLowerCase().startsWith("corbaname:"))
  initFromNS(s);
      else
  throw new MTPException("Invalid string prefix");
    }

    void initFromIOR(String s) throws MTPException {
      parseIOR(s, FIPA_2000_TYPE_ID);
      anchor = "";
    }

    private void initFromURL(String s, short endianness) throws MTPException {

      // Remove 'corbaloc:' prefix to get URL host, port and file
      s = s.substring(9);

      if(s.toLowerCase().startsWith("iiop:")) {
  // Remove an explicit IIOP specification
  s = s.substring(5);
      }
      else if(s.startsWith(":")) {
  // Remove implicit IIOP specification
  s = s.substring(1);
      }
      else
  throw new MTPException("Invalid 'corbaloc' URL: neither 'iiop:' nor ':' was specified.");

      buildIOR(s, FIPA_2000_TYPE_ID, endianness);

    }

    private void initFromNS(String s) throws MTPException {
      // First perform a 'corbaloc::' resolution to get the IOR of the Naming Service.
      // Replace 'corbaname:' with 'corbaloc::'
      StringBuffer buf = new StringBuffer(s);

      // Use 'corbaloc' support to build a reference on the NamingContext
      // where the real object reference will be looked up.
      buf.replace(0, 11, "corbaloc::");
      buildIOR(s.substring(11), NS_TYPE_ID, BIG_ENDIAN);
      org.omg.CORBA.Object o = orb.string_to_object(ior);
      NamingContext ctx = NamingContextHelper.narrow(o);

      try {

  // Transform the string after the '#' sign into a COSNaming::Name.
  StringTokenizer lexer = new StringTokenizer(anchor, "/.", true);
  List name = new ArrayList();
  while(lexer.hasMoreTokens()) {
    String tok = lexer.nextToken();
    NameComponent nc = new NameComponent();
    nc.id = tok;
    name.add(nc);
    if(!lexer.hasMoreTokens())
      break; // Out of the while loop

    tok = lexer.nextToken();
    if(tok.equals(".")) { // An (id, kind) pair
      tok = lexer.nextToken();
      nc.kind = tok;
    }
    else if(!tok.equals("/")) // No separator other than '.' or '/' is allowed
      throw new MTPException("Ill-formed path into the Naming Service: Unknown separator.");
  }

  // Get the object reference stored into the naming service...
  NameComponent[] path = (NameComponent[])name.toArray(new NameComponent[name.size()]);
  o = ctx.resolve(path);

  // Stringify it and use the resulting IOR to initialize yourself
        String realIOR = orb.object_to_string(o);
  initFromIOR(realIOR);

      }
      catch(NoSuchElementException nsee) {
  throw new MTPException("Ill-formed path into the Naming Service.", nsee);
      }
      catch(UserException ue) {
  throw new MTPException("CORBA Naming Service user exception.", ue);
      }
      catch(SystemException se) {
  throw new MTPException("CORBA Naming Service system exception.", se);
      }
     

    }

    private void parseIOR(String s, String typeName) throws MTPException {
      try {
  // Store stringified IOR
  ior = s.toUpperCase();

  // Remove 'IOR:' prefix to get Hex digits
  String hexString = ior.substring(4);

  short endianness = Short.parseShort(hexString.substring(0, 2), 16);

  switch(endianness) {
  case BIG_ENDIAN:
    codecStrategy = new BigEndianCodec(hexString);
    break;
  case LITTLE_ENDIAN:
    codecStrategy = new LittleEndianCodec(hexString);
    break;
  default:
    throw new MTPException("Invalid endianness specifier");
  }

  try {
    // Read 'string type_id' field
    String typeID = codecStrategy.readString();
    if(!typeID.equalsIgnoreCase(typeName))
      throw new MTPException("Invalid type ID" + typeID);
  }
  catch (Exception e) { // all exceptions are converted into MTPException
    throw new MTPException("Invalid type ID");
  }

  // Read 'sequence<TaggedProfile> profiles' field
  // Read sequence length
  int seqLen = codecStrategy.readLong();
  for(int i = 0; i < seqLen; i++) {
    // Read 'ProfileId tag' field
    int tag = codecStrategy.readLong();
    byte[] profile = codecStrategy.readOctetSequence();
    if(tag == TAG_INTERNET_IOP) {
      // Process IIOP profile
      CDRCodec profileBodyCodec;
      switch(profile[0]) {
      case BIG_ENDIAN:
        profileBodyCodec = new BigEndianCodec(profile);
        break;
      case LITTLE_ENDIAN:
        profileBodyCodec = new LittleEndianCodec(profile);
        break;
      default:
        throw new MTPException("Invalid endianness specifier");
      }

      // Read IIOP version
      byte versionMajor = profileBodyCodec.readOctet();
      byte versionMinor = profileBodyCodec.readOctet();
      if(versionMajor != 1)
        throw new MTPException("IIOP version not supported");

      try {
        // Read 'string host' field
        host = profileBodyCodec.readString();
      }
      catch (Exception e) {
        throw new MTPException("Invalid host string");
      }

      // Read 'unsigned short port' field
      port = profileBodyCodec.readShort();

      // Read 'sequence<octet> object_key' field and convert it
      // into a String object
      byte[] keyBuffer = profileBodyCodec.readOctetSequence();
      ByteArrayOutputStream buf = new ByteArrayOutputStream();

      // Escape every forbidden character, as for RFC 2396 (URI: Generic Syntax)
      for(int ii = 0; ii < keyBuffer.length; ii++) {
        byte b = keyBuffer[ii];
        if(isUnreservedURIChar(b)) {
    // Write the character 'as is'
    buf.write(b);
        }
        else {
    // Escape it using '%'
    buf.write(ASCII_PERCENT);
    buf.write(HEX[(b & 0xF0) >> 4]); // High nibble
    buf.write(HEX[b & 0x0F]); // Low nibble
        }
      }

      objectKey = buf.toString("US-ASCII");
      codecStrategy = null;

    }
  }
      }
      catch (Exception e) { // all exceptions are converted into MTPException
  throw new MTPException(e.getMessage());
      }
    }

    private void buildIOR(String s, String typeName, short endianness) throws MTPException {
      int colonPos = s.indexOf(':');
      int slashPos = s.indexOf('/');
      int poundPos = s.indexOf('#');
      if((colonPos == -1) || (slashPos == -1))
  throw new MTPException("Invalid URL string");

      host = s.substring(0, colonPos);
      port = Short.parseShort(s.substring(colonPos + 1, slashPos));
      if(poundPos == -1) {
  objectKey = s.substring(slashPos + 1, s.length());
  anchor = "";
      }
      else {
  objectKey = s.substring(slashPos + 1, poundPos);
  anchor = s.substring(poundPos + 1, s.length());
      }

      switch(endianness) {
      case BIG_ENDIAN:
  codecStrategy = new BigEndianCodec(new byte[0]);
  break;
      case LITTLE_ENDIAN:
  codecStrategy = new LittleEndianCodec(new byte[0]);
  break;
      default:
  throw new MTPException("Invalid endianness specifier");
      }

      codecStrategy.writeString(typeName);

      // Write '1' as profiles sequence length
      codecStrategy.writeLong(1);

      codecStrategy.writeLong(TAG_INTERNET_IOP);
      CDRCodec profileBodyCodec;
      switch(endianness) {
      case BIG_ENDIAN:
  profileBodyCodec = new BigEndianCodec(new byte[0]);
  break;
      case LITTLE_ENDIAN:
  profileBodyCodec = new LittleEndianCodec(new byte[0]);
  break;
      default:
  throw new MTPException("Invalid endianness specifier");
      }

      // Write IIOP 1.0 profile to auxiliary CDR codec
      profileBodyCodec.writeOctet(IIOP_MAJOR);
      profileBodyCodec.writeOctet(IIOP_MINOR);
      profileBodyCodec.writeString(host);
      profileBodyCodec.writeShort(port);
      try {
  byte[] objKey = objectKey.getBytes("US-ASCII");

  // Remove all the RFC 2396 escape sequences...
  ByteArrayOutputStream buf = new ByteArrayOutputStream();
  for(int i = 0; i < objKey.length; i++) {
    byte b = objKey[i];
    if(b != ASCII_PERCENT)
      buf.write(b);
    else {
      // Get the hex value represented by the two bytes after '%'
      try {
        String hexPair = new String(objKey, i + 1, 2, "US-ASCII");
        short sh = Short.parseShort(hexPair, 16);
        if(sh > Byte.MAX_VALUE)
    b = (byte)(sh + 2*Byte.MIN_VALUE); // Conversion from unsigned to signed
        else
    b = (byte)sh;
      }
      catch(UnsupportedEncodingException uee) {
        b = 0;
      }
      buf.write(b);
      i += 2;
    }
  }

  profileBodyCodec.writeOctetSequence(buf.toByteArray());

  byte[] encapsulatedProfile = profileBodyCodec.writtenBytes();

  // Write encapsulated profile to main IOR codec
  codecStrategy.writeOctetSequence(encapsulatedProfile);

  String hexString = codecStrategy.writtenString();
  ior = "IOR:" + hexString;

  codecStrategy = null;

      }
      catch(UnsupportedEncodingException uee) {
  // It should never happen
  uee.printStackTrace();
      }

    }

    // This method returns true if and only if the supplied byte,
    // interpreted as an US-ASCII encoded character, corresponds to an
    // unreserved URI character. See RFC 2396 for details.
    private boolean isUnreservedURIChar(byte b) {
      // An upper case letter?
      if((ASCII_UPPER_A <= b)&&(ASCII_UPPER_Z >= b))
  return true;
      // A lower case letter?
      if((ASCII_LOWER_A <= b)&&(ASCII_LOWER_Z >= b))
  return true;
      // A decimal digit?
      if((ASCII_ZERO <= b)&&(ASCII_NINE >= b))
  return true;
      // An unreserved, but not alphanumeric character?
      if((b == ASCII_MINUS)||(b == ASCII_UNDERSCORE)||(b == ASCII_DOT)||(b == ASCII_BANG)||(b == ASCII_TILDE)||
   (b == ASCII_STAR)||(b == ASCII_QUOTE)||(b == ASCII_OPEN_BRACKET)||(b == ASCII_CLOSED_BRACKET))
  return true;

      // Anything else is not allowed
      return false;
    }

    public String getURL() {
      int portNum = port;
      if(portNum < 0)
  portNum += 65536;
      return "corbaloc::" + host + ":" + portNum + "/" + objectKey;
    }

    public String getIOR() {
      return ior;
    }

    public FIPA.MTS getObject() {
      return FIPA.MTSHelper.narrow(orb.string_to_object(ior));
    }

    private static abstract class CDRCodec {

      protected byte[] readBuffer;
      protected StringBuffer writeBuffer;
      protected int readIndex = 0;
      protected int writeIndex = 0;

      protected CDRCodec(String hexString) {
  // Put all Hex digits into a byte array
  readBuffer = bytesFromHexString(hexString);
  readIndex = 1;
  writeBuffer = new StringBuffer(255);
      }

      protected CDRCodec(byte[] hexDigits) {
  readBuffer = new byte[hexDigits.length];
  System.arraycopy(hexDigits, 0, readBuffer, 0, readBuffer.length);
  readIndex = 1;
  writeBuffer = new StringBuffer(255);
      }

      public String writtenString() {
  return new String(writeBuffer);
      }

      public byte[] writtenBytes() {
  return bytesFromHexString(new String(writeBuffer));
      }

      public byte readOctet() {
  return readBuffer[readIndex++];
      }

      public byte[] readOctetSequence() {
  int seqLen = readLong();
  byte[] result = new byte[seqLen];
  System.arraycopy(readBuffer, readIndex, result, 0, seqLen);
  readIndex += seqLen;
  return result;
      }

      public String readString() {
    int strLen = readLong(); // This includes '\0' terminator
    String result = new String(readBuffer, readIndex, strLen - 1);
    readIndex += strLen;
    return result;
      }

      // These depend on endianness, so are deferred to subclasses
      public abstract short readShort();   // 16 bits
      public abstract int readLong();      // 32 bits
      public abstract long readLongLong(); // 64 bits

      // Writes a couple of hexadecimal digits representing the given byte.
      // All other marshalling operations ultimately use this method to modify
      // the write buffer
      public void writeOctet(byte b) {
  char[] digits = new char[2];
  digits[0] = HEX[(b & 0xF0) >> 4]; // High nibble
  digits[1] = HEX[b & 0x0F]; // Low nibble
  writeBuffer.append(digits);
  writeIndex++;
      }

      public void writeOctetSequence(byte[] seq) {
  int seqLen = seq.length;
  writeLong(seqLen);
  for(int i = 0; i < seqLen; i++)
    writeOctet(seq[i]);
      }

      public void writeString(String s) {
  int strLen = s.length() + 1; // This includes '\0' terminator
  writeLong(strLen);
  byte[] bytes = s.getBytes();
  for(int i = 0; i < s.length(); i++)
    writeOctet(bytes[i]);
  writeOctet((byte)0x00);
      }

      // These depend on endianness, so are deferred to subclasses
      public abstract void writeShort(short s);   // 16 bits
      public abstract void writeLong(int i);      // 32 bits
      public abstract void writeLongLong(long l); // 64 bits

      protected void setReadAlignment(int align) {
  while((readIndex % align) != 0)
    readIndex++;
      }

      protected void setWriteAlignment(int align) {
  while(writeIndex % align != 0)
    writeOctet((byte)0x00);
      }

      private byte[] bytesFromHexString(String hexString) {
  int hexLen = hexString.length() / 2;
  byte[] result = new byte[hexLen];

  for(int i = 0; i < hexLen; i ++) {
    String currentDigit = hexString.substring(2*i, 2*(i + 1));
    Short s = Short.valueOf(currentDigit, 16);
    result[i] = s.byteValue();
  }

  return result;
      }

    } // End of CDRCodec class

    private static class BigEndianCodec extends CDRCodec {

      public BigEndianCodec(String ior) {
  super(ior);
  writeOctet((byte)0x00); // Writes 'Big Endian' magic number
      }

      public BigEndianCodec(byte[] hexDigits) {
  super(hexDigits);
  writeOctet((byte)0x00); // Writes 'Big Endian' magic number
      }

      public short readShort() {
  setReadAlignment(2);
  short result = (short)((readBuffer[readIndex++] << 8) + readBuffer[readIndex++]);
  return result;
      }

      public int readLong() {
  setReadAlignment(4);
  int result = (readBuffer[readIndex++] << 24) + (readBuffer[readIndex++] << 16);
  result += (readBuffer[readIndex++] << 8) + readBuffer[readIndex++];
  return result;
      }

      public long readLongLong() {
  setReadAlignment(8);
  long result = (readBuffer[readIndex++] << 56) + (readBuffer[readIndex++] << 48);
  result += (readBuffer[readIndex++] << 40) + (readBuffer[readIndex++] << 32);
  result += (readBuffer[readIndex++] << 24) + (readBuffer[readIndex++] << 16);
  result += (readBuffer[readIndex++] << 8) + readBuffer[readIndex++];
  return result;
      }

      public void writeShort(short s) {
  setWriteAlignment(2);
  writeOctet((byte)((s & 0xFF00) >> 8));
  writeOctet((byte)(s & 0x00FF));
      }

      public void writeLong(int i) {
  setWriteAlignment(4);
  writeOctet((byte)((i & 0xFF000000) >> 24));
  writeOctet((byte)((i & 0x00FF0000) >> 16));
  writeOctet((byte)((i & 0x0000FF00) >> 8));
  writeOctet((byte)(i & 0x000000FF));
      }

      public void writeLongLong(long l) {
  setWriteAlignment(8);
  writeOctet((byte)((l & 0xFF00000000000000L) >> 56));
  writeOctet((byte)((l & 0x00FF000000000000L) >> 48));
  writeOctet((byte)((l & 0x0000FF0000000000L) >> 40));
  writeOctet((byte)((l & 0x000000FF00000000L) >> 32));
  writeOctet((byte)((l & 0x00000000FF000000L) >> 24));
  writeOctet((byte)((l & 0x0000000000FF0000L) >> 16));
  writeOctet((byte)((l & 0x000000000000FF00L) >> 8));
  writeOctet((byte)(l & 0x00000000000000FFL));
      }

    } // End of BigEndianCodec class

    private static class LittleEndianCodec extends CDRCodec {

      public LittleEndianCodec(String ior) {
  super(ior);
  writeOctet((byte)0x01); // Writes 'Little Endian' magic number
      }

      public LittleEndianCodec(byte[] hexDigits) {
  super(hexDigits);
  writeOctet((byte)0x01); // Writes 'Little Endian' magic number
      }

      public short readShort() {
  setReadAlignment(2);
  short result = (short)(readBuffer[readIndex++] + (readBuffer[readIndex++] << 8));
  return result;
      }

      public int readLong() {
  setReadAlignment(4);
  int result = readBuffer[readIndex++] + (readBuffer[readIndex++] << 8) + (readBuffer[readIndex++] << 16) + (readBuffer[readIndex++] << 24);
  return result;
      }

      public long readLongLong() {
  setReadAlignment(8);
  long result = readBuffer[readIndex++] + (readBuffer[readIndex++] << 8);
  result += (readBuffer[readIndex++] << 16) + (readBuffer[readIndex++] << 24);
  result += (readBuffer[readIndex++] << 32) + (readBuffer[readIndex++] << 40);
  result += (readBuffer[readIndex++] << 48) + (readBuffer[readIndex++] << 56);
  return result;
      }

      public void writeShort(short s) {
  setWriteAlignment(2);
  writeOctet((byte)(s & 0x00FF));
  writeOctet((byte)((s & 0xFF00) >> 8));
      }

      public void writeLong(int i) {
  setWriteAlignment(4);
  writeOctet((byte)(i & 0x000000FF));
  writeOctet((byte)((i & 0x0000FF00) >> 8));
  writeOctet((byte)((i & 0x00FF0000) >> 16));
  writeOctet((byte)((i & 0xFF000000) >> 24));
      }

      public void writeLongLong(long l) {
  setWriteAlignment(8);
  writeOctet((byte)(l & 0x00000000000000FFL));
  writeOctet((byte)((l & 0x000000000000FF00L) >> 8));
  writeOctet((byte)((l & 0x0000000000FF0000L) >> 16));
  writeOctet((byte)((l & 0x00000000FF000000L) >> 24));
  writeOctet((byte)((l & 0x000000FF00000000L) >> 32));
  writeOctet((byte)((l & 0x0000FF0000000000L) >> 40));
  writeOctet((byte)((l & 0x00FF000000000000L) >> 48));
  writeOctet((byte)((l & 0xFF00000000000000L) >> 56));
      }

    }  // End of LittleEndianCodec class

    public String getProto() {
      return "iiop";
    }

    public String getHost() {
      return host;
    }

    public String getPort() {
      return Short.toString(port);
    }

    public String getFile() {
      return objectKey;
    }

    public String getAnchor() {
      return anchor;
    }
   
   

  } // End of IIOPAddress class

TOP

Related Classes of jade.mtp.iiop.IIOPAddress$BigEndianCodec

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.