1. /*
  2. * @(#)DynSequenceImpl.java 1.6 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.internal.DynamicAny;
  8. import org.omg.CORBA.ORB;
  9. import org.omg.CORBA.TypeCode;
  10. import org.omg.CORBA.Any;
  11. import org.omg.CORBA.NO_IMPLEMENT;
  12. import org.omg.CORBA.OBJECT_NOT_EXIST;
  13. import org.omg.CORBA.BAD_OPERATION;
  14. import org.omg.CORBA.TypeCodePackage.BadKind;
  15. import org.omg.CORBA.TypeCodePackage.Bounds;
  16. import org.omg.CORBA.portable.InputStream;
  17. import org.omg.CORBA.portable.OutputStream;
  18. import org.omg.DynamicAny.*;
  19. import org.omg.DynamicAny.DynAnyPackage.TypeMismatch;
  20. import org.omg.DynamicAny.DynAnyPackage.InvalidValue;
  21. import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode;
  22. // _REVIST_ Could make this a subclass of DynArrayImpl
  23. // But that would mean that an object that implements DynSequence also implements DynArray
  24. // which the spec doesn't mention (it also doesn't forbid it).
  25. public class DynSequenceImpl extends DynAnyCollectionImpl implements DynSequence
  26. {
  27. //
  28. // Constructors
  29. //
  30. private DynSequenceImpl() {
  31. this(null, (Any)null, false);
  32. }
  33. protected DynSequenceImpl(ORB orb, Any any, boolean copyValue) {
  34. super(orb, any, copyValue);
  35. }
  36. // Sets the current position to -1 and creates an empty sequence.
  37. protected DynSequenceImpl(ORB orb, TypeCode typeCode) {
  38. super(orb, typeCode);
  39. }
  40. // Initializes components and anys representation
  41. // from the Any representation
  42. protected boolean initializeComponentsFromAny() {
  43. // This typeCode is of kind tk_sequence.
  44. TypeCode typeCode = any.type();
  45. int length;
  46. TypeCode contentType = getContentType();
  47. InputStream input;
  48. try {
  49. input = any.create_input_stream();
  50. } catch (BAD_OPERATION e) {
  51. return false;
  52. }
  53. length = input.read_long();
  54. components = new DynAny[length];
  55. anys = new Any[length];
  56. for (int i=0; i<length; i++) {
  57. // _REVISIT_ Could use read_xxx_array() methods on InputStream for efficiency
  58. // but only for primitive types
  59. anys[i] = DynAnyUtil.extractAnyFromStream(contentType, input, orb);
  60. try {
  61. // Creates the appropriate subtype without copying the Any
  62. components[i] = DynAnyUtil.createMostDerivedDynAny(anys[i], orb, false);
  63. } catch (InconsistentTypeCode itc) { // impossible
  64. }
  65. }
  66. return true;
  67. }
  68. // Sets the current position to -1 and creates an empty sequence.
  69. protected boolean initializeComponentsFromTypeCode() {
  70. // already done in the type code constructor
  71. components = new DynAny[0];
  72. anys = new Any[0];
  73. return true;
  74. }
  75. // Collapses the whole DynAny hierarchys values into one single streamed Any
  76. protected boolean initializeAnyFromComponents() {
  77. OutputStream out = any.create_output_stream();
  78. // Writing the length first is the only difference to supers implementation
  79. out.write_long(components.length);
  80. for (int i=0; i<components.length; i++) {
  81. if (components[i] instanceof DynAnyImpl) {
  82. ((DynAnyImpl)components[i]).writeAny(out);
  83. } else {
  84. // Not our implementation. Nothing we can do to prevent copying.
  85. components[i].to_any().write_value(out);
  86. }
  87. }
  88. any.read_value(out.create_input_stream(), any.type());
  89. return true;
  90. }
  91. //
  92. // DynSequence interface methods
  93. //
  94. // Returns the current length of the sequence
  95. public int get_length() {
  96. if (status == STATUS_DESTROYED) {
  97. throw new OBJECT_NOT_EXIST();
  98. }
  99. return (checkInitComponents() ? components.length : 0);
  100. }
  101. // Sets the length of the sequence. Increasing the length of a sequence
  102. // adds new elements at the tail without affecting the values of already
  103. // existing elements. Newly added elements are default-initialized.
  104. //
  105. // Increasing the length of a sequence sets the current position to the first
  106. // newly-added element if the previous current position was -1.
  107. // Otherwise, if the previous current position was not -1,
  108. // the current position is not affected.
  109. //
  110. // Increasing the length of a bounded sequence to a value larger than the bound
  111. // raises InvalidValue.
  112. //
  113. // Decreasing the length of a sequence removes elements from the tail
  114. // without affecting the value of those elements that remain.
  115. // The new current position after decreasing the length of a sequence is determined
  116. // as follows:
  117. // ?f the length of the sequence is set to zero, the current position is set to -1.
  118. // ?f the current position is -1 before decreasing the length, it remains at -1.
  119. // ?f the current position indicates a valid element and that element is not removed
  120. // when the length is decreased, the current position remains unaffected.
  121. // ?f the current position indicates a valid element and that element is removed, the
  122. // current position is set to -1.
  123. public void set_length(int len)
  124. throws org.omg.DynamicAny.DynAnyPackage.InvalidValue
  125. {
  126. if (status == STATUS_DESTROYED) {
  127. throw new OBJECT_NOT_EXIST();
  128. }
  129. int bound = getBound();
  130. if (bound > 0 && len > bound) {
  131. throw new InvalidValue();
  132. }
  133. checkInitComponents();
  134. int oldLength = components.length;
  135. if (len > oldLength) {
  136. // Increase length
  137. DynAny[] newComponents = new DynAny[len];
  138. Any[] newAnys = new Any[len];
  139. System.arraycopy(components, 0, newComponents, 0, oldLength);
  140. System.arraycopy(anys, 0, newAnys, 0, oldLength);
  141. components = newComponents;
  142. anys = newAnys;
  143. // Newly added elements are default-initialized
  144. TypeCode contentType = getContentType();
  145. for (int i=oldLength; i<len; i++) {
  146. createDefaultComponentAt(i, contentType);
  147. }
  148. // Increasing the length of a sequence sets the current position to the first
  149. // newly-added element if the previous current position was -1.
  150. if (index == NO_INDEX)
  151. index = oldLength;
  152. } else if (len < oldLength) {
  153. // Decrease length
  154. DynAny[] newComponents = new DynAny[len];
  155. Any[] newAnys = new Any[len];
  156. System.arraycopy(components, 0, newComponents, 0, len);
  157. System.arraycopy(anys, 0, newAnys, 0, len);
  158. // It is probably right not to destroy the released component DynAnys.
  159. // Some other DynAny or a user variable might still hold onto them
  160. // and if not then the garbage collector will take care of it.
  161. //for (int i=len; i<oldLength; i++) {
  162. // components[i].destroy();
  163. //}
  164. components = newComponents;
  165. anys = newAnys;
  166. // ?f the length of the sequence is set to zero, the current position is set to -1.
  167. // ?f the current position is -1 before decreasing the length, it remains at -1.
  168. // ?f the current position indicates a valid element and that element is not removed
  169. // when the length is decreased, the current position remains unaffected.
  170. // ?f the current position indicates a valid element and that element is removed,
  171. // the current position is set to -1.
  172. if (len == 0 || index >= len) {
  173. index = NO_INDEX;
  174. }
  175. } else {
  176. // Length unchanged
  177. // Maybe components is now default initialized from type code
  178. if (index == NO_INDEX && len > 0) {
  179. index = 0;
  180. }
  181. }
  182. }
  183. // Initializes the elements of the sequence.
  184. // The length of the DynSequence is set to the length of value.
  185. // The current position is set to zero if value has non-zero length
  186. // and to -1 if value is a zero-length sequence.
  187. // If the length of value exceeds the bound of a bounded sequence,
  188. // the operation raises InvalidValue.
  189. // If value contains one or more elements whose TypeCode is not equivalent
  190. // to the element TypeCode of the DynSequence, the operation raises TypeMismatch.
  191. /*
  192. public void set_elements(org.omg.CORBA.Any[] value)
  193. throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch,
  194. org.omg.DynamicAny.DynAnyPackage.InvalidValue;
  195. */
  196. //
  197. // Utility methods
  198. //
  199. protected void checkValue(Object[] value)
  200. throws org.omg.DynamicAny.DynAnyPackage.InvalidValue
  201. {
  202. if (value == null || value.length == 0) {
  203. clearData();
  204. index = NO_INDEX;
  205. return;
  206. } else {
  207. index = 0;
  208. }
  209. int bound = getBound();
  210. if (bound > 0 && value.length > bound) {
  211. throw new InvalidValue();
  212. }
  213. }
  214. }