libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / gnu / CORBA / IOR.java
blob7f63471eef0912d2e9770fb18bb206a2bab403b5
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 gnu.java.lang.CPStringBuilder;
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;
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;
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.
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()}.
78 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
80 * @see org.mog.CORBA.Object.object_to_string(Object forObject)
81 * @see string_to_object(String IOR)
83 public class IOR
85 /**
86 * The code sets tagged component, normally part of the Internet profile. This
87 * compone consists of the two componenets itself.
89 public static class CodeSets_profile
91 public CodeSets_profile()
93 int[] supported = CharSets_OSF.getSupportedCharSets();
95 narrow.native_set = CharSets_OSF.NATIVE_CHARACTER;
96 narrow.conversion = supported;
98 wide.native_set = CharSets_OSF.NATIVE_WIDE_CHARACTER;
99 wide.conversion = supported;
103 * The code set component.
105 public static class CodeSet_component
108 * The conversion code sets.
110 public int[] conversion;
113 * The native code set.
115 public int native_set;
118 * Read from the CDR stream.
120 public void read(org.omg.CORBA.portable.InputStream in)
122 native_set = in.read_ulong();
123 conversion = ULongSeqHelper.read(in);
127 * Get a string representation.
129 public String toString()
131 CPStringBuilder b = new CPStringBuilder();
132 b.append("native " + name(native_set));
133 if (conversion != null && conversion.length > 0)
135 b.append(" conversion ");
136 for (int i = 0; i < conversion.length; i++)
138 b.append(name(conversion[i]));
139 b.append(' ');
142 b.append(' ');
143 return b.toString();
147 * Get a better formatted multiline string representation.
149 public String toStringFormatted()
151 CPStringBuilder b = new CPStringBuilder();
152 b.append("\n Native set " + name(native_set));
153 if (conversion != null && conversion.length > 0)
155 b.append("\n Other supported sets:\n ");
156 for (int i = 0; i < conversion.length; i++)
158 b.append(name(conversion[i]));
159 b.append(' ');
162 b.append("\n");
163 return b.toString();
168 * Write into CDR stream.
170 public void write(org.omg.CORBA.portable.OutputStream out)
172 out.write_long(native_set);
173 ULongSeqHelper.write(out, conversion);
176 private String name(int set)
178 return "0x" + Integer.toHexString(set) + " ("
179 + CharSets_OSF.getName(set) + ") ";
184 * The agreed tag for the Codesets profile.
186 public static final int TAG_CODE_SETS = 1;
189 * Information about narrow character encoding (TCS-C).
191 public CodeSet_component narrow = new CodeSet_component();
194 * About wide character encoding (TCS-W).
196 public CodeSet_component wide = new CodeSet_component();
199 * The negotiated coding result for this IOR. Saves time, requred for
200 * negotiation computations.
202 public CodeSetServiceContext negotiated;
205 * Read the code set profile information from the given input stream.
207 * @param profile a stream to read from.
209 public void read(AbstractCdrInput profile)
211 BufferredCdrInput encapsulation = profile.read_encapsulation();
212 narrow.read(encapsulation);
213 wide.read(encapsulation);
217 * Returns a string representation.
219 public String toString()
221 return "Narrow char: " + narrow + ", Wide char: " + wide;
225 * Write the code set profile information into the given input stream.
227 * @param profile a stream to write into.
229 public void write(AbstractCdrOutput profile)
231 AbstractCdrOutput encapsulation = profile.createEncapsulation();
232 narrow.write(encapsulation);
233 wide.write(encapsulation);
236 encapsulation.close();
238 catch (IOException ex)
240 throw new InternalError();
246 * The internet profile.
248 public class Internet_profile
251 * The agreed tag for the Internet profile.
253 public static final int TAG_INTERNET_IOP = 0;
256 * The host.
258 public String host;
261 * The IIOP version (initialised to 1.2 by default).
263 public Version version = new Version(1, 2);
266 * The port.
268 public int port;
271 * The code sets component in the internet profile of this IOR. This is not
272 * a separate profile.
274 public CodeSets_profile CodeSets = new CodeSets_profile();
277 * Reserved for all components of this profile, this array holds the
278 * components other than code set components.
280 ArrayList components = new ArrayList();
283 * Return the human readable representation.
285 public String toString()
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();
300 * Write the internet profile (except the heading tag.
302 public void write(AbstractCdrOutput out)
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();
310 version.write(b);
311 b.write_string(host);
313 b.write_ushort((short) (port & 0xFFFF));
315 // Write the object key.
316 b.write_long(key.length);
317 b.write(key);
319 // Number of the tagged components.
320 b.write_long(1 + components.size());
322 b.write_long(CodeSets_profile.TAG_CODE_SETS);
323 CodeSets.write(b);
325 TaggedComponent t;
327 for (int i = 0; i < components.size(); i++)
329 t = (TaggedComponent) components.get(i);
330 TaggedComponentHelper.write(b, t);
333 b.close();
335 catch (Exception e)
337 MARSHAL m = new MARSHAL("Unable to write Internet profile.");
338 m.minor = Minor.IOR;
339 m.initCause(e);
340 throw m;
346 * The standard minor code, indicating that the string to object converstio
347 * has failed due non specific reasons.
349 public static final int FAILED = 10;
352 * The internet profile of this IOR.
354 public Internet_profile Internet = new Internet_profile();
357 * The object repository Id.
359 public String Id;
362 * The object key.
364 public byte[] key;
367 * All tagged profiles of this IOR, except the separately defined Internet
368 * profile.
370 ArrayList profiles = new ArrayList();
373 * True if the profile was encoded using the Big Endian or the encoding is not
374 * known.
376 * false if it was encoded using the Little Endian.
378 public boolean Big_Endian = true;
381 * Create an empty instance, initialising the code sets to default values.
383 public IOR()
388 * Parse the provided stringifed reference.
390 * @param stringified_reference in the form of IOR:nnnnnn.....
392 * @return the parsed IOR
394 * @throws BAD_PARAM, minor code 10, if the IOR cannot be parsed.
396 * TODO corballoc and other alternative formats.
398 public static IOR parse(String stringified_reference)
399 throws BAD_PARAM
403 if (!stringified_reference.startsWith("IOR:"))
404 throw new BAD_PARAM("The string refernce must start with IOR:",
405 FAILED, CompletionStatus.COMPLETED_NO);
407 IOR r = new IOR();
409 ByteArrayOutputStream buf = new ByteArrayOutputStream();
410 String x = stringified_reference;
411 x = x.substring(x.indexOf(":") + 1);
413 char cx;
415 for (int i = 0; i < x.length(); i = i + 2)
417 cx = (char) Integer.parseInt(x.substring(i, i + 2), 16);
418 buf.write(cx);
421 BufferredCdrInput cdr = new BufferredCdrInput(buf.toByteArray());
423 r._read(cdr);
424 return r;
426 catch (Exception ex)
428 ex.printStackTrace();
429 throw new BAD_PARAM(ex + " while parsing " + stringified_reference,
430 FAILED, CompletionStatus.COMPLETED_NO);
435 * Read the IOR from the provided input stream.
437 * @param c a stream to read from.
438 * @throws IOException if the stream throws it.
440 public void _read(AbstractCdrInput c)
441 throws IOException, BAD_PARAM
443 int endian;
445 endian = c.read_long();
446 if (endian != 0)
448 Big_Endian = false;
449 c.setBigEndian(false);
451 _read_no_endian(c);
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)}.
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).
462 * Id is checked for null in AbstractCdrInput that then returns null instead of
463 * object.
465 * @param c a stream to read from.
466 * @throws IOException if the stream throws it.
468 public void _read_no_endian(AbstractCdrInput c)
469 throws IOException, BAD_PARAM
471 Id = c.read_string();
473 int n_profiles = c.read_long();
475 if (n_profiles == 0)
477 Id = null;
478 Internet = null;
479 return;
482 for (int i = 0; i < n_profiles; i++)
484 int tag = c.read_long();
485 BufferredCdrInput profile = c.read_encapsulation();
487 if (tag == Internet_profile.TAG_INTERNET_IOP)
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();
494 key = profile.read_sequence();
496 // Read tagged components.
497 int n_components = 0;
501 if (Internet.version.since_inclusive(1, 1))
502 n_components = profile.read_long();
504 for (int t = 0; t < n_components; t++)
506 int ctag = profile.read_long();
508 if (ctag == CodeSets_profile.TAG_CODE_SETS)
510 Internet.CodeSets.read(profile);
512 else
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);
523 catch (Unexpected ex)
525 ex.printStackTrace();
528 else
530 // Construct a generic profile.
531 TaggedProfile p = new TaggedProfile();
532 p.tag = tag;
533 p.profile_data = profile.buffer.getBuffer();
535 profiles.add(p);
541 * Write this IOR record to the provided CDR stream. This procedure writes the
542 * zero (Big Endian) marker first.
544 public void _write(AbstractCdrOutput out)
546 // Always use Big Endian.
547 out.write(0);
548 _write_no_endian(out);
552 * Write a null value to the CDR output stream.
554 * The null value is written as defined in OMG specification (zero length
555 * string, followed by an empty set of profiles).
557 public static void write_null(AbstractCdrOutput out)
559 // Empty Id string.
560 out.write_string("");
562 // Empty set of profiles.
563 out.write_long(0);
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.
570 public void _write_no_endian(AbstractCdrOutput out)
572 // Write repository id.
573 out.write_string(Id);
575 out.write_long(1 + profiles.size());
577 // Write the Internet profile.
578 out.write_long(Internet_profile.TAG_INTERNET_IOP);
579 Internet.write(out);
581 // Write other profiles.
582 TaggedProfile tp;
584 for (int i = 0; i < profiles.size(); i++)
586 tp = (TaggedProfile) profiles.get(i);
587 TaggedProfileHelper.write(out, tp);
592 * Returns a human readable string representation of this IOR object.
594 public String toString()
596 CPStringBuilder b = new CPStringBuilder();
597 b.append(Id);
598 b.append(" at ");
599 b.append(Internet);
601 if (!Big_Endian)
602 b.append(" (Little endian) ");
604 b.append(" Key ");
606 for (int i = 0; i < key.length; i++)
608 b.append(Integer.toHexString(key[i] & 0xFF));
611 b.append(" ");
612 b.append(Internet.CodeSets);
614 return b.toString();
618 * Returns a multiline formatted human readable string representation of
619 * this IOR object.
621 public String toStringFormatted()
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);
629 if (Big_Endian)
630 b.append("\n Big endian encoding");
631 else
632 b.append("\n Little endian encoding.");
634 b.append("\nObject Key\n ");
636 for (int i = 0; i < key.length; i++)
638 b.append(Integer.toHexString(key[i] & 0xFF));
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());
647 return b.toString();
651 * Returs a stringified reference.
653 * @return a newly constructed stringified reference.
655 public String toStringifiedReference()
657 BufferedCdrOutput out = new BufferedCdrOutput();
659 _write(out);
661 CPStringBuilder b = new CPStringBuilder("IOR:");
663 byte[] binary = out.buffer.toByteArray();
664 String s;
666 for (int i = 0; i < binary.length; i++)
668 s = Integer.toHexString(binary[i] & 0xFF);
669 if (s.length() == 1)
670 b.append('0');
671 b.append(s);
674 return b.toString();
678 * Adds a service-specific component to the IOR profile. The specified
679 * component will be included in all profiles, present in the IOR.
681 * @param tagged_component a tagged component being added.
683 public void add_ior_component(TaggedComponent tagged_component)
685 // Add to the Internet profile.
686 Internet.components.add(tagged_component);
688 // Add to others.
689 for (int i = 0; i < profiles.size(); i++)
691 TaggedProfile profile = (TaggedProfile) profiles.get(i);
692 addComponentTo(profile, tagged_component);
697 * Adds a service-specific component to the IOR profile.
699 * @param tagged_component a tagged component being added.
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.
705 public void add_ior_component_to_profile(TaggedComponent tagged_component,
706 int profile_id)
708 if (profile_id == TAG_INTERNET_IOP.value)
709 // Add to the Internet profile
710 Internet.components.add(tagged_component);
711 else
713 // Add to others.
714 for (int i = 0; i < profiles.size(); i++)
716 TaggedProfile profile = (TaggedProfile) profiles.get(i);
717 if (profile.tag == profile_id)
718 addComponentTo(profile, tagged_component);
724 * Add given component to the given profile that is NOT an Internet profile.
726 * @param profile the profile, where the component should be added.
727 * @param component the component to add.
729 private static void addComponentTo(TaggedProfile profile,
730 TaggedComponent component)
732 if (profile.tag == TAG_MULTIPLE_COMPONENTS.value)
734 TaggedComponent[] present;
735 if (profile.profile_data.length > 0)
737 BufferredCdrInput in = new BufferredCdrInput(profile.profile_data);
739 present = new TaggedComponent[in.read_long()];
741 for (int i = 0; i < present.length; i++)
743 present[i] = TaggedComponentHelper.read(in);
746 else
747 present = new TaggedComponent[0];
749 BufferedCdrOutput out = new BufferedCdrOutput(profile.profile_data.length
750 + component.component_data.length
751 + 8);
753 // Write new amount of components.
754 out.write_long(present.length + 1);
756 // Write other components.
757 for (int i = 0; i < present.length; i++)
758 TaggedComponentHelper.write(out, present[i]);
760 // Write the passed component.
761 TaggedComponentHelper.write(out, component);
765 out.close();
767 catch (IOException e)
769 throw new Unexpected(e);
771 profile.profile_data = out.buffer.toByteArray();
773 else
774 // The future supported tagged profiles should be added here.
775 throw new BAD_PARAM("Unsupported profile type " + profile.tag);
779 * Checks for equality.
781 public boolean equals(Object x)
783 if (x instanceof IOR)
785 boolean keys;
786 boolean hosts = true;
788 IOR other = (IOR) x;
790 if (Internet==null || other.Internet==null)
791 return Internet == other.Internet;
793 if (key != null && other.key != null)
794 keys = Arrays.equals(key, other.key);
795 else
796 keys = key == other.key;
798 if (Internet != null && Internet.host != null)
799 if (other.Internet != null && other.Internet.host != null)
800 hosts = other.Internet.host.equals(Internet.host);
802 return keys & hosts && Internet.port==other.Internet.port;
804 else
805 return false;
809 * Get the hashcode of this IOR.
811 public int hashCode()
813 Adler32 adler = new Adler32();
814 if (key != null)
815 adler.update(key);
816 if (Internet != null)
818 if (Internet.host != null)
819 adler.update(Internet.host.getBytes());
820 adler.update(Internet.port);
822 return (int) adler.getValue();