libjava/
[official-gcc.git] / libjava / classpath / gnu / CORBA / IOR.java
blob5e13aecabd3f6e6833d8062a8f0a3c9459c57984
1 /* IOR.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package gnu.CORBA;
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;
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;
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;
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.
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()}.
76 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
78 * @see org.mog.CORBA.Object.object_to_string(Object forObject)
79 * @see string_to_object(String IOR)
81 public class IOR
83 /**
84 * The code sets tagged component, normally part of the Internet profile. This
85 * compone consists of the two componenets itself.
87 public static class CodeSets_profile
89 public CodeSets_profile()
91 int[] supported = CharSets_OSF.getSupportedCharSets();
93 narrow.native_set = CharSets_OSF.NATIVE_CHARACTER;
94 narrow.conversion = supported;
96 wide.native_set = CharSets_OSF.NATIVE_WIDE_CHARACTER;
97 wide.conversion = supported;
101 * The code set component.
103 public static class CodeSet_component
106 * The conversion code sets.
108 public int[] conversion;
111 * The native code set.
113 public int native_set;
116 * Read from the CDR stream.
118 public void read(org.omg.CORBA.portable.InputStream in)
120 native_set = in.read_ulong();
121 conversion = ULongSeqHelper.read(in);
125 * Get a string representation.
127 public String toString()
129 StringBuffer b = new StringBuffer();
130 b.append("native " + name(native_set));
131 if (conversion != null && conversion.length > 0)
133 b.append(" conversion ");
134 for (int i = 0; i < conversion.length; i++)
136 b.append(name(conversion[i]));
137 b.append(' ');
140 b.append(' ');
141 return b.toString();
145 * Get a better formatted multiline string representation.
147 public String toStringFormatted()
149 StringBuffer b = new StringBuffer();
150 b.append("\n Native set " + name(native_set));
151 if (conversion != null && conversion.length > 0)
153 b.append("\n Other supported sets:\n ");
154 for (int i = 0; i < conversion.length; i++)
156 b.append(name(conversion[i]));
157 b.append(' ');
160 b.append("\n");
161 return b.toString();
166 * Write into CDR stream.
168 public void write(org.omg.CORBA.portable.OutputStream out)
170 out.write_long(native_set);
171 ULongSeqHelper.write(out, conversion);
174 private String name(int set)
176 return "0x" + Integer.toHexString(set) + " ("
177 + CharSets_OSF.getName(set) + ") ";
182 * The agreed tag for the Codesets profile.
184 public static final int TAG_CODE_SETS = 1;
187 * Information about narrow character encoding (TCS-C).
189 public CodeSet_component narrow = new CodeSet_component();
192 * About wide character encoding (TCS-W).
194 public CodeSet_component wide = new CodeSet_component();
197 * The negotiated coding result for this IOR. Saves time, requred for
198 * negotiation computations.
200 public CodeSetServiceContext negotiated;
203 * Read the code set profile information from the given input stream.
205 * @param profile a stream to read from.
207 public void read(AbstractCdrInput profile)
209 BufferredCdrInput encapsulation = profile.read_encapsulation();
210 narrow.read(encapsulation);
211 wide.read(encapsulation);
215 * Returns a string representation.
217 public String toString()
219 return "Narrow char: " + narrow + ", Wide char: " + wide;
223 * Write the code set profile information into the given input stream.
225 * @param profile a stream to write into.
227 public void write(AbstractCdrOutput profile)
229 AbstractCdrOutput encapsulation = profile.createEncapsulation();
230 narrow.write(encapsulation);
231 wide.write(encapsulation);
234 encapsulation.close();
236 catch (IOException ex)
238 throw new InternalError();
244 * The internet profile.
246 public class Internet_profile
249 * The agreed tag for the Internet profile.
251 public static final int TAG_INTERNET_IOP = 0;
254 * The host.
256 public String host;
259 * The IIOP version (initialised to 1.2 by default).
261 public Version version = new Version(1, 2);
264 * The port.
266 public int port;
269 * The code sets component in the internet profile of this IOR. This is not
270 * a separate profile.
272 public CodeSets_profile CodeSets = new CodeSets_profile();
275 * Reserved for all components of this profile, this array holds the
276 * components other than code set components.
278 ArrayList components = new ArrayList();
281 * Return the human readable representation.
283 public String toString()
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();
298 * Write the internet profile (except the heading tag.
300 public void write(AbstractCdrOutput out)
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();
308 version.write(b);
309 b.write_string(host);
311 b.write_ushort((short) (port & 0xFFFF));
313 // Write the object key.
314 b.write_long(key.length);
315 b.write(key);
317 // Number of the tagged components.
318 b.write_long(1 + components.size());
320 b.write_long(CodeSets_profile.TAG_CODE_SETS);
321 CodeSets.write(b);
323 TaggedComponent t;
325 for (int i = 0; i < components.size(); i++)
327 t = (TaggedComponent) components.get(i);
328 TaggedComponentHelper.write(b, t);
331 b.close();
333 catch (Exception e)
335 MARSHAL m = new MARSHAL("Unable to write Internet profile.");
336 m.minor = Minor.IOR;
337 m.initCause(e);
338 throw m;
344 * The standard minor code, indicating that the string to object converstio
345 * has failed due non specific reasons.
347 public static final int FAILED = 10;
350 * The internet profile of this IOR.
352 public Internet_profile Internet = new Internet_profile();
355 * The object repository Id.
357 public String Id;
360 * The object key.
362 public byte[] key;
365 * All tagged profiles of this IOR, except the separately defined Internet
366 * profile.
368 ArrayList profiles = new ArrayList();
371 * True if the profile was encoded using the Big Endian or the encoding is not
372 * known.
374 * false if it was encoded using the Little Endian.
376 public boolean Big_Endian = true;
379 * Create an empty instance, initialising the code sets to default values.
381 public IOR()
386 * Parse the provided stringifed reference.
388 * @param stringified_reference in the form of IOR:nnnnnn.....
390 * @return the parsed IOR
392 * @throws BAD_PARAM, minor code 10, if the IOR cannot be parsed.
394 * TODO corballoc and other alternative formats.
396 public static IOR parse(String stringified_reference)
397 throws BAD_PARAM
401 if (!stringified_reference.startsWith("IOR:"))
402 throw new BAD_PARAM("The string refernce must start with IOR:",
403 FAILED, CompletionStatus.COMPLETED_NO);
405 IOR r = new IOR();
407 ByteArrayOutputStream buf = new ByteArrayOutputStream();
408 String x = stringified_reference;
409 x = x.substring(x.indexOf(":") + 1);
411 char cx;
413 for (int i = 0; i < x.length(); i = i + 2)
415 cx = (char) Integer.parseInt(x.substring(i, i + 2), 16);
416 buf.write(cx);
419 BufferredCdrInput cdr = new BufferredCdrInput(buf.toByteArray());
421 r._read(cdr);
422 return r;
424 catch (Exception ex)
426 ex.printStackTrace();
427 throw new BAD_PARAM(ex + " while parsing " + stringified_reference,
428 FAILED, CompletionStatus.COMPLETED_NO);
433 * Read the IOR from the provided input stream.
435 * @param c a stream to read from.
436 * @throws IOException if the stream throws it.
438 public void _read(AbstractCdrInput c)
439 throws IOException, BAD_PARAM
441 int endian;
443 endian = c.read_long();
444 if (endian != 0)
446 Big_Endian = false;
447 c.setBigEndian(false);
449 _read_no_endian(c);
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)}.
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).
460 * Id is checked for null in AbstractCdrInput that then returns null instead of
461 * object.
463 * @param c a stream to read from.
464 * @throws IOException if the stream throws it.
466 public void _read_no_endian(AbstractCdrInput c)
467 throws IOException, BAD_PARAM
469 Id = c.read_string();
471 int n_profiles = c.read_long();
473 if (n_profiles == 0)
475 Id = null;
476 Internet = null;
477 return;
480 for (int i = 0; i < n_profiles; i++)
482 int tag = c.read_long();
483 BufferredCdrInput profile = c.read_encapsulation();
485 if (tag == Internet_profile.TAG_INTERNET_IOP)
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();
492 key = profile.read_sequence();
494 // Read tagged components.
495 int n_components = 0;
499 if (Internet.version.since_inclusive(1, 1))
500 n_components = profile.read_long();
502 for (int t = 0; t < n_components; t++)
504 int ctag = profile.read_long();
506 if (ctag == CodeSets_profile.TAG_CODE_SETS)
508 Internet.CodeSets.read(profile);
510 else
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);
521 catch (Unexpected ex)
523 ex.printStackTrace();
526 else
528 // Construct a generic profile.
529 TaggedProfile p = new TaggedProfile();
530 p.tag = tag;
531 p.profile_data = profile.buffer.getBuffer();
533 profiles.add(p);
539 * Write this IOR record to the provided CDR stream. This procedure writes the
540 * zero (Big Endian) marker first.
542 public void _write(AbstractCdrOutput out)
544 // Always use Big Endian.
545 out.write(0);
546 _write_no_endian(out);
550 * Write a null value to the CDR output stream.
552 * The null value is written as defined in OMG specification (zero length
553 * string, followed by an empty set of profiles).
555 public static void write_null(AbstractCdrOutput out)
557 // Empty Id string.
558 out.write_string("");
560 // Empty set of profiles.
561 out.write_long(0);
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.
568 public void _write_no_endian(AbstractCdrOutput out)
570 // Write repository id.
571 out.write_string(Id);
573 out.write_long(1 + profiles.size());
575 // Write the Internet profile.
576 out.write_long(Internet_profile.TAG_INTERNET_IOP);
577 Internet.write(out);
579 // Write other profiles.
580 TaggedProfile tp;
582 for (int i = 0; i < profiles.size(); i++)
584 tp = (TaggedProfile) profiles.get(i);
585 TaggedProfileHelper.write(out, tp);
590 * Returns a human readable string representation of this IOR object.
592 public String toString()
594 StringBuffer b = new StringBuffer();
595 b.append(Id);
596 b.append(" at ");
597 b.append(Internet);
599 if (!Big_Endian)
600 b.append(" (Little endian) ");
602 b.append(" Key ");
604 for (int i = 0; i < key.length; i++)
606 b.append(Integer.toHexString(key[i] & 0xFF));
609 b.append(" ");
610 b.append(Internet.CodeSets);
612 return b.toString();
616 * Returns a multiline formatted human readable string representation of
617 * this IOR object.
619 public String toStringFormatted()
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);
627 if (Big_Endian)
628 b.append("\n Big endian encoding");
629 else
630 b.append("\n Little endian encoding.");
632 b.append("\nObject Key\n ");
634 for (int i = 0; i < key.length; i++)
636 b.append(Integer.toHexString(key[i] & 0xFF));
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());
645 return b.toString();
649 * Returs a stringified reference.
651 * @return a newly constructed stringified reference.
653 public String toStringifiedReference()
655 BufferedCdrOutput out = new BufferedCdrOutput();
657 _write(out);
659 StringBuffer b = new StringBuffer("IOR:");
661 byte[] binary = out.buffer.toByteArray();
662 String s;
664 for (int i = 0; i < binary.length; i++)
666 s = Integer.toHexString(binary[i] & 0xFF);
667 if (s.length() == 1)
668 b.append('0');
669 b.append(s);
672 return b.toString();
676 * Adds a service-specific component to the IOR profile. The specified
677 * component will be included in all profiles, present in the IOR.
679 * @param tagged_component a tagged component being added.
681 public void add_ior_component(TaggedComponent tagged_component)
683 // Add to the Internet profile.
684 Internet.components.add(tagged_component);
686 // Add to others.
687 for (int i = 0; i < profiles.size(); i++)
689 TaggedProfile profile = (TaggedProfile) profiles.get(i);
690 addComponentTo(profile, tagged_component);
695 * Adds a service-specific component to the IOR profile.
697 * @param tagged_component a tagged component being added.
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.
703 public void add_ior_component_to_profile(TaggedComponent tagged_component,
704 int profile_id)
706 if (profile_id == TAG_INTERNET_IOP.value)
707 // Add to the Internet profile
708 Internet.components.add(tagged_component);
709 else
711 // Add to others.
712 for (int i = 0; i < profiles.size(); i++)
714 TaggedProfile profile = (TaggedProfile) profiles.get(i);
715 if (profile.tag == profile_id)
716 addComponentTo(profile, tagged_component);
722 * Add given component to the given profile that is NOT an Internet profile.
724 * @param profile the profile, where the component should be added.
725 * @param component the component to add.
727 private static void addComponentTo(TaggedProfile profile,
728 TaggedComponent component)
730 if (profile.tag == TAG_MULTIPLE_COMPONENTS.value)
732 TaggedComponent[] present;
733 if (profile.profile_data.length > 0)
735 BufferredCdrInput in = new BufferredCdrInput(profile.profile_data);
737 present = new TaggedComponent[in.read_long()];
739 for (int i = 0; i < present.length; i++)
741 present[i] = TaggedComponentHelper.read(in);
744 else
745 present = new TaggedComponent[0];
747 BufferedCdrOutput out = new BufferedCdrOutput(profile.profile_data.length
748 + component.component_data.length
749 + 8);
751 // Write new amount of components.
752 out.write_long(present.length + 1);
754 // Write other components.
755 for (int i = 0; i < present.length; i++)
756 TaggedComponentHelper.write(out, present[i]);
758 // Write the passed component.
759 TaggedComponentHelper.write(out, component);
763 out.close();
765 catch (IOException e)
767 throw new Unexpected(e);
769 profile.profile_data = out.buffer.toByteArray();
771 else
772 // The future supported tagged profiles should be added here.
773 throw new BAD_PARAM("Unsupported profile type " + profile.tag);
777 * Checks for equality.
779 public boolean equals(Object x)
781 if (x instanceof IOR)
783 boolean keys;
784 boolean hosts = true;
786 IOR other = (IOR) x;
788 if (Internet==null || other.Internet==null)
789 return Internet == other.Internet;
791 if (key != null && other.key != null)
792 keys = Arrays.equals(key, other.key);
793 else
794 keys = key == other.key;
796 if (Internet != null && Internet.host != null)
797 if (other.Internet != null && other.Internet.host != null)
798 hosts = other.Internet.host.equals(Internet.host);
800 return keys & hosts && Internet.port==other.Internet.port;
802 else
803 return false;
807 * Get the hashcode of this IOR.
809 public int hashCode()
811 Adler32 adler = new Adler32();
812 if (key != null)
813 adler.update(key);
814 if (Internet != null)
816 if (Internet.host != null)
817 adler.update(Internet.host.getBytes());
818 adler.update(Internet.port);
820 return (int) adler.getValue();