1 /*
   2  * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.corba.se.impl.dynamicany;
  27 
  28 import org.omg.CORBA.TypeCode;
  29 import org.omg.CORBA.TCKind;
  30 import org.omg.CORBA.Any;
  31 import org.omg.CORBA.TypeCodePackage.BadKind;
  32 import org.omg.CORBA.TypeCodePackage.Bounds;
  33 import org.omg.CORBA.portable.InputStream;
  34 import org.omg.DynamicAny.*;
  35 import org.omg.DynamicAny.DynAnyPackage.TypeMismatch;
  36 import org.omg.DynamicAny.DynAnyPackage.InvalidValue;
  37 import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode;
  38 
  39 import com.sun.corba.se.spi.orb.ORB ;
  40 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  41 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  42 
  43 abstract class DynAnyComplexImpl extends DynAnyConstructedImpl
  44 {
  45     //
  46     // Instance variables
  47     //
  48 
  49     String[] names = null;
  50     // Instance variables components and names above are kept in sync
  51     // with these two arrays at all times.
  52     NameValuePair[] nameValuePairs = null;
  53     NameDynAnyPair[] nameDynAnyPairs = null;
  54 
  55     //
  56     // Constructors
  57     //
  58 
  59     private DynAnyComplexImpl() {
  60         this(null, (Any)null, false);
  61     }
  62 
  63     protected DynAnyComplexImpl(ORB orb, Any any, boolean copyValue) {
  64         // We can be sure that typeCode is of kind tk_struct
  65         super(orb, any, copyValue);
  66         // Initialize components lazily, on demand.
  67         // This is an optimization in case the user is only interested in storing Anys.
  68     }
  69 
  70     protected DynAnyComplexImpl(ORB orb, TypeCode typeCode) {
  71         // We can be sure that typeCode is of kind tk_struct
  72         super(orb, typeCode);
  73         // For DynAnyComplex, the operation sets the current position to -1
  74         // for empty exceptions and to zero for all other TypeCodes.
  75         // The members (if any) are (recursively) initialized to their default values.
  76         index = 0;
  77     }
  78 
  79     //
  80     // DynAny interface methods
  81     //
  82 
  83     // _REVISIT_ Overridden to provide more efficient copying.
  84     // Copies all the internal representations which is faster than reconstructing them.
  85 /*
  86     public org.omg.DynamicAny.DynAny copy() {
  87         if (status == STATUS_DESTROYED) {
  88             throw new OBJECT_NOT_EXIST();
  89         }
  90         DynAnyComplexImpl returnValue = null;
  91         if ((representations & REPRESENTATION_ANY) != 0) {
  92             // The flag "true" indicates copying the Any value
  93             returnValue = (DynAnyComplexImpl)DynAnyUtil.createMostDerivedDynAny(any, orb, true);
  94         }
  95         if ((representations & REPRESENTATION_COMPONENTS) != 0) {
  96         }
  97         return returnValue;
  98     }
  99 */
 100 
 101     //
 102     // Complex methods
 103     //
 104 
 105     public String current_member_name ()
 106         throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch,
 107                org.omg.DynamicAny.DynAnyPackage.InvalidValue
 108     {
 109         if (status == STATUS_DESTROYED) {
 110             throw wrapper.dynAnyDestroyed() ;
 111         }
 112         if( ! checkInitComponents() || index < 0 || index >= names.length) {
 113             throw new InvalidValue();
 114         }
 115         return names[index];
 116     }
 117 
 118     public TCKind current_member_kind ()
 119         throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch,
 120                org.omg.DynamicAny.DynAnyPackage.InvalidValue
 121     {
 122         if (status == STATUS_DESTROYED) {
 123             throw wrapper.dynAnyDestroyed() ;
 124         }
 125         if( ! checkInitComponents() || index < 0 || index >= components.length) {
 126             throw new InvalidValue();
 127         }
 128         return components[index].type().kind();
 129     }
 130 
 131     // Creates references to the parameter instead of copying it.
 132     public void set_members (org.omg.DynamicAny.NameValuePair[] value)
 133         throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch,
 134                org.omg.DynamicAny.DynAnyPackage.InvalidValue
 135     {
 136         if (status == STATUS_DESTROYED) {
 137             throw wrapper.dynAnyDestroyed() ;
 138         }
 139         if (value == null || value.length == 0) {
 140             clearData();
 141             return;
 142         }
 143 
 144         Any memberAny;
 145         DynAny memberDynAny = null;
 146         String memberName;
 147         // We know that this is of kind tk_struct
 148         TypeCode expectedTypeCode = any.type();
 149 
 150         int expectedMemberCount = 0;
 151         try {
 152             expectedMemberCount = expectedTypeCode.member_count();
 153         } catch (BadKind badKind) { // impossible
 154         }
 155         if (expectedMemberCount != value.length) {
 156             clearData();
 157             throw new InvalidValue();
 158         }
 159 
 160         allocComponents(value);
 161 
 162         for (int i=0; i<value.length; i++) {
 163             if (value[i] != null) {
 164                 memberName = value[i].id;
 165                 String expectedMemberName = null;
 166                 try {
 167                     expectedMemberName = expectedTypeCode.member_name(i);
 168                 } catch (BadKind badKind) { // impossible
 169                 } catch (Bounds bounds) { // impossible
 170                 }
 171                 if ( ! (expectedMemberName.equals(memberName) || memberName.equals(""))) {
 172                     clearData();
 173                     // _REVISIT_ More info
 174                     throw new TypeMismatch();
 175                 }
 176                 memberAny = value[i].value;
 177                 TypeCode expectedMemberType = null;
 178                 try {
 179                     expectedMemberType = expectedTypeCode.member_type(i);
 180                 } catch (BadKind badKind) { // impossible
 181                 } catch (Bounds bounds) { // impossible
 182                 }
 183                 if (! expectedMemberType.equal(memberAny.type())) {
 184                     clearData();
 185                     // _REVISIT_ More info
 186                     throw new TypeMismatch();
 187                 }
 188                 try {
 189                     // Creates the appropriate subtype without copying the Any
 190                     memberDynAny = DynAnyUtil.createMostDerivedDynAny(memberAny, orb, false);
 191                 } catch (InconsistentTypeCode itc) {
 192                     throw new InvalidValue();
 193                 }
 194                 addComponent(i, memberName, memberAny, memberDynAny);
 195             } else {
 196                 clearData();
 197                 // _REVISIT_ More info
 198                 throw new InvalidValue();
 199             }
 200         }
 201         index = (value.length == 0 ? NO_INDEX : 0);
 202         representations = REPRESENTATION_COMPONENTS;
 203     }
 204 
 205     // Creates references to the parameter instead of copying it.
 206     public void set_members_as_dyn_any (org.omg.DynamicAny.NameDynAnyPair[] value)
 207         throws org.omg.DynamicAny.DynAnyPackage.TypeMismatch,
 208                org.omg.DynamicAny.DynAnyPackage.InvalidValue
 209     {
 210         if (status == STATUS_DESTROYED) {
 211             throw wrapper.dynAnyDestroyed() ;
 212         }
 213         if (value == null || value.length == 0) {
 214             clearData();
 215             return;
 216         }
 217 
 218         Any memberAny;
 219         DynAny memberDynAny;
 220         String memberName;
 221         // We know that this is of kind tk_struct
 222         TypeCode expectedTypeCode = any.type();
 223 
 224         int expectedMemberCount = 0;
 225         try {
 226             expectedMemberCount = expectedTypeCode.member_count();
 227         } catch (BadKind badKind) { // impossible
 228         }
 229         if (expectedMemberCount != value.length) {
 230             clearData();
 231             throw new InvalidValue();
 232         }
 233 
 234         allocComponents(value);
 235 
 236         for (int i=0; i<value.length; i++) {
 237             if (value[i] != null) {
 238                 memberName = value[i].id;
 239                 String expectedMemberName = null;
 240                 try {
 241                     expectedMemberName = expectedTypeCode.member_name(i);
 242                 } catch (BadKind badKind) { // impossible
 243                 } catch (Bounds bounds) { // impossible
 244                 }
 245                 if ( ! (expectedMemberName.equals(memberName) || memberName.equals(""))) {
 246                     clearData();
 247                     // _REVISIT_ More info
 248                     throw new TypeMismatch();
 249                 }
 250                 memberDynAny = value[i].value;
 251                 memberAny = getAny(memberDynAny);
 252                 TypeCode expectedMemberType = null;
 253                 try {
 254                     expectedMemberType = expectedTypeCode.member_type(i);
 255                 } catch (BadKind badKind) { // impossible
 256                 } catch (Bounds bounds) { // impossible
 257                 }
 258                 if (! expectedMemberType.equal(memberAny.type())) {
 259                     clearData();
 260                     // _REVISIT_ More info
 261                     throw new TypeMismatch();
 262                 }
 263 
 264                 addComponent(i, memberName, memberAny, memberDynAny);
 265             } else {
 266                 clearData();
 267                 // _REVISIT_ More info
 268                 throw new InvalidValue();
 269             }
 270         }
 271         index = (value.length == 0 ? NO_INDEX : 0);
 272         representations = REPRESENTATION_COMPONENTS;
 273     }
 274 
 275     //
 276     // Utility methods
 277     //
 278 
 279     private void allocComponents(int length) {
 280         components = new DynAny[length];
 281         names = new String[length];
 282         nameValuePairs = new NameValuePair[length];
 283         nameDynAnyPairs = new NameDynAnyPair[length];
 284         for (int i=0; i<length; i++) {
 285             nameValuePairs[i] = new NameValuePair();
 286             nameDynAnyPairs[i] = new NameDynAnyPair();
 287         }
 288     }
 289 
 290     private void allocComponents(org.omg.DynamicAny.NameValuePair[] value) {
 291         components = new DynAny[value.length];
 292         names = new String[value.length];
 293         nameValuePairs = value;
 294         nameDynAnyPairs = new NameDynAnyPair[value.length];
 295         for (int i=0; i<value.length; i++) {
 296             nameDynAnyPairs[i] = new NameDynAnyPair();
 297         }
 298     }
 299 
 300     private void allocComponents(org.omg.DynamicAny.NameDynAnyPair[] value) {
 301         components = new DynAny[value.length];
 302         names = new String[value.length];
 303         nameValuePairs = new NameValuePair[value.length];
 304         for (int i=0; i<value.length; i++) {
 305             nameValuePairs[i] = new NameValuePair();
 306         }
 307         nameDynAnyPairs = value;
 308     }
 309 
 310     private void addComponent(int i, String memberName, Any memberAny, DynAny memberDynAny) {
 311         components[i] = memberDynAny;
 312         names[i] = (memberName != null ? memberName : "");
 313         nameValuePairs[i].id = memberName;
 314         nameValuePairs[i].value = memberAny;
 315         nameDynAnyPairs[i].id = memberName;
 316         nameDynAnyPairs[i].value = memberDynAny;
 317         if (memberDynAny instanceof DynAnyImpl)
 318             ((DynAnyImpl)memberDynAny).setStatus(STATUS_UNDESTROYABLE);
 319     }
 320 
 321     // Initializes components, names, nameValuePairs and nameDynAnyPairs representation
 322     // from the Any representation
 323     protected boolean initializeComponentsFromAny() {
 324         // This typeCode is of kind tk_struct.
 325         TypeCode typeCode = any.type();
 326         TypeCode memberType = null;
 327         Any memberAny;
 328         DynAny memberDynAny = null;
 329         String memberName = null;
 330         int length = 0;
 331 
 332         try {
 333             length = typeCode.member_count();
 334         } catch (BadKind badKind) { // impossible
 335         }
 336 
 337         InputStream input = any.create_input_stream();
 338 
 339         allocComponents(length);
 340 
 341         for (int i=0; i<length; i++) {
 342             try {
 343                 memberName = typeCode.member_name(i);
 344                 memberType = typeCode.member_type(i);
 345             } catch (BadKind badKind) { // impossible
 346             } catch (Bounds bounds) { // impossible
 347             }
 348             memberAny = DynAnyUtil.extractAnyFromStream(memberType, input, orb);
 349             try {
 350                 // Creates the appropriate subtype without copying the Any
 351                 memberDynAny = DynAnyUtil.createMostDerivedDynAny(memberAny, orb, false);
 352                 // _DEBUG_
 353                 //System.out.println("Created DynAny for " + memberName +
 354                 //                   ", type " + memberType.kind().value());
 355             } catch (InconsistentTypeCode itc) { // impossible
 356             }
 357             addComponent(i, memberName, memberAny, memberDynAny);
 358         }
 359         return true;
 360     }
 361 
 362     // Initializes components, names, nameValuePairs and nameDynAnyPairs representation
 363     // from the internal TypeCode information with default values
 364     // This is not done recursively, only one level.
 365     // More levels are initialized lazily, on demand.
 366     protected boolean initializeComponentsFromTypeCode() {
 367         // This typeCode is of kind tk_struct.
 368         TypeCode typeCode = any.type();
 369         TypeCode memberType = null;
 370         Any memberAny;
 371         DynAny memberDynAny = null;
 372         String memberName;
 373         int length = 0;
 374 
 375         try {
 376             length = typeCode.member_count();
 377         } catch (BadKind badKind) { // impossible
 378         }
 379 
 380         allocComponents(length);
 381 
 382         for (int i=0; i<length; i++) {
 383             memberName = null;
 384             try {
 385                 memberName = typeCode.member_name(i);
 386                 memberType = typeCode.member_type(i);
 387             } catch (BadKind badKind) { // impossible
 388             } catch (Bounds bounds) { // impossible
 389             }
 390             try {
 391                 memberDynAny = DynAnyUtil.createMostDerivedDynAny(memberType, orb);
 392                 // _DEBUG_
 393                 //System.out.println("Created DynAny for " + memberName +
 394                 //                   ", type " + memberType.kind().value());
 395 /*
 396                 if (memberDynAny instanceof DynAnyConstructedImpl) {
 397                     if ( ! ((DynAnyConstructedImpl)memberDynAny).isRecursive()) {
 398                         // This is the recursive part
 399                         ((DynAnyConstructedImpl)memberDynAny).initializeComponentsFromTypeCode();
 400                     }
 401                 } // Other implementations have their own way of dealing with implementing the spec.
 402 */
 403             } catch (InconsistentTypeCode itc) { // impossible
 404             }
 405             // get a hold of the default initialized Any without copying
 406             memberAny = getAny(memberDynAny);
 407             addComponent(i, memberName, memberAny, memberDynAny);
 408         }
 409         return true;
 410     }
 411 
 412     // It is probably right not to destroy the released component DynAnys.
 413     // Some other DynAny or a user variable might still hold onto them
 414     // and if not then the garbage collector will take care of it.
 415     protected void clearData() {
 416         super.clearData();
 417         names = null;
 418         nameValuePairs = null;
 419         nameDynAnyPairs = null;
 420     }
 421 }