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)
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
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
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. */
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;
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)
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]));
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]));
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;
261 * The IIOP version (initialised to 1.2 by default).
263 public Version version = new Version(1, 2);
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();
294 if (components.size() > 0)
295 b.append(" " + components.size() + " extra components.");
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();
311 b.write_string(host);
313 b.write_ushort((short) (port & 0xFFFF));
315 // Write the object key.
316 b.write_long(key.length);
319 // Number of the tagged components.
320 b.write_long(1 + components.size());
322 b.write_long(CodeSets_profile.TAG_CODE_SETS);
327 for (int i = 0; i < components.size(); i++)
329 t = (TaggedComponent) components.get(i);
330 TaggedComponentHelper.write(b, t);
337 MARSHAL m = new MARSHAL("Unable to write Internet profile.");
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.
367 * All tagged profiles of this IOR, except the separately defined Internet
370 ArrayList profiles = new ArrayList();
373 * True if the profile was encoded using the Big Endian or the encoding is not
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.
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)
403 if (!stringified_reference.startsWith("IOR:"))
404 throw new BAD_PARAM("The string refernce must start with IOR:",
405 FAILED, CompletionStatus.COMPLETED_NO);
409 ByteArrayOutputStream buf = new ByteArrayOutputStream();
410 String x = stringified_reference;
411 x = x.substring(x.indexOf(":") + 1);
415 for (int i = 0; i < x.length(); i = i + 2)
417 cx = (char) Integer.parseInt(x.substring(i, i + 2), 16);
421 BufferredCdrInput cdr = new BufferredCdrInput(buf.toByteArray());
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
445 endian = c.read_long();
449 c.setBigEndian(false);
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
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();
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);
514 // Construct a generic component for codesets
516 TaggedComponent pc = new TaggedComponent();
518 pc.component_data = profile.read_sequence();
519 Internet.components.add(pc);
523 catch (Unexpected ex)
525 ex.printStackTrace();
530 // Construct a generic profile.
531 TaggedProfile p = new TaggedProfile();
533 p.profile_data = profile.buffer.getBuffer();
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.
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)
560 out.write_string("");
562 // Empty set of profiles.
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);
581 // Write other profiles.
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();
602 b.append(" (Little endian) ");
606 for (int i = 0; i < key.length; i++)
608 b.append(Integer.toHexString(key[i] & 0xFF));
612 b.append(Internet.CodeSets);
618 * Returns a multiline formatted human readable string representation of
621 public String toStringFormatted()
623 CPStringBuilder b = new CPStringBuilder();
624 b.append("\nObject Id:\n ");
626 b.append("\nObject is accessible at:\n ");
630 b.append("\n Big endian encoding");
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());
651 * Returs a stringified reference.
653 * @return a newly constructed stringified reference.
655 public String toStringifiedReference()
657 BufferedCdrOutput out = new BufferedCdrOutput();
661 CPStringBuilder b = new CPStringBuilder("IOR:");
663 byte[] binary = out.buffer.toByteArray();
666 for (int i = 0; i < binary.length; i++)
668 s = Integer.toHexString(binary[i] & 0xFF);
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);
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,
708 if (profile_id == TAG_INTERNET_IOP.value)
709 // Add to the Internet profile
710 Internet.components.add(tagged_component);
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);
747 present = new TaggedComponent[0];
749 BufferedCdrOutput out = new BufferedCdrOutput(profile.profile_data.length
750 + component.component_data.length
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);
767 catch (IOException e)
769 throw new Unexpected(e);
771 profile.profile_data = out.buffer.toByteArray();
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)
786 boolean hosts = true;
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);
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;
809 * Get the hashcode of this IOR.
811 public int hashCode()
813 Adler32 adler = new Adler32();
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();