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.Vio;
42 import gnu.CORBA.CDR.BufferredCdrInput;
43 import gnu.CORBA.CDR.BufferedCdrOutput;
44 import gnu.CORBA.typecodes.PrimitiveTypeCode;
45 import gnu.CORBA.typecodes.StringTypeCode;
47 import org.omg.CORBA.Any;
48 import org.omg.CORBA.AnyHolder;
49 import org.omg.CORBA.BAD_OPERATION;
50 import org.omg.CORBA.BooleanHolder;
51 import org.omg.CORBA.CharHolder;
52 import org.omg.CORBA.DoubleHolder;
53 import org.omg.CORBA.FixedHolder;
54 import org.omg.CORBA.FloatHolder;
55 import org.omg.CORBA.IntHolder;
56 import org.omg.CORBA.LongHolder;
57 import org.omg.CORBA.MARSHAL;
58 import org.omg.CORBA.ORB;
59 import org.omg.CORBA.ObjectHolder;
60 import org.omg.CORBA.Principal;
61 import org.omg.CORBA.PrincipalHolder;
62 import org.omg.CORBA.ShortHolder;
63 import org.omg.CORBA.StringHolder;
64 import org.omg.CORBA.TCKind;
65 import org.omg.CORBA.TypeCode;
66 import org.omg.CORBA.TypeCodeHolder;
67 import org.omg.CORBA.ValueBaseHolder;
68 import org.omg.CORBA.portable.Streamable;
70 import java.io.Serializable;
71 import java.lang.reflect.Field;
72 import java.math.BigDecimal;
73 import java.util.Arrays;
74 import java.util.zip.Adler32;
77 * The implementation of {@link Any}.
79 * For performance reasonse, the inserted values are not cloned.
80 * If the value object allows modifications (like {@link Streamable}),
81 * these subsequent alterations are reflected by the instance of
82 * this gnuAny, and the gnuAny alterations are reflected by the
83 * returned value. If it is required to have the uncoupled value,
84 * it must be requested from the copy of the current instance.
85 * The {@link gnuAny} can be simply cloned by the provided
86 * {@link Clone()} method.
88 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
94 * Use serialVersionUID for interoperability.
96 private static final long serialVersionUID = 1;
99 * The value, returned by {@link #type()} if the value has been
102 protected static final TypeCode nullType =
103 new PrimitiveTypeCode(TCKind.tk_null);
106 * The Streamable, representing the value, held by this gnuAny.
108 protected Streamable has;
111 * The complete typecode of the Streamable, if explicitly set.
113 protected TypeCode typecode;
116 * The typecode kind of the Streamable, if explicitly set.
118 protected int xKind = -1;
121 * The associated ORB.
126 * Set the associated orb.
128 public void setOrb(ORB an_orb)
134 * Creates a deep copy of this gnuAny, writing to and subsequently
135 * reading from from the byte buffer.
137 * @return the uncoupled gnuAny with all fields set to identical
140 public gnuAny Clone()
142 BufferedCdrOutput out = new BufferedCdrOutput();
146 BufferredCdrInput in = new BufferredCdrInput(out.buffer.toByteArray());
148 return (gnuAny) in.read_any();
152 * Create the buffered CDR input stream, containing the
153 * value, stored inside of this {@link Any}.
155 public org.omg.CORBA.portable.InputStream create_input_stream()
157 if (has instanceof GeneralHolder)
159 GeneralHolder u = (GeneralHolder) has;
160 return u.getInputStream();
164 BufferedCdrOutput out = new BufferedCdrOutput();
168 BufferredCdrInput in = new BufferredCdrInput(out.buffer.toByteArray());
175 * Create the buffered CDR output stream (empty).
177 public org.omg.CORBA.portable.OutputStream create_output_stream()
179 BufferedCdrOutput stream = new BufferedCdrOutput();
185 * Compare two Any's for equality.
186 * @param other the other Any to compare.
188 public boolean equal(Any other)
192 if (type().kind() != other.type().kind())
195 if (has != null && other instanceof gnuAny)
196 if (has.equals(((gnuAny) other).has))
199 BufferedCdrOutput a = new BufferedCdrOutput();
203 BufferedCdrOutput b = new BufferedCdrOutput();
205 other.write_value(b);
207 byte[] ba = a.buffer.toByteArray();
208 byte[] bb = b.buffer.toByteArray();
210 return Arrays.equals(ba, bb);
214 * Get the content - dependent hashcode.
216 public int hashCode()
219 return type().kind().value();
222 Adler32 adler = new Adler32();
224 BufferedCdrOutput a = new BufferedCdrOutput();
228 adler.update(a.buffer.toByteArray());
229 adler.update(type().kind().value());
231 return (int) adler.getValue() & Integer.MAX_VALUE;
236 * Delegates functionality to {@link #equal(Any)}.
238 public boolean equals(java.lang.Object other)
242 if (!(other instanceof Any))
245 return equal((Any) other);
249 * Extract the previously stored object.
251 public org.omg.CORBA.Object extract_Object()
255 return ((ObjectHolder) has).value;
257 catch (ClassCastException ex)
259 BAD_OPERATION bad = new BAD_OPERATION();
261 bad.minor = Minor.Any;
267 * Extract the previously inserted CORBA <code>Principal</code>/
268 * @return the previously inserted value.
270 * @throws org.omg.CORBA.BAD_OPERATION if the holder contains something
271 * else than Principal.
273 * @deprecated by CORBA 2.2.
275 public Principal extract_Principal()
277 check(TCKind._tk_Principal);
278 return ((PrincipalHolder) has).value;
282 * Return the value, encapsulated in a suitable holder.
283 * This implementation returns the direct reference,
284 * so the alterations on the returned streamable are
285 * directly reflected to the content of this {@link Any}.
287 public Streamable extract_Streamable()
292 public TypeCode extract_TypeCode()
295 check(TCKind._tk_TypeCode);
296 return ((TypeCodeHolder) has).value;
300 * Extract the stored value type.
302 * @return the previously stored value type.
304 * @throws BAD_OPERATION if the Any contains something different.
306 * @see org.omg.CORBA.portable.ValueBase
308 public Serializable extract_Value()
313 if (has instanceof ValueBaseHolder)
314 return ((ValueBaseHolder) has).value;
317 // Normally, ValueBase holder must be an instance of the
318 // ValueBaseHolder. However some IDL compilers probably
319 // have a bug, do not deriving this way. The the only
320 // way to access the wrapped value is via reflection.
321 Field f = has.getClass().getField("value");
322 return (Serializable) f.get(has);
327 BAD_OPERATION bad = new BAD_OPERATION("Value type expected");
328 bad.minor = Minor.Any;
335 public Any extract_any()
338 check(TCKind._tk_any);
339 return ((AnyHolder) has).value;
343 public boolean extract_boolean()
346 check(TCKind._tk_boolean);
347 return ((BooleanHolder) has).value;
351 public char extract_char()
354 check(TCKind._tk_char);
355 return ((CharHolder) has).value;
359 public double extract_double()
362 check(TCKind._tk_double);
363 return ((DoubleHolder) has).value;
367 * Extract the previously inserted CORBA <code>fixed</code>/
368 * @return the previously inserted value.
370 * @throws org.omg.CORBA.BAD_OPERATION if the holder contains something
371 * else than BigDecimal.
373 public BigDecimal extract_fixed()
374 throws org.omg.CORBA.BAD_OPERATION
376 check(TCKind._tk_fixed);
377 return ((FixedHolder) has).value;
381 public float extract_float()
384 check(TCKind._tk_float);
385 return ((FloatHolder) has).value;
389 public int extract_long()
392 // CORBA long = java int.
393 check(TCKind._tk_long);
394 return ((IntHolder) has).value;
398 public long extract_longlong()
401 check(TCKind._tk_longlong);
402 return ((LongHolder) has).value;
406 public byte extract_octet()
409 // ShortHolder holds also octets.
410 check(TCKind._tk_octet);
411 return (byte) ((OctetHolder) has).value;
415 public short extract_short()
418 check(TCKind._tk_short);
419 return ((ShortHolder) has).value;
423 public String extract_string()
426 check(TCKind._tk_string);
427 return ((StringHolder) has).value;
431 public int extract_ulong()
434 // IntHolder also holds ulongs.
435 check(TCKind._tk_ulong);
436 return ((IntHolder) has).value;
440 public long extract_ulonglong()
443 // LongHolder also holds ulonglong
444 check(TCKind._tk_ulonglong);
445 return ((LongHolder) has).value;
449 public short extract_ushort()
452 // ShortHolder also holds ushorts.
453 check(TCKind._tk_ushort);
454 return ((ShortHolder) has).value;
458 public char extract_wchar()
461 check(TCKind._tk_wchar);
462 return ((WCharHolder) has).value;
466 public String extract_wstring()
469 // StringHolder also holds wstrings.
470 check(TCKind._tk_wstring);
471 return ((WStringHolder) has).value;
475 * Inserts the CORBA object and sets the typecode to the given type.
477 public void insert_Object(org.omg.CORBA.Object x, TypeCode typecode)
479 has = new ObjectHolder(x);
484 * Inserts the CORBA object.
486 public void insert_Object(org.omg.CORBA.Object x)
488 has = new ObjectHolder(x);
492 * Insert the CORBA Principal.
493 * This implementation uses direct assignment, so the later
494 * alterations of that BigDecimal are reflected on the
495 * content of this {@link Any}.
497 * @deprecated by CORBA 2.2.
499 public void insert_Principal(Principal x)
502 if (has instanceof PrincipalHolder)
503 ((PrincipalHolder) has).value = x;
505 has = new PrincipalHolder(x);
509 * Sets the value to the value, encapsulated in this holder.
510 * This implementation uses direct assignment, so the later
511 * alterations of that streamable are reflected on the
512 * content of this {@link Any}.
514 public void insert_Streamable(Streamable x)
521 * Insert the typecode into this Any
522 * @param typecode the typecode to insert.
524 public void insert_TypeCode(TypeCode typecode)
527 if (has instanceof TypeCodeHolder)
528 ((TypeCodeHolder) has).value = typecode;
530 has = new TypeCodeHolder(typecode);
534 public void insert_Value(Serializable x, TypeCode c_typecode)
536 if (typecode != null && typecode.kind() == TCKind.tk_value_box)
538 has = new gnuValueHolder(x, typecode);
548 public void insert_Value(Serializable x)
550 if (typecode != null && typecode.kind() == TCKind.tk_value_box)
552 has = new gnuValueHolder(x, typecode);
556 if (has instanceof ValueBaseHolder)
557 ((ValueBaseHolder) has).value = x;
559 has = new ValueBaseHolder(x);
564 * Insert another {@link Any} into this {@link Any}.
565 * This implementation uses direct assignment, so the later
566 * alterations of that {@link Any} are reflected on the
567 * content of this {@link Any}.
569 public void insert_any(Any an_any)
572 if (has instanceof AnyHolder)
573 ((AnyHolder) has).value = an_any;
575 has = new AnyHolder(an_any);
579 public void insert_boolean(boolean x)
582 if (has instanceof BooleanHolder)
583 ((BooleanHolder) has).value = x;
585 has = new BooleanHolder(x);
589 public void insert_char(char x)
592 if (has instanceof CharHolder)
593 ((CharHolder) has).value = x;
595 has = new CharHolder(x);
599 public void insert_double(double x)
602 if (has instanceof DoubleHolder)
603 ((DoubleHolder) has).value = x;
605 has = new DoubleHolder(x);
609 * Inserts the CORBA <code>fixed</code>, setting the typecode
611 * This implementation uses direct assignment, so the later
612 * alterations of that BigDecimal are reflected on the
613 * content of this {@link Any}.
615 public void insert_fixed(BigDecimal x, TypeCode x_typecode)
619 typecode = x_typecode;
623 * Inserts the CORBA <code>fixed</code>, setting the typecode
624 * by example of the currently passed value.
625 * This implementation uses direct assignment, so the later
626 * alterations of that BigDecimal are reflected on the
627 * content of this {@link Any}, including the typecode.
629 public void insert_fixed(BigDecimal x)
632 if (has instanceof FixedHolder)
633 ((FixedHolder) has).value = x;
635 has = new FixedHolder(x);
639 public void insert_float(float x)
642 if (has instanceof FloatHolder)
643 ((FloatHolder) has).value = x;
645 has = new FloatHolder(x);
649 public void insert_long(int x)
652 if (has instanceof IntHolder)
653 ((IntHolder) has).value = x;
655 has = new IntHolder(x);
659 public void insert_longlong(long x)
662 if (has instanceof LongHolder)
663 ((LongHolder) has).value = x;
665 has = new LongHolder(x);
669 public void insert_octet(byte x)
672 if (has instanceof OctetHolder)
673 ((OctetHolder) has).value = x;
675 has = new OctetHolder(x);
679 public void insert_short(short x)
682 if (has instanceof ShortHolder)
683 ((ShortHolder) has).value = x;
685 has = new ShortHolder(x);
689 public void insert_string(String x)
692 if (has instanceof StringHolder)
693 ((StringHolder) has).value = x;
695 has = new StringHolder(x);
697 typecode = new StringTypeCode(TCKind.tk_string);
701 public void insert_ulong(int x)
704 if (has instanceof IntHolder)
705 ((IntHolder) has).value = x;
707 has = new IntHolder(x);
708 xKind = TCKind._tk_ulong;
712 public void insert_ulonglong(long x)
715 if (has instanceof LongHolder)
716 ((LongHolder) has).value = x;
718 has = new LongHolder(x);
719 xKind = TCKind._tk_ulonglong;
723 public void insert_ushort(short x)
726 if (has instanceof ShortHolder)
727 ((ShortHolder) has).value = x;
729 has = new ShortHolder(x);
730 xKind = TCKind._tk_ushort;
734 public void insert_wchar(char x)
737 if (has instanceof WCharHolder)
738 ((WCharHolder) has).value = x;
740 has = new WCharHolder(x);
744 public void insert_wstring(String x)
747 if (has instanceof WStringHolder)
748 ((WStringHolder) has).value = x;
750 has = new WStringHolder(x);
754 * Return the associated orb.
762 * Read the value of the given type from the given stream.
764 * @param input a stream to read from.
765 * @param a_type a typecode of the value to read.
767 public void read_value(org.omg.CORBA.portable.InputStream input,
774 int kind = a_type.kind().value();
776 // Fixed needs special handling.
777 if (kind == TCKind._tk_fixed)
779 BigDecimal dec = BigDecimalHelper.read(input, a_type.fixed_scale());
780 has = new FixedHolder(dec);
784 has = HolderLocator.createHolder(a_type);
787 // Use the Universal Holder that reads till the end of stream.
788 // This works with the extract/insert pair of the typical
790 BufferedCdrOutput buffer = new BufferedCdrOutput();
792 has = new GeneralHolder(buffer);
797 if (!(has instanceof GeneralHolder) &&
798 (kind == TCKind._tk_value_box))
800 // The streamable only contains operations for
801 // reading the value, not the value header.
802 Field vField = has.getClass().getField("value");
804 Object content = Vio.read(input, a_type.id());
805 vField.set(has, content);
812 MARSHAL m = new MARSHAL();
820 public TypeCode type()
822 if (typecode != null)
826 typecode = new PrimitiveTypeCode(TCKind.from_int(xKind));
830 return has != null ? has._type() : nullType;
834 * Explicitly set the typecode of the value to the given type.
836 * @param valueTypeCode the typecode of the value.
838 public void type(TypeCode valueTypeCode)
840 xKind = valueTypeCode.kind().value();
841 typecode = valueTypeCode;
845 public void write_value(org.omg.CORBA.portable.OutputStream output)
850 // These kinds support null.
851 if (xKind == TCKind._tk_null || xKind == TCKind._tk_objref ||
852 xKind == TCKind._tk_value || xKind == TCKind._tk_value_box
854 output.write_long(0);
858 * Check if the current value if the value of the given kind.
860 * @param kind a kind to check.
861 * @throws BAD_OPERATION if the value is not set of is different kind.
863 protected void check(int kind)
868 BAD_OPERATION bad = new BAD_OPERATION("value not set");
869 bad.minor = Minor.Any;
876 if (!(xKind == TCKind._tk_alias && has._type().kind().value() == kind))
878 BAD_OPERATION bad = new BAD_OPERATION("Extracting "
879 + TypeKindNamer.nameIt(kind) + " when stored "
880 + TypeKindNamer.nameIt(xKind));
881 bad.minor = Minor.Any;
887 if (type().kind().value() != kind)
888 if (!(type().kind().value() == TCKind._tk_alias && has._type().kind().value() == kind))
890 BAD_OPERATION bad = new BAD_OPERATION("Extracting "
891 + TypeKindNamer.nameIt(kind) + " stored "
892 + TypeKindNamer.nameIt(type()));
893 bad.minor = Minor.Any;
900 * Clear the additional type information before reusing this instance.
902 private final void resetTypes()