Source for gnu.CORBA.IOR

   1: /* IOR.java --
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.CORBA;
  40: 
  41: import gnu.CORBA.CDR.BufferredCdrInput;
  42: import gnu.CORBA.CDR.BufferedCdrOutput;
  43: import gnu.CORBA.CDR.AbstractCdrInput;
  44: import gnu.CORBA.CDR.AbstractCdrOutput;
  45: import gnu.CORBA.GIOP.CharSets_OSF;
  46: import gnu.CORBA.GIOP.CodeSetServiceContext;
  47: 
  48: import org.omg.CORBA.BAD_PARAM;
  49: import org.omg.CORBA.CompletionStatus;
  50: import org.omg.CORBA.MARSHAL;
  51: import org.omg.CORBA.ULongSeqHelper;
  52: import org.omg.IOP.TAG_INTERNET_IOP;
  53: import org.omg.IOP.TAG_MULTIPLE_COMPONENTS;
  54: import org.omg.IOP.TaggedComponent;
  55: import org.omg.IOP.TaggedComponentHelper;
  56: import org.omg.IOP.TaggedProfile;
  57: import org.omg.IOP.TaggedProfileHelper;
  58: 
  59: import java.io.ByteArrayOutputStream;
  60: import java.io.IOException;
  61: import java.util.ArrayList;
  62: import java.util.Arrays;
  63: import java.util.zip.Adler32;
  64: 
  65: /**
  66:  * The implementaton of the Interoperable Object Reference (IOR). IOR can be
  67:  * compared with the Internet address for a web page, it provides means to
  68:  * locate the CORBA service on the web. IOR contains the host address, port
  69:  * number, the object identifier (key) inside the server, the communication
  70:  * protocol version, supported charsets and so on.
  71:  *
  72:  * Ths class provides method for encoding and decoding the IOR information
  73:  * from/to the stringified references, usually returned by
  74:  * {@link org.omg.CORBA.ORB#String object_to_string()}.
  75:  *
  76:  * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
  77:  *
  78:  * @see org.mog.CORBA.Object.object_to_string(Object forObject)
  79:  * @see string_to_object(String IOR)
  80:  */
  81: public class IOR
  82: {
  83:   /**
  84:    * The code sets tagged component, normally part of the Internet profile. This
  85:    * compone consists of the two componenets itself.
  86:    */
  87:   public static class CodeSets_profile
  88:   {
  89:     public CodeSets_profile()
  90:     {
  91:       int[] supported = CharSets_OSF.getSupportedCharSets();
  92: 
  93:       narrow.native_set = CharSets_OSF.NATIVE_CHARACTER;
  94:       narrow.conversion = supported;
  95: 
  96:       wide.native_set = CharSets_OSF.NATIVE_WIDE_CHARACTER;
  97:       wide.conversion = supported;
  98:     }
  99: 
 100:     /**
 101:      * The code set component.
 102:      */
 103:     public static class CodeSet_component
 104:     {
 105:       /**
 106:        * The conversion code sets.
 107:        */
 108:       public int[] conversion;
 109: 
 110:       /**
 111:        * The native code set.
 112:        */
 113:       public int native_set;
 114: 
 115:       /**
 116:        * Read from the CDR stream.
 117:        */
 118:       public void read(org.omg.CORBA.portable.InputStream in)
 119:       {
 120:         native_set = in.read_ulong();
 121:         conversion = ULongSeqHelper.read(in);
 122:       }
 123: 
 124:       /**
 125:        * Get a string representation.
 126:        */
 127:       public String toString()
 128:       {
 129:         StringBuffer b = new StringBuffer();
 130:         b.append("native " + name(native_set));
 131:         if (conversion != null && conversion.length > 0)
 132:           {
 133:             b.append(" conversion ");
 134:             for (int i = 0; i < conversion.length; i++)
 135:               {
 136:                 b.append(name(conversion[i]));
 137:                 b.append(' ');
 138:               }
 139:           }
 140:         b.append(' ');
 141:         return b.toString();
 142:       }
 143:       
 144:       /**
 145:        * Get a better formatted multiline string representation.
 146:        */
 147:       public String toStringFormatted()
 148:       {
 149:         StringBuffer b = new StringBuffer();
 150:         b.append("\n  Native set " + name(native_set));
 151:         if (conversion != null && conversion.length > 0)
 152:           {
 153:             b.append("\n  Other supported sets:\n    ");
 154:             for (int i = 0; i < conversion.length; i++)
 155:               {
 156:                 b.append(name(conversion[i]));
 157:                 b.append(' ');
 158:               }
 159:           }
 160:         b.append("\n");
 161:         return b.toString();
 162:       }
 163:       
 164: 
 165:       /**
 166:        * Write into CDR stream.
 167:        */
 168:       public void write(org.omg.CORBA.portable.OutputStream out)
 169:       {
 170:         out.write_long(native_set);
 171:         ULongSeqHelper.write(out, conversion);
 172:       }
 173: 
 174:       private String name(int set)
 175:       {
 176:         return "0x" + Integer.toHexString(set) + " ("
 177:                + CharSets_OSF.getName(set) + ") ";
 178:       }
 179:     }
 180: 
 181:     /**
 182:      * The agreed tag for the Codesets profile.
 183:      */
 184:     public static final int TAG_CODE_SETS = 1;
 185: 
 186:     /**
 187:      * Information about narrow character encoding (TCS-C).
 188:      */
 189:     public CodeSet_component narrow = new CodeSet_component();
 190: 
 191:     /**
 192:      * About wide character encoding (TCS-W).
 193:      */
 194:     public CodeSet_component wide = new CodeSet_component();
 195: 
 196:     /**
 197:      * The negotiated coding result for this IOR. Saves time, requred for
 198:      * negotiation computations.
 199:      */
 200:     public CodeSetServiceContext negotiated;
 201: 
 202:     /**
 203:      * Read the code set profile information from the given input stream.
 204:      *
 205:      * @param profile a stream to read from.
 206:      */
 207:     public void read(AbstractCdrInput profile)
 208:     {
 209:       BufferredCdrInput encapsulation = profile.read_encapsulation();
 210:       narrow.read(encapsulation);
 211:       wide.read(encapsulation);
 212:     }
 213: 
 214:     /**
 215:      * Returns a string representation.
 216:      */
 217:     public String toString()
 218:     {
 219:       return "Narrow char: " + narrow + ", Wide char: " + wide;
 220:     }
 221: 
 222:     /**
 223:      * Write the code set profile information into the given input stream.
 224:      *
 225:      * @param profile a stream to write into.
 226:      */
 227:     public void write(AbstractCdrOutput profile)
 228:     {
 229:       AbstractCdrOutput encapsulation = profile.createEncapsulation();
 230:       narrow.write(encapsulation);
 231:       wide.write(encapsulation);
 232:       try
 233:         {
 234:           encapsulation.close();
 235:         }
 236:       catch (IOException ex)
 237:         {
 238:           throw new InternalError();
 239:         }
 240:     }
 241:   }
 242: 
 243:   /**
 244:    * The internet profile.
 245:    */
 246:   public class Internet_profile
 247:   {
 248:     /**
 249:      * The agreed tag for the Internet profile.
 250:      */
 251:     public static final int TAG_INTERNET_IOP = 0;
 252: 
 253:     /**
 254:      * The host.
 255:      */
 256:     public String host;
 257: 
 258:     /**
 259:      * The IIOP version (initialised to 1.2 by default).
 260:      */
 261:     public Version version = new Version(1, 2);
 262: 
 263:     /**
 264:      * The port.
 265:      */
 266:     public int port;
 267: 
 268:     /**
 269:      * The code sets component in the internet profile of this IOR. This is not
 270:      * a separate profile.
 271:      */
 272:     public CodeSets_profile CodeSets = new CodeSets_profile();
 273: 
 274:     /**
 275:      * Reserved for all components of this profile, this array holds the
 276:      * components other than code set components.
 277:      */
 278:     ArrayList components = new ArrayList();
 279: 
 280:     /**
 281:      * Return the human readable representation.
 282:      */
 283:     public String toString()
 284:     {
 285:       StringBuffer b = new StringBuffer();
 286:       b.append(host);
 287:       b.append(":");
 288:       b.append(port);
 289:       b.append(" (v");
 290:       b.append(version);
 291:       b.append(")");
 292:       if (components.size() > 0)
 293:         b.append(" " + components.size() + " extra components.");
 294:       return b.toString();
 295:     }
 296: 
 297:     /**
 298:      * Write the internet profile (except the heading tag.
 299:      */
 300:     public void write(AbstractCdrOutput out)
 301:     {
 302:       try
 303:         {
 304:           // Need to write the Internet profile into the separate
 305:           // stream as we must know the size in advance.
 306:           AbstractCdrOutput b = out.createEncapsulation();
 307: 
 308:           version.write(b);
 309:           b.write_string(host);
 310: 
 311:           b.write_ushort((short) (port & 0xFFFF));
 312: 
 313:           // Write the object key.
 314:           b.write_long(key.length);
 315:           b.write(key);
 316: 
 317:           // Number of the tagged components.
 318:           b.write_long(1 + components.size());
 319: 
 320:           b.write_long(CodeSets_profile.TAG_CODE_SETS);
 321:           CodeSets.write(b);
 322: 
 323:           TaggedComponent t;
 324: 
 325:           for (int i = 0; i < components.size(); i++)
 326:             {
 327:               t = (TaggedComponent) components.get(i);
 328:               TaggedComponentHelper.write(b, t);
 329:             }
 330: 
 331:           b.close();
 332:         }
 333:       catch (Exception e)
 334:         {
 335:           MARSHAL m = new MARSHAL("Unable to write Internet profile.");
 336:           m.minor = Minor.IOR;
 337:           m.initCause(e);
 338:           throw m;
 339:         }
 340:     }
 341:   }
 342: 
 343:   /**
 344:    * The standard minor code, indicating that the string to object converstio
 345:    * has failed due non specific reasons.
 346:    */
 347:   public static final int FAILED = 10;
 348: 
 349:   /**
 350:    * The internet profile of this IOR.
 351:    */
 352:   public Internet_profile Internet = new Internet_profile();
 353: 
 354:   /**
 355:    * The object repository Id.
 356:    */
 357:   public String Id;
 358: 
 359:   /**
 360:    * The object key.
 361:    */
 362:   public byte[] key;
 363: 
 364:   /**
 365:    * All tagged profiles of this IOR, except the separately defined Internet
 366:    * profile.
 367:    */
 368:   ArrayList profiles = new ArrayList();
 369: 
 370:   /**
 371:    * True if the profile was encoded using the Big Endian or the encoding is not
 372:    * known.
 373:    *
 374:    * false if it was encoded using the Little Endian.
 375:    */
 376:   public boolean Big_Endian = true;
 377: 
 378:   /**
 379:    * Create an empty instance, initialising the code sets to default values.
 380:    */
 381:   public IOR()
 382:   {
 383:   }
 384: 
 385:   /**
 386:    * Parse the provided stringifed reference.
 387:    *
 388:    * @param stringified_reference, in the form of IOR:nnnnnn.....
 389:    *
 390:    * @return the parsed IOR
 391:    *
 392:    * @throws BAD_PARAM, minor code 10, if the IOR cannot be parsed.
 393:    *
 394:    * TODO corballoc and other alternative formats.
 395:    */
 396:   public static IOR parse(String stringified_reference)
 397:     throws BAD_PARAM
 398:   {
 399:     try
 400:       {
 401:         if (!stringified_reference.startsWith("IOR:"))
 402:           throw new BAD_PARAM("The string refernce must start with IOR:",
 403:                               FAILED, CompletionStatus.COMPLETED_NO);
 404: 
 405:         IOR r = new IOR();
 406: 
 407:         ByteArrayOutputStream buf = new ByteArrayOutputStream();
 408:         String x = stringified_reference;
 409:         x = x.substring(x.indexOf(":") + 1);
 410: 
 411:         char cx;
 412: 
 413:         for (int i = 0; i < x.length(); i = i + 2)
 414:           {
 415:             cx = (char) Integer.parseInt(x.substring(i, i + 2), 16);
 416:             buf.write(cx);
 417:           }
 418: 
 419:         BufferredCdrInput cdr = new BufferredCdrInput(buf.toByteArray());
 420: 
 421:         r._read(cdr);
 422:         return r;
 423:       }
 424:     catch (Exception ex)
 425:       {
 426:         ex.printStackTrace();
 427:         throw new BAD_PARAM(ex + " while parsing " + stringified_reference,
 428:                             FAILED, CompletionStatus.COMPLETED_NO);
 429:       }
 430:   }
 431: 
 432:   /**
 433:    * Read the IOR from the provided input stream.
 434:    *
 435:    * @param c a stream to read from.
 436:    * @throws IOException if the stream throws it.
 437:    */
 438:   public void _read(AbstractCdrInput c)
 439:     throws IOException, BAD_PARAM
 440:   {
 441:     int endian;
 442: 
 443:     endian = c.read_long();
 444:     if (endian != 0)
 445:       {
 446:         Big_Endian = false;
 447:         c.setBigEndian(false);
 448:       }
 449:     _read_no_endian(c);
 450:   }
 451: 
 452:   /**
 453:    * Read the IOR from the provided input stream, not reading the endian data at
 454:    * the beginning of the stream. The IOR is thansferred in this form in
 455:    * {@link write_Object(org.omg.CORBA.Object)}.
 456:    *
 457:    * If the stream contains a null value, the Id and Internet fields become
 458:    * equal to null. Otherwise Id contains some string (possibly empty).
 459:    *
 460:    * Id is checked for null in AbstractCdrInput that then returns null instead of
 461:    * object.
 462:    *
 463:    * @param c a stream to read from.
 464:    * @throws IOException if the stream throws it.
 465:    */
 466:   public void _read_no_endian(AbstractCdrInput c)
 467:     throws IOException, BAD_PARAM
 468:   {
 469:     Id = c.read_string();
 470: 
 471:     int n_profiles = c.read_long();
 472: 
 473:     if (n_profiles == 0)
 474:       {
 475:         Id = null;
 476:         Internet = null;
 477:         return;
 478:       }
 479: 
 480:     for (int i = 0; i < n_profiles; i++)
 481:       {
 482:         int tag = c.read_long();
 483:         BufferredCdrInput profile = c.read_encapsulation();
 484: 
 485:         if (tag == Internet_profile.TAG_INTERNET_IOP)
 486:           {
 487:             Internet = new Internet_profile();
 488:             Internet.version = Version.read_version(profile);
 489:             Internet.host = profile.read_string();
 490:             Internet.port = profile.gnu_read_ushort();
 491: 
 492:             key = profile.read_sequence();
 493: 
 494:             // Read tagged components.
 495:             int n_components = 0;
 496: 
 497:             try
 498:               {
 499:                 if (Internet.version.since_inclusive(1, 1))
 500:                   n_components = profile.read_long();
 501: 
 502:                 for (int t = 0; t < n_components; t++)
 503:                   {
 504:                     int ctag = profile.read_long();
 505: 
 506:                     if (ctag == CodeSets_profile.TAG_CODE_SETS)
 507:                       {
 508:                         Internet.CodeSets.read(profile);
 509:                       }
 510:                     else
 511:                       {
 512:                         // Construct a generic component for codesets
 513:                         // profile.
 514:                         TaggedComponent pc = new TaggedComponent();
 515:                         pc.tag = ctag;
 516:                         pc.component_data = profile.read_sequence();
 517:                         Internet.components.add(pc);
 518:                       }
 519:                   }
 520:               }
 521:             catch (Unexpected ex)
 522:               {
 523:                 ex.printStackTrace();
 524:               }
 525:           }
 526:         else
 527:           {
 528:             // Construct a generic profile.
 529:             TaggedProfile p = new TaggedProfile();
 530:             p.tag = tag;
 531:             p.profile_data = profile.buffer.getBuffer();
 532: 
 533:             profiles.add(p);
 534:           }
 535:       }
 536:   }
 537: 
 538:   /**
 539:    * Write this IOR record to the provided CDR stream. This procedure writes the
 540:    * zero (Big Endian) marker first.
 541:    */
 542:   public void _write(AbstractCdrOutput out)
 543:   {
 544:     // Always use Big Endian.
 545:     out.write(0);
 546:     _write_no_endian(out);
 547:   }
 548: 
 549:   /**
 550:    * Write a null value to the CDR output stream.
 551:    *
 552:    * The null value is written as defined in OMG specification (zero length
 553:    * string, followed by an empty set of profiles).
 554:    */
 555:   public static void write_null(AbstractCdrOutput out)
 556:   {
 557:     // Empty Id string.
 558:     out.write_string("");
 559: 
 560:     // Empty set of profiles.
 561:     out.write_long(0);
 562:   }
 563: 
 564:   /**
 565:    * Write this IOR record to the provided CDR stream. The procedure writed data
 566:    * in Big Endian, but does NOT add any endian marker to the beginning.
 567:    */
 568:   public void _write_no_endian(AbstractCdrOutput out)
 569:   {
 570:     // Write repository id.
 571:     out.write_string(Id);
 572: 
 573:     out.write_long(1 + profiles.size());
 574: 
 575:     // Write the Internet profile.
 576:     out.write_long(Internet_profile.TAG_INTERNET_IOP);
 577:     Internet.write(out);
 578: 
 579:     // Write other profiles.
 580:     TaggedProfile tp;
 581: 
 582:     for (int i = 0; i < profiles.size(); i++)
 583:       {
 584:         tp = (TaggedProfile) profiles.get(i);
 585:         TaggedProfileHelper.write(out, tp);
 586:       }
 587:   }
 588: 
 589:   /**
 590:    * Returns a human readable string representation of this IOR object.
 591:    */
 592:   public String toString()
 593:   {
 594:     StringBuffer b = new StringBuffer();
 595:     b.append(Id);
 596:     b.append(" at ");
 597:     b.append(Internet);
 598: 
 599:     if (!Big_Endian)
 600:       b.append(" (Little endian) ");
 601: 
 602:     b.append(" Key ");
 603: 
 604:     for (int i = 0; i < key.length; i++)
 605:       {
 606:         b.append(Integer.toHexString(key[i] & 0xFF));
 607:       }
 608: 
 609:     b.append(" ");
 610:     b.append(Internet.CodeSets);
 611: 
 612:     return b.toString();
 613:   }
 614:   
 615:   /**
 616:    * Returns a multiline formatted human readable string representation of 
 617:    * this IOR object.
 618:    */
 619:   public String toStringFormatted()
 620:   {
 621:     StringBuffer b = new StringBuffer();
 622:     b.append("\nObject Id:\n  ");
 623:     b.append(Id);
 624:     b.append("\nObject is accessible at:\n  ");
 625:     b.append(Internet);
 626: 
 627:     if (Big_Endian)
 628:       b.append("\n  Big endian encoding");
 629:     else
 630:       b.append("\n  Little endian encoding.");      
 631: 
 632:     b.append("\nObject Key\n  ");
 633: 
 634:     for (int i = 0; i < key.length; i++)
 635:       {
 636:         b.append(Integer.toHexString(key[i] & 0xFF));
 637:       }
 638: 
 639:     b.append("\nSupported code sets:");
 640:     b.append("\n Wide:");
 641:     b.append(Internet.CodeSets.wide.toStringFormatted());
 642:     b.append(" Narrow:");
 643:     b.append(Internet.CodeSets.wide.toStringFormatted());
 644: 
 645:     return b.toString();
 646:   }  
 647: 
 648:   /**
 649:    * Returs a stringified reference.
 650:    *
 651:    * @return a newly constructed stringified reference.
 652:    */
 653:   public String toStringifiedReference()
 654:   {
 655:     BufferedCdrOutput out = new BufferedCdrOutput();
 656: 
 657:     _write(out);
 658: 
 659:     StringBuffer b = new StringBuffer("IOR:");
 660: 
 661:     byte[] binary = out.buffer.toByteArray();
 662:     String s;
 663: 
 664:     for (int i = 0; i < binary.length; i++)
 665:       {
 666:         s = Integer.toHexString(binary[i] & 0xFF);
 667:         if (s.length() == 1)
 668:           b.append('0');
 669:         b.append(s);
 670:       }
 671: 
 672:     return b.toString();
 673:   }
 674: 
 675:   /**
 676:    * Adds a service-specific component to the IOR profile. The specified
 677:    * component will be included in all profiles, present in the IOR.
 678:    *
 679:    * @param tagged_component a tagged component being added.
 680:    */
 681:   public void add_ior_component(TaggedComponent tagged_component)
 682:   {
 683:     // Add to the Internet profile.
 684:     Internet.components.add(tagged_component);
 685: 
 686:     // Add to others.
 687:     for (int i = 0; i < profiles.size(); i++)
 688:       {
 689:         TaggedProfile profile = (TaggedProfile) profiles.get(i);
 690:         addComponentTo(profile, tagged_component);
 691:       }
 692:   }
 693: 
 694:   /**
 695:    * Adds a service-specific component to the IOR profile.
 696:    *
 697:    * @param tagged_component a tagged component being added.
 698:    *
 699:    * @param profile_id the IOR profile to that the component must be added. The
 700:    * 0 value ({@link org.omg.IOP.TAG_INTERNET_IOP#value}) adds to the Internet
 701:    * profile where host and port are stored by default.
 702:    */
 703:   public void add_ior_component_to_profile(TaggedComponent tagged_component,
 704:                                            int profile_id)
 705:   {
 706:     if (profile_id == TAG_INTERNET_IOP.value)
 707:       // Add to the Internet profile
 708:       Internet.components.add(tagged_component);
 709:     else
 710:       {
 711:         // Add to others.
 712:         for (int i = 0; i < profiles.size(); i++)
 713:           {
 714:             TaggedProfile profile = (TaggedProfile) profiles.get(i);
 715:             if (profile.tag == profile_id)
 716:               addComponentTo(profile, tagged_component);
 717:           }
 718:       }
 719:   }
 720: 
 721:   /**
 722:    * Add given component to the given profile that is NOT an Internet profile.
 723:    *
 724:    * @param profile the profile, where the component should be added.
 725:    * @param component the component to add.
 726:    */
 727:   private static void addComponentTo(TaggedProfile profile,
 728:                                      TaggedComponent component)
 729:   {
 730:     if (profile.tag == TAG_MULTIPLE_COMPONENTS.value)
 731:       {
 732:         TaggedComponent[] present;
 733:         if (profile.profile_data.length > 0)
 734:           {
 735:             BufferredCdrInput in = new BufferredCdrInput(profile.profile_data);
 736: 
 737:             present = new TaggedComponent[in.read_long()];
 738: 
 739:             for (int i = 0; i < present.length; i++)
 740:               {
 741:                 present[i] = TaggedComponentHelper.read(in);
 742:               }
 743:           }
 744:         else
 745:           present = new TaggedComponent[0];
 746: 
 747:         BufferedCdrOutput out = new BufferedCdrOutput(profile.profile_data.length
 748:                                             + component.component_data.length
 749:                                             + 8);
 750: 
 751:         // Write new amount of components.
 752:         out.write_long(present.length + 1);
 753: 
 754:         // Write other components.
 755:         for (int i = 0; i < present.length; i++)
 756:           TaggedComponentHelper.write(out, present[i]);
 757: 
 758:         // Write the passed component.
 759:         TaggedComponentHelper.write(out, component);
 760: 
 761:         try
 762:           {
 763:             out.close();
 764:           }
 765:         catch (IOException e)
 766:           {
 767:             throw new Unexpected(e);
 768:           }
 769:         profile.profile_data = out.buffer.toByteArray();
 770:       }
 771:     else
 772:       // The future supported tagged profiles should be added here.
 773:       throw new BAD_PARAM("Unsupported profile type " + profile.tag);
 774:   }
 775:   
 776:   /**
 777:    * Checks for equality.
 778:    */
 779:   public boolean equals(Object x)
 780:   {
 781:     if (x instanceof IOR)
 782:       {
 783:         boolean keys;
 784:         boolean hosts = true;
 785: 
 786:         IOR other = (IOR) x;
 787:         
 788:         if (Internet==null || other.Internet==null)
 789:           return Internet == other.Internet;
 790:         
 791:         if (key != null && other.key != null)
 792:           keys = Arrays.equals(key, other.key);
 793:         else
 794:           keys = key == other.key;
 795: 
 796:         if (Internet != null && Internet.host != null)
 797:           if (other.Internet != null && other.Internet.host != null)
 798:             hosts = other.Internet.host.equals(Internet.host);
 799: 
 800:         return keys & hosts && Internet.port==other.Internet.port;
 801:       }
 802:     else
 803:       return false;
 804:   }
 805:   
 806:   /**
 807:    * Get the hashcode of this IOR.
 808:    */
 809:   public int hashCode()
 810:   {
 811:     Adler32 adler = new Adler32();
 812:     if (key != null)
 813:       adler.update(key);
 814:     if (Internet != null)
 815:       {
 816:         if (Internet.host != null)
 817:           adler.update(Internet.host.getBytes());
 818:         adler.update(Internet.port);
 819:       }
 820:     return (int) adler.getValue();
 821:   }