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