Source for gnu.CORBA.CDR.Vio

   1: /* Vio.java -- Value type IO operations.
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   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.
  10: 
  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.
  15: 
  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.
  20: 
  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.
  25: 
  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. */
  37: 
  38: 
  39: package gnu.CORBA.CDR;
  40: 
  41: import gnu.CORBA.Minor;
  42: import gnu.CORBA.ObjectCreator;
  43: 
  44: import gnu.java.lang.CPStringBuilder;
  45: 
  46: import org.omg.CORBA.CustomMarshal;
  47: import org.omg.CORBA.DataInputStream;
  48: import org.omg.CORBA.DataOutputStream;
  49: import org.omg.CORBA.MARSHAL;
  50: import org.omg.CORBA.NO_IMPLEMENT;
  51: import org.omg.CORBA.StringSeqHelper;
  52: import org.omg.CORBA.StringValueHelper;
  53: import org.omg.CORBA.SystemException;
  54: import org.omg.CORBA.WStringValueHelper;
  55: import org.omg.CORBA.portable.BoxedValueHelper;
  56: import org.omg.CORBA.portable.InputStream;
  57: import org.omg.CORBA.portable.OutputStream;
  58: import org.omg.CORBA.portable.Streamable;
  59: import org.omg.CORBA.portable.ValueFactory;
  60: 
  61: import java.io.IOException;
  62: import java.io.Serializable;
  63: import java.lang.reflect.Constructor;
  64: import java.lang.reflect.Modifier;
  65: import java.util.StringTokenizer;
  66: 
  67: import javax.rmi.CORBA.Util;
  68: import javax.rmi.CORBA.ValueHandler;
  69: 
  70: /**
  71:  * A specialised class for reading and writing the value types.
  72:  *
  73:  * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
  74:  */
  75: public abstract class Vio
  76: {
  77:   /**
  78:    * If true, wrap value type data into chunks. This decrease the performance,
  79:    * and is not required for interoperability with jdk 1.5, but is left in the
  80:    * implementation as the optional mode for solving possible interoperability
  81:    * problems with non-Sun CORBA implementations.
  82:    *
  83:    * The current implementation would accept both single chunk or multiple
  84:    * chunks, but will always send a single chunk (if true) or unchunked data (if
  85:    * false).
  86:    */
  87:   public static boolean USE_CHUNKING = false;
  88: 
  89:   /**
  90:    * The first field in the value record. The last octet may contain additional
  91:    * flags (vf_CODEBASE, vf_ID and vf_MULTIPLE_IDS). The tag value is different
  92:    * for the indirections (vt_INDIRECTION) and nulls (vt_NULL).
  93:    */
  94:   public static final int vt_VALUE_TAG = 0x7fffff00;
  95: 
  96:   /**
  97:    * The value tag flag, indicating that the codebase URL is present in the
  98:    * value tag record.
  99:    */
 100:   public static final int vf_CODEBASE = 0x1;
 101: 
 102:   /**
 103:    * The value tag flag, indicating that a single repository id is present in
 104:    * the value tag record.
 105:    */
 106:   public static final int vf_ID = 0x2;
 107: 
 108:   /**
 109:    * The value tag flag, indicating, that there are multiple repository ids
 110:    * present in the record. If this flag is set, the flag vf_ID must also be
 111:    * set, resulting the value of the least significant byte 0x6.
 112:    */
 113:   public static final int vf_MULTIPLE_IDS = 0x4;
 114: 
 115:   /**
 116:    * The value tag flag, indicating the presence of chunking. Each chunk is
 117:    * preceeded by a positive int, indicating the number of bytes in the chunk. A
 118:    * sequence of chunks is terminated by a non positive int.
 119:    */
 120:   public static final int vf_CHUNKING = 0x8;
 121: 
 122:   /**
 123:    * The indirection tag value. Such tag must be followed by the CORBA long,
 124:    * indicating the offset in the CORBA message, where the indirected
 125:    * information is present. This offset is assumed zero at the position where
 126:    * the mentioned CORBA long starts and can refer both forward (positive
 127:    * values) and backward (negative values).
 128:    */
 129:   public static final int vt_INDIRECTION = 0xffffffff;
 130: 
 131:   /**
 132:    * This tag value means that the value object being transferred is equal to
 133:    * null.
 134:    */
 135:   public static final int vt_NULL = 0x0;
 136: 
 137:   /**
 138:    * The size of CORBA long (java int).
 139:    */
 140:   static final int INT_SIZE = 4;
 141: 
 142:   /**
 143:    * The String value helper (one instance is sufficient).
 144:    */
 145:   public static final WStringValueHelper m_StringValueHelper = new WStringValueHelper();
 146: 
 147:   /**
 148:    * An instance of the value handler.
 149:    */
 150:   static ValueHandler handler = Util.createValueHandler();
 151: 
 152:   /**
 153:    * Read the value base from the given input stream. Determines the required
 154:    * class from the repository id. This includes operations that are not
 155:    * required when an unitialised instance or at least class of the value type
 156:    * is known. Hence it may be faster to use the alternative methods,
 157:    * read(InputStream, Class) or read(InputStream, Serializable).
 158:    *
 159:    * @param input a stream to read from.
 160:    *
 161:    * @return the loaded value.
 162:    *
 163:    * @throws MARSHAL if the reading has failed due any reason.
 164:    */
 165:   public static Serializable read(InputStream input)
 166:   {
 167:     return read(input, (String) null);
 168:   }
 169: 
 170:   /**
 171:    * Read the value base from the given input stream. Determines the required
 172:    * class from the repository id. This includes operations that are not
 173:    * required when an unitialised instance or at least class of the value type
 174:    * is known. Hence it may be faster to use the alternative methods,
 175:    * read(InputStream, Class) or read(InputStream, Serializable).
 176:    *
 177:    * @param input a stream to read from.
 178:    * @param repository_id a repository id of the object being read, may be null.
 179:    *
 180:    * @return the loaded value.
 181:    *
 182:    * @throws MARSHAL if the reading has failed due any reason.
 183:    */
 184:   public static Serializable read(InputStream input, String repository_id)
 185:   {
 186:     try
 187:       {
 188:         final int position = getCurrentPosition(input);
 189:         // We may need to jump back if the value is read via value factory.
 190:         input.mark(512);
 191: 
 192:         int value_tag = input.read_long();
 193:         checkTag(value_tag);
 194: 
 195:         String codebase = null;
 196:         String[] ids = null;
 197:         String id = repository_id;
 198: 
 199:         // Check for the agreed null value.
 200:         if (value_tag == vt_NULL)
 201:           return null;
 202:         else if (value_tag == vt_INDIRECTION)
 203:           return readIndirection(input);
 204:         else
 205:           {
 206:             // Read the value.
 207:             if ((value_tag & vf_CODEBASE) != 0)
 208:               {
 209:                 // The codebase is present. The codebase is a space
 210:                 // separated list of URLs from where the implementing
 211:                 // code can be downloaded.
 212:                 codebase = read_string(input);
 213:               }
 214: 
 215:             if ((value_tag & vf_MULTIPLE_IDS) != 0)
 216:               {
 217:                 // Multiple supported repository ids are present.
 218:                 ids = read_string_array(input);
 219:               }
 220:             else if ((value_tag & vf_ID) != 0)
 221:               {
 222:                 // Single supported repository id is present.
 223:                 id = read_string(input);
 224:               }
 225:           }
 226: 
 227:         BoxedValueHelper helper = getHelper(null, id);
 228:         // The existing implementing object.
 229:         java.lang.Object ox = null;
 230: 
 231:         if (helper != null)
 232:           ox = null; // Helper will care about the instantiating.
 233:         else if (id.equals(WStringValueHelper.id()))
 234:           helper = m_StringValueHelper;
 235:         else
 236:           ox = createInstance(id, ids, codebase);
 237:         return (Serializable) read_instance(input, position, ox, value_tag,
 238:           helper, id, ids, codebase);
 239:       }
 240:     catch (Exception ex)
 241:       {
 242:         MARSHAL m = new MARSHAL();
 243:         m.minor = Minor.Value;
 244:         m.initCause(ex);
 245:         throw m;
 246:       }
 247:   }
 248: 
 249:   /**
 250:    * Read the value base from the given input stream when the value base class
 251:    * is available. Hence there is no need to guess it from the repository id.
 252:    *
 253:    * @param input a stream to read from.
 254:    * @param value_class the class of the value being read.
 255:    *
 256:    * @return the loaded value.
 257:    *
 258:    * @throws MARSHAL if the reading has failed due any reason.
 259:    */
 260:   public static Serializable read(InputStream input, Class value_class)
 261:   {
 262:     final int position = getCurrentPosition(input);
 263: 
 264:     String id = null;
 265:     String[] ids = null;
 266:     String codebase = null;
 267: 
 268:     try
 269:       {
 270:         int value_tag = input.read_long();
 271:         checkTag(value_tag);
 272: 
 273:         // Check for the agreed null value.
 274:         if (value_tag == vt_NULL)
 275:           return null;
 276:         else if (value_tag == vt_INDIRECTION)
 277:           return readIndirection(input);
 278:         else
 279:           {
 280:             // Read the value.
 281:             if ((value_tag & vf_CODEBASE) != 0)
 282:               {
 283:                 // The codebase is present.
 284:                 codebase = read_string(input);
 285:               }
 286: 
 287:             if ((value_tag & vf_MULTIPLE_IDS) != 0)
 288:               {
 289:                 // Multiple supported repository ids are present.
 290:                 ids = read_string_array(input);
 291:               }
 292:             else if ((value_tag & vf_ID) != 0)
 293:               {
 294:                 // Single supported repository id is present.
 295:                 id = read_string(input);
 296:               }
 297:           }
 298: 
 299:         BoxedValueHelper vHelper = id != null ? getHelper(value_class, id)
 300:           : getHelper(value_class, ids);
 301: 
 302:         java.lang.Object ox;
 303: 
 304:         if (vHelper == null)
 305:           {
 306:             try
 307:               {
 308:                 ox = createInstance(id, ids, codebase);
 309:               }
 310:             catch (Exception e)
 311:               {
 312:                 ox = null;
 313:               }
 314: 
 315:             if (ox != null)
 316:               {
 317:                 if (value_class != null
 318:                   && !value_class.isAssignableFrom(ox.getClass()))
 319:                   {
 320:                     MARSHAL m = new MARSHAL(ox.getClass() + " is not a "
 321:                     + value_class.getName());
 322:                     m.minor = Minor.ClassCast;
 323:                     throw m;
 324:                   }
 325:               }
 326:           }
 327:         else
 328:           ox = null;
 329: 
 330:         ox = read_instance(input, position, ox, value_tag, vHelper, id, ids,
 331:           codebase);
 332:         return (Serializable) ox;
 333:       }
 334:     catch (MARSHAL m)
 335:       {
 336:         throw m;
 337:       }
 338:     catch (SystemException sysEx)
 339:       {
 340:         // OK.
 341:         throw sysEx;
 342:       }
 343:     catch (Exception ex)
 344:       {
 345:         MARSHAL m = new MARSHAL("Cant read " + value_class);
 346:         m.minor = Minor.Value;
 347:         m.initCause(ex);
 348:         throw m;
 349:       }
 350:   }
 351: 
 352:   /**
 353:    * Read the value base from the given input stream when the unitialised
 354:    * instance is available. Hence there is no need to guess the class from the
 355:    * repository id and then to instantiate an instance.
 356:    *
 357:    * @param input a stream to read from.
 358:    *
 359:    * @param value_instance an pre-created instance of the value. If the helper
 360:    * is not null, this parameter is ignored an should be null.
 361:    *
 362:    * @param helper a helper to create an instance and read the object- specific
 363:    * part of the record. If the value_instance is used instead, this parameter
 364:    * should be null.
 365:    *
 366:    * @return the loaded value.
 367:    *
 368:    * @throws MARSHAL if the reading has failed due any reason.
 369:    */
 370:   public static Object read(InputStream input, Object value_instance,
 371:     BoxedValueHelper helper)
 372:   {
 373:     final int position = getCurrentPosition(input);
 374: 
 375:     String id = null;
 376:     String[] ids = null;
 377:     String codebase = null;
 378: 
 379:     try
 380:       {
 381:         int value_tag = input.read_long();
 382:         checkTag(value_tag);
 383: 
 384:         // Check for the agreed null value.
 385:         if (value_tag == vt_NULL)
 386:           return null;
 387:         else if (value_tag == vt_INDIRECTION)
 388:           return readIndirection(input);
 389:         else
 390:           {
 391:             // Read the value.
 392:             if ((value_tag & vf_CODEBASE) != 0)
 393:               {
 394:                 // The codebase is present.
 395:                 codebase = read_string(input);
 396:               }
 397: 
 398:             if ((value_tag & vf_MULTIPLE_IDS) != 0)
 399:               {
 400:                 // Multiple supported repository ids are present.
 401:                 ids = read_string_array(input);
 402:               }
 403:             else if ((value_tag & vf_ID) != 0)
 404:               {
 405:                 // Single supported repository id is present.
 406:                 id = read_string(input);
 407:               }
 408:           }
 409: 
 410:         Class value_class = value_instance == null ? null
 411:           : value_instance.getClass();
 412: 
 413:         if (helper == null)
 414:           helper = id != null ? getHelper(value_class, id) : getHelper(
 415:             value_class, ids);
 416: 
 417:         value_instance = read_instance(input, position, value_instance,
 418:           value_tag, helper, id, ids, codebase);
 419:         return value_instance;
 420:       }
 421:     catch (Exception ex)
 422:       {
 423:         MARSHAL m = new MARSHAL();
 424:         m.minor = Minor.Value;
 425:         m.initCause(ex);
 426:         throw m;
 427:       }
 428:   }
 429: 
 430:   /**
 431:    * Read using provided boxed value helper. This method expects the full value
 432:    * type header, followed by contents, that are delegated to the provided
 433:    * helper. It handles null.
 434:    *
 435:    * @param input the stream to read from.
 436:    * @param helper the helper that reads the type-specific part of the content.
 437:    *
 438:    * @return the value, created by the helper, or null if the header indicates
 439:    * that null was previously written.
 440:    */
 441:   public static Serializable read(InputStream input, BoxedValueHelper helper)
 442:   {
 443:     return (Serializable) read(input, null, helper);
 444:   }
 445: 
 446:   /**
 447:    * Fill in the instance fields by the data from the input stream. The method
 448:    * assumes that the value header, if any, is already behind. The information
 449:    * from the stream is stored into the passed ox parameter.
 450:    *
 451:    * @param input an input stream to read from.
 452:    *
 453:    * @param value a pre-instantiated value type object, must be either
 454:    * Streamable or CustomMarshal. If the helper is used, this parameter is
 455:    * ignored and should be null.
 456:    *
 457:    * @param value_tag the tag that must be read previously.
 458:    * @param helper the helper for read object specific part; may be null to read
 459:    * in using other methods.
 460:    *
 461:    * @return the value that was read.
 462:    */
 463:   static Object read_instance(InputStream input, final int position,
 464:     Object value, int value_tag, BoxedValueHelper helper, String id,
 465:     String[] ids, String codebase)
 466:   {
 467:     if (helper != m_StringValueHelper && id != null)
 468:       if (id.equals(StringValueHelper.id()))
 469:         {
 470:           value = null;
 471:           helper = m_StringValueHelper;
 472:         }
 473: 
 474:     try
 475:       {
 476:         if ((value_tag & vf_CHUNKING) != 0)
 477:           {
 478:             BufferedCdrOutput output = createBuffer(input, 1024);
 479:             // Read the current (not a nested one) value in this spec case.
 480:             readNestedValue(value_tag, input, output, -1);
 481:             BufferredCdrInput ci = new BufferredCdrInput(output.buffer.getBuffer());
 482:             ci.setRunTime(output.getRunTime());
 483: 
 484:             input = new HeadlessInput(ci, input);
 485:           }
 486:         else
 487:           {
 488:             if (input instanceof BufferredCdrInput)
 489:               {
 490:                 // Highly probable case.
 491:                 input = new HeadlessInput((BufferredCdrInput) input, null);
 492:               }
 493:             else if (input instanceof HeadlessInput)
 494:               {
 495:                 // There is no need to instantiate one more HeadlessInput
 496:                 // as we can just reset.
 497:                 ((HeadlessInput) input).subsequentCalls = false;
 498:               }
 499:             else
 500:               {
 501:                 BufferedCdrOutput bout = new BufferedCdrOutput();
 502:                 int c;
 503:                 while ((c = input.read()) >= 0)
 504:                   bout.write((byte) c);
 505:                 input = new HeadlessInput(
 506:                   (BufferredCdrInput) bout.create_input_stream(), input);
 507:               }
 508:           }
 509:       }
 510:     catch (IOException ex)
 511:       {
 512:         MARSHAL m = new MARSHAL("Unable to read chunks");
 513:         m.minor = Minor.Value;
 514:         m.initCause(ex);
 515:         throw m;
 516:       }
 517: 
 518:     return readValue(input, position, value, helper, id, ids, codebase);
 519:   }
 520: 
 521:   /**
 522:    * Create a buffer, inheriting critical settings from the passed input stream.
 523:    */
 524:   private static BufferedCdrOutput createBuffer(InputStream input, int proposed_size)
 525:   {
 526:     BufferedCdrOutput bout;
 527:     bout = new BufferedCdrOutput(2 * proposed_size + 256);
 528: 
 529:     if (input instanceof BufferredCdrInput)
 530:       {
 531:         BufferredCdrInput in = (BufferredCdrInput) input;
 532:         bout.setBigEndian(in.isBigEndian());
 533:       }
 534: 
 535:     if (input instanceof gnuValueStream)
 536:       bout.setRunTime(((gnuValueStream) input).getRunTime());
 537:     else
 538:       bout.setRunTime(new gnuRuntime(null, null));
 539:     return bout;
 540:   }
 541: 
 542:   /**
 543:    * Read the chunked nested value from the given input stream, transferring the
 544:    * contents to the given output stream.
 545:    *
 546:    * @param value_tag the value tag of the value being read.
 547:    * @param input the input stream from where the remainder of the nested value
 548:    * must be read.
 549:    * @param output the output stream where the unchunked nested value must be
 550:    * copied.
 551:    *
 552:    * @return the tag that ended the nested value.
 553:    */
 554:   public static int readNestedValue(int value_tag, InputStream input,
 555:     BufferedCdrOutput output, int level)
 556:     throws IOException
 557:   {
 558:     String id = null;
 559:     if (level < -1)
 560:       {
 561:         // For the first level, this information is already behind.
 562:         output.write_long(value_tag - vf_CHUNKING);
 563: 
 564:         // The nested value should be aways chunked.
 565:         if ((value_tag & vf_CHUNKING) == 0)
 566:           {
 567:             MARSHAL m = new MARSHAL("readNestedValue: must be chunked");
 568:             m.minor = Minor.Chunks;
 569:             throw m;
 570:           }
 571:         else if (value_tag == vt_NULL)
 572:           {
 573:             MARSHAL m = new MARSHAL("readNestedValue: nul");
 574:             m.minor = Minor.Chunks;
 575:             throw m;
 576:           }
 577:         else if (value_tag == vt_INDIRECTION)
 578:           {
 579:             MARSHAL m = new MARSHAL("readNestedValue: indirection");
 580:             m.minor = Minor.Chunks;
 581:             throw m;
 582:           }
 583:         else
 584:           {
 585:             // Read the value.
 586:             if ((value_tag & vf_CODEBASE) != 0)
 587:               {
 588:                 String codebase = read_string(input);
 589:                 write_string(output, codebase);
 590:               }
 591: 
 592:             if ((value_tag & vf_MULTIPLE_IDS) != 0)
 593:               {
 594:                 // Multiple supported repository ids are present.
 595:                 String[] ids = read_string_array(input);
 596:                 id = ids[0];
 597:                 write_string_array(output, ids);
 598:               }
 599:             else if ((value_tag & vf_ID) != 0)
 600:               {
 601:                 id = read_string(input);
 602:                 write_string(output, id);
 603:               }
 604:           }
 605:       }
 606: 
 607:     int n = -1;
 608: 
 609:     // Read all chunks.
 610:     int chunk_size;
 611: 
 612:     byte[] r = null;
 613: 
 614:     while (true)
 615:       {
 616:         // Read the size of the next chunk or it may also be the
 617:         // header of the nested value.
 618:         chunk_size = input.read_long();
 619: 
 620:         // End of chunk terminator.
 621:         if (chunk_size < 0 && chunk_size >= level)
 622:           return chunk_size;
 623:         else if (chunk_size >= 0x7FFFFF00)
 624:           {
 625:             int onInput = getCurrentPosition(input) - 4;
 626:             int onOutput = output.getPosition();
 627:             output.getRunTime().redirect(onInput, onOutput);
 628:             // Value over 0x7FFFFF00 indicates that the nested value
 629:             // starts here. Read the nested value, storing it into the output.
 630:             // First parameter is actually the value tag.
 631:             chunk_size = readNestedValue(chunk_size, input, output, level - 1);
 632:             if (chunk_size < 0 && chunk_size >= level)
 633:               return chunk_size;
 634:           }
 635:         else
 636:           {
 637:             // The chunk follows.
 638:             if (r == null || r.length < chunk_size)
 639:               r = new byte[chunk_size + 256];
 640: 
 641:             n = 0;
 642:             while (n < chunk_size)
 643:               n += input.read(r, n, chunk_size - n);
 644:             output.write(r, 0, n);
 645:           }
 646:       }
 647:   }
 648: 
 649:   /**
 650:    * Read the value (the header must be behind).
 651:    */
 652:   public static Serializable readValue(InputStream input, final int position,
 653:     Object value, BoxedValueHelper helper, String id, String[] ids,
 654:     String codebase)
 655:   {
 656:     gnuRuntime g;
 657:     gnuValueStream c = ((gnuValueStream) input);
 658:     if (c.getRunTime() == null)
 659:       {
 660:         g = new gnuRuntime(codebase, value);
 661:         c.setRunTime(g);
 662:       }
 663:     else
 664:       {
 665:         g = c.getRunTime();
 666:         g.addCodeBase(codebase);
 667:         g.target = (Serializable) value;
 668:       }
 669:     if (value != null)
 670:       g.objectWritten(value, position);
 671: 
 672:     if (input instanceof HeadlessInput)
 673:       ((HeadlessInput) input).subsequentCalls = false;
 674: 
 675:     boolean ok = true;
 676: 
 677:     // The user-defined io operations are implemented.
 678:     if (value instanceof CustomMarshal)
 679:       {
 680:         CustomMarshal marsh = (CustomMarshal) value;
 681:         marsh.unmarshal((DataInputStream) input);
 682:       }
 683:     else
 684:     // The IDL-generated io operations are implemented.
 685:     if (value instanceof Streamable)
 686:       {
 687:         ((Streamable) value)._read(input);
 688:       }
 689:     else if (helper != null)
 690:       {
 691:         // If helper is non-null the value should normally be null.
 692:         value = helper.read_value(input);
 693:         g.objectWritten(value, position);
 694:       }
 695:     else
 696:       {
 697:         ok = false;
 698:         ValueFactory factory = null;
 699:         org.omg.CORBA_2_3.ORB orb = (org.omg.CORBA_2_3.ORB) input.orb();
 700: 
 701:         if (id != null)
 702:           factory = orb.lookup_value_factory(id);
 703: 
 704:         if (factory == null && ids != null)
 705:           {
 706:             for (int i = 0; i < ids.length && factory == null; i++)
 707:               {
 708:                 factory = orb.lookup_value_factory(ids[i]);
 709:               }
 710:           }
 711: 
 712:         if (factory != null)
 713:           {
 714:             value = factory.read_value((org.omg.CORBA_2_3.portable.InputStream) input);
 715:             ok = true;
 716:           }
 717:       }
 718: 
 719:     if (!ok && value instanceof Serializable)
 720:     // Delegate to ValueHandler
 721:       {
 722:         if (ids != null && ids.length > 0)
 723:           id = ids[0];
 724: 
 725:         value = handler.readValue(input, position, value.getClass(), id, g);
 726:         ok = true;
 727:       }
 728: 
 729:     if (!ok)
 730:       {
 731:         if (value != null)
 732:           {
 733:             MARSHAL m = new MARSHAL(value.getClass().getName()
 734:             + " must be Streamable, CustomMarshal or Serializable");
 735:             m.minor = Minor.UnsupportedValue;
 736:             throw m;
 737:           }
 738:         else
 739:           {
 740:             MARSHAL m = new MARSHAL("Unable to instantiate " + id + ":" + list(ids)
 741:             + " helper " + helper);
 742:             m.minor = Minor.UnsupportedValue;
 743:             throw m;
 744:           }
 745:       }
 746:     else
 747:       return (Serializable) value;
 748:   }
 749: 
 750:   /**
 751:    * Conveniency method to list ids in exception reports.
 752:    */
 753:   static String list(String[] s)
 754:   {
 755:     if (s == null)
 756:       return "null";
 757:     else
 758:       {
 759:         CPStringBuilder b = new CPStringBuilder("{");
 760:         for (int i = 0; i < s.length; i++)
 761:           {
 762:             b.append(s[i]);
 763:             b.append(" ");
 764:           }
 765:         b.append("}");
 766:         return b.toString();
 767:       }
 768:   }
 769: 
 770:   /**
 771:    * Write the value base into the given stream.
 772:    *
 773:    * @param output a stream to write to.
 774:    *
 775:    * @param value a value type object, must be either Streamable or
 776:    * CustomMarshal.
 777:    *
 778:    * @throws MARSHAL if the writing failed due any reason.
 779:    */
 780:   public static void write(OutputStream output, Serializable value)
 781:   {
 782:     // Write null if this is a null value.
 783:     if (value == null)
 784:       output.write_long(vt_NULL);
 785:     else if (value instanceof String)
 786:       write(output, value, m_StringValueHelper);
 787:     else
 788:       write(output, value, value.getClass());
 789:   }
 790: 
 791:   /**
 792:    * Write the value base into the given stream, stating that it is an instance
 793:    * of the given class.
 794:    *
 795:    * @param output a stream to write to.
 796:    *
 797:    * @param value a value to write.
 798:    *
 799:    * @throws MARSHAL if the writing failed due any reason.
 800:    */
 801:   public static void write(OutputStream output, Serializable value,
 802:     Class substitute)
 803:   {
 804:     // Write null if this is a null value.
 805:     if (value == null)
 806:       output.write_long(vt_NULL);
 807:     else if (value instanceof String || substitute == String.class)
 808:       writeString(output, value);
 809:     else
 810:       {
 811:         String vId = ObjectCreator.getRepositoryId(value.getClass());
 812:         if (substitute == null || value.getClass().equals(substitute))
 813:           write_instance(output, value, vId, getHelper(value.getClass(), vId));
 814:         else
 815:           {
 816:             String vC = ObjectCreator.getRepositoryId(substitute);
 817:             String[] ids = new String[] { vId, vC };
 818:             BoxedValueHelper h = getHelper(substitute.getClass(), ids);
 819:             // If the helper is available, it is also responsible for
 820:             // providing the repository Id. Otherwise, write both
 821:             // ids.
 822:             if (h == null)
 823:               write_instance(output, value, ids, null);
 824:             else
 825:               write_instance(output, value, h.get_id(), null);
 826:           }
 827:       }
 828:   }
 829: 
 830:   /**
 831:    * Write the value base into the given stream, supplementing it with an array
 832:    * of the provided repository ids plus the repository id, derived from the
 833:    * passed value.
 834:    *
 835:    * @param output a stream to write to.
 836:    *
 837:    * @param value a value to write.
 838:    *
 839:    * @throws MARSHAL if the writing failed due any reason.
 840:    */
 841:   public static void write(OutputStream output, Serializable value,
 842:     String[] multiple_ids)
 843:   {
 844:     // Write null if this is a null value.
 845:     if (value == null)
 846:       output.write_long(vt_NULL);
 847:     else
 848:       {
 849:         String[] ids = new String[multiple_ids.length + 1];
 850:         ids[0] = ObjectCreator.getRepositoryId(value.getClass());
 851:         System.arraycopy(multiple_ids, 0, ids, 1, multiple_ids.length);
 852:         BoxedValueHelper h = getHelper(value.getClass(), ids);
 853:         write_instance(output, value, ids, h);
 854:       }
 855:   }
 856: 
 857:   /**
 858:    * Write value when its repository Id is explicitly given. Only this Id is
 859:    * written, the type of value is not taken into consideration.
 860:    *
 861:    * @param output an output stream to write into.
 862:    * @param value a value to write.
 863:    * @param id a value repository id.
 864:    */
 865:   public static void write(OutputStream output, Serializable value, String id)
 866:   {
 867:     if (value == null)
 868:       output.write_long(vt_NULL);
 869:     else
 870:       write_instance(output, value, id, getHelper(value.getClass(), id));
 871:   }
 872: 
 873:   /**
 874:    * Write standard value type header, followed by contents, produced by the
 875:    * boxed value helper.
 876:    *
 877:    * @param output the stream to write to.
 878:    * @param value the value to write, can be null.
 879:    * @param helper the helper that writes the value content if it is not null
 880:    * (must be provided for this method).
 881:    */
 882:   public static void write(OutputStream output, Serializable value,
 883:     BoxedValueHelper helper)
 884:   {
 885:     if (helper == null)
 886:       throw new AssertionError("Helper must be provided");
 887:     if (value == null)
 888:       output.write_long(vt_NULL);
 889:     else
 890:       write_instance(output, value, helper.get_id(), helper);
 891:   }
 892: 
 893:   /**
 894:    * Write the parameter that is surely a string and not null.
 895:    */
 896:   private static void writeString(OutputStream output, Serializable string)
 897:   {
 898:     write_instance(output, string, m_StringValueHelper.get_id(),
 899:       m_StringValueHelper);
 900:   }
 901: 
 902:   /**
 903:    * Write value when its repository Id is explicitly given. Does not handle
 904:    * null.
 905:    *
 906:    * @param output an output stream to write into.
 907:    * @param value a value to write.
 908:    * @param ids a value repository id (can be either single string or string
 909:    * array).
 910:    * @param helper a helper, writing object - specifical part. Can be null if
 911:    * the value should be written using other methods.
 912:    */
 913:   static void write_instance(OutputStream output, Serializable value,
 914:     Object ids, BoxedValueHelper helper)
 915:   {
 916:     gnuValueStream rout = null;
 917:     gnuRuntime runtime = null;
 918: 
 919:     try
 920:       {
 921:         if (output instanceof gnuValueStream)
 922:           {
 923:             int position;
 924:             rout = (gnuValueStream) output;
 925:             runtime = rout.getRunTime();
 926: 
 927:             if (runtime == null)
 928:               {
 929:                 runtime = new gnuRuntime(null, value);
 930:                 rout.setRunTime(runtime);
 931:                 rout.getRunTime().objectWritten(value,
 932:                   position = rout.getPosition());
 933:               }
 934:             else if (runtime.target == value)
 935:               {
 936:                 if (!writeSelf(output, value))
 937:                   throw new InternalError("Recursive helper call for "
 938:                     + value.getClass().getName());
 939:                 return;
 940:               }
 941:             else
 942:               {
 943:                 position = runtime.isWrittenAt(value);
 944:                 if (position >= 0)
 945:                   {
 946:                     // The object was already written.
 947:                     output.write_long(vt_INDIRECTION);
 948:                     output.write_long(position - rout.getPosition());
 949:                     // Replacing object write data by indirection reference.
 950:                     return;
 951:                   }
 952:                 else
 953:                   {
 954:                     runtime.objectWritten(value, position = rout.getPosition());
 955:                   }
 956:               }
 957:           }
 958: 
 959:         int value_tag = vt_VALUE_TAG;
 960: 
 961:         if (ids instanceof String)
 962:           value_tag |= vf_ID;
 963:         else if (ids instanceof String[])
 964:           // OMG standard requires to set both flags.
 965:           value_tag |= vf_MULTIPLE_IDS | vf_ID;
 966: 
 967:         int chunkSizeLocation;
 968: 
 969:         OutputStream outObj;
 970: 
 971:         if (USE_CHUNKING)
 972:           {
 973:             // Wrap the value being written into one chunk (makes sense only for
 974:             // compatibility reasons).
 975:             outObj = output;
 976:             value_tag |= vf_CHUNKING;
 977:           }
 978:         else
 979:           outObj = output;
 980: 
 981:         output.write_long(value_tag);
 982: 
 983:         if ((value_tag & vf_MULTIPLE_IDS) != 0)
 984:           write_string_array(output, (String[]) ids);
 985:         else if ((value_tag & vf_ID) != 0)
 986:           write_string(output, (String) ids);
 987: 
 988:         if (USE_CHUNKING)
 989:           {
 990:             // So far, write 0x55555555 instead of the chunk size (alignment may
 991:             // take place).
 992:             output.write_long(0x55555555);
 993:             // If the chunking is involved, the chunk size must be written here.
 994:             chunkSizeLocation = rout.getPosition() - INT_SIZE;
 995:           }
 996:         else
 997:           // Not in use for this case.
 998:           chunkSizeLocation = -1;
 999: 
1000:         writeValue(outObj, value, helper);
1001: 
1002:         if (USE_CHUNKING)
1003:           {
1004:             // Write the chunk size where the place for it was reserved.
1005:             int chunkSize = rout.getPosition() - chunkSizeLocation - INT_SIZE;
1006:             int current = rout.getPosition();
1007:             rout.seek(chunkSizeLocation);
1008:             output.write_long(chunkSize);
1009:             rout.seek(current);
1010: 
1011:             // The end of record marker.
1012:             output.write_long(-1);
1013:           }
1014:       }
1015:     finally
1016:       {
1017:         if (runtime != null)
1018:           runtime.target = null;
1019:       }
1020:   }
1021: 
1022:   /**
1023:    * Write value (after header).
1024:    */
1025:   static void writeValue(OutputStream output, Serializable value,
1026:     BoxedValueHelper helper)
1027:   {
1028:     ((gnuValueStream) output).getRunTime().target = value;
1029:     if (helper != null)
1030:       helper.write_value(output, value);
1031:     else if (!writeSelf(output, value))
1032:       {
1033:         // Try to find helper via class loader.
1034:         boolean ok = false;
1035: 
1036:         if (!ok)
1037:           {
1038:             if (output instanceof BufferedCdrOutput)
1039:               {
1040:                 BufferedCdrOutput b = (BufferedCdrOutput) output;
1041:                 if (b.runtime == null)
1042:                   b.runtime = new gnuRuntime(null, value);
1043:               }
1044: 
1045:             handler.writeValue(output, value);
1046:           }
1047:       }
1048:   }
1049: 
1050:   /**
1051:    * Try to write value supposing that it implements self-streamable interfaces.
1052:    * Return false if it does not or true on success.
1053:    */
1054:   static boolean writeSelf(OutputStream output, Serializable value)
1055:   {
1056:     // User defined write method is present.
1057:     if (value instanceof CustomMarshal)
1058:       {
1059:         ((CustomMarshal) value).marshal((DataOutputStream) output);
1060:         return true;
1061:       }
1062:     else if (value instanceof Streamable)
1063:       {
1064:         ((Streamable) value)._write(output);
1065:         return true;
1066:       }
1067:     return false;
1068:   }
1069: 
1070:   /**
1071:    * Read the indirection data and return the object that was already written to
1072:    * this stream.
1073:    *
1074:    * @param an_input the input stream, must be BufferredCdrInput.
1075:    */
1076:   static Serializable readIndirection(InputStream an_input)
1077:   {
1078:     if (!(an_input instanceof gnuValueStream))
1079:       throw new NO_IMPLEMENT(gnuValueStream.class.getName()
1080:         + " expected as parameter");
1081: 
1082:     gnuValueStream in = (gnuValueStream) an_input;
1083: 
1084:     int current_pos = in.getPosition();
1085: 
1086:     int offset = an_input.read_long();
1087:     if (offset > -INT_SIZE)
1088:       {
1089:         MARSHAL m = new MARSHAL("Indirection tag refers to " + offset
1090:         + " (must be less than -" + INT_SIZE + ")");
1091:         m.minor = Minor.Offset;
1092:         throw m;
1093:       }
1094: 
1095:     int stored_at = current_pos + offset;
1096: 
1097:     if (in.getRunTime() == null)
1098:       {
1099:         MARSHAL m = new MARSHAL(stored_at + " offset " + offset + ": not written");
1100:         m.minor = Minor.Value;
1101:         throw m;
1102:       }
1103: 
1104:     return (Serializable) in.getRunTime().isObjectWrittenAt(stored_at, offset);
1105:   }
1106: 
1107:   /**
1108:    * Check the passed value tag for correctness.
1109:    *
1110:    * @param value_tag a tag to check, must be between 0x7fffff00 and 0x7fffffff
1111:    *
1112:    * @throws MARSHAL if the tag is outside this interval.
1113:    */
1114:   static void checkTag(int value_tag)
1115:   {
1116:     if ((value_tag < 0x7fffff00 || value_tag > 0x7fffffff)
1117:       && value_tag != vt_NULL && value_tag != vt_INDIRECTION)
1118:       {
1119:         MARSHAL m = new MARSHAL("Invalid value record, unsupported header tag: "
1120:         + value_tag + " (0x" + Integer.toHexString(value_tag) + ")");
1121:         m.minor = Minor.ValueHeaderTag;
1122:         throw m;
1123:       }
1124: 
1125:     if ((value_tag & vf_MULTIPLE_IDS) != 0 && (value_tag & vf_ID) == 0)
1126:       {
1127:         MARSHAL m = new MARSHAL("Invalid value record header flag combination (0x"
1128:         + Integer.toHexString(value_tag) + ")");
1129:         m.minor = Minor.ValueHeaderFlags;
1130:         throw m;
1131:       }
1132:   }
1133: 
1134:   /**
1135:    * Throw MARSHAL.
1136:    */
1137:   static void throwIt(String msg, String id1, String id2, Throwable e)
1138:     throws MARSHAL
1139:   {
1140:     MARSHAL m = new MARSHAL(msg + ":'" + id1 + "' versus '" + id2 + "'");
1141:     if (e != null)
1142:       m.initCause(e);
1143:     m.minor = Minor.Value;
1144:     throw m;
1145:   }
1146: 
1147:   /**
1148:    * Load class by name and create the instance.
1149:    */
1150:   static Object createInstance(String id, String[] ids, String codebase)
1151:   {
1152:     Object o = null;
1153: 
1154:     if (id != null)
1155:       o = _createInstance(id, codebase);
1156: 
1157:     if (ids != null)
1158:       for (int i = 0; i < ids.length && o == null; i++)
1159:         o = _createInstance(ids[i], codebase);
1160:     return o;
1161:   }
1162: 
1163:   static Object _createInstance(String id, String codebase)
1164:   {
1165:     if (id == null)
1166:       return null;
1167:     if (id.equals(StringValueHelper.id()))
1168:       return "";
1169:     StringTokenizer st = new StringTokenizer(id, ":");
1170: 
1171:     String prefix = st.nextToken();
1172:     if (prefix.equalsIgnoreCase("IDL"))
1173:       return ObjectCreator.Idl2Object(id);
1174:     else if (prefix.equalsIgnoreCase("RMI"))
1175:       {
1176:         String className = st.nextToken();
1177:         String hashCode = st.nextToken();
1178:         String sid = null;
1179:         if (st.hasMoreElements())
1180:           sid = st.nextToken();
1181: 
1182:         try
1183:           {
1184:             Class objectClass = Util.loadClass(className, codebase,
1185:               Vio.class.getClassLoader());
1186: 
1187:             String rid = ObjectCreator.getRepositoryId(objectClass);
1188: 
1189:             if (!rid.equals(id))
1190:               {
1191:                 // If direct string comparison fails, compare by meaning.
1192:                 StringTokenizer st2 = new StringTokenizer(rid, ":");
1193:                 if (!st2.nextToken().equals("RMI"))
1194:                   throw new InternalError("RMI format expected: '" + rid + "'");
1195:                 if (!st2.nextToken().equals(className))
1196:                   throwIt("Class name mismatch", id, rid, null);
1197: 
1198:                 try
1199:                   {
1200:                     long h1 = Long.parseLong(hashCode, 16);
1201:                     long h2 = Long.parseLong(st2.nextToken(), 16);
1202:                     if (h1 != h2)
1203:                       throwIt("Hashcode mismatch", id, rid, null);
1204: 
1205:                     if (sid != null && st2.hasMoreTokens())
1206:                       {
1207:                         long s1 = Long.parseLong(hashCode, 16);
1208:                         long s2 = Long.parseLong(st2.nextToken(), 16);
1209:                         if (s1 != s2)
1210:                           throwIt("serialVersionUID mismatch", id, rid, null);
1211:                       }
1212:                   }
1213:                 catch (NumberFormatException e)
1214:                   {
1215:                     throwIt("Invalid hashcode or svuid format: ", id, rid, e);
1216:                   }
1217:               }
1218: 
1219:             // Low - level instantiation required here.
1220:             return instantiateAnyWay(objectClass);
1221:           }
1222:         catch (Exception ex)
1223:           {
1224:             MARSHAL m = new MARSHAL("Unable to instantiate " + id);
1225:             m.minor = Minor.Instantiation;
1226:             m.initCause(ex);
1227:             throw m;
1228:           }
1229:       }
1230:     else
1231:       throw new NO_IMPLEMENT("Unsupported prefix " + prefix + ":");
1232:   }
1233: 
1234:   /**
1235:    * Read string, expecting the probable indirection.
1236:    */
1237:   static String read_string(InputStream input)
1238:   {
1239:     gnuValueStream g = (gnuValueStream) input;
1240:     int previous = g.getPosition();
1241:     int l = input.read_long();
1242:     if (l != vt_INDIRECTION)
1243:       {
1244:         g.seek(previous);
1245:         String s = input.read_string();
1246:         if (g.getRunTime() == null)
1247:           g.setRunTime(new gnuRuntime(null, null));
1248:         g.getRunTime().singleIdWritten(s, previous);
1249:         return s;
1250:       }
1251:     else
1252:       {
1253:         gnuRuntime r = g.getRunTime();
1254:         int base = g.getPosition();
1255:         int delta = input.read_long();
1256:         if (r == null)
1257:           {
1258:             previous = g.getPosition();
1259:             g.seek(base + delta);
1260:             String indir = input.read_string();
1261:             g.seek(previous);
1262:             return indir;
1263:           }
1264:         else
1265:           {
1266:             return (String) r.isObjectWrittenAt(base + delta, delta);
1267:           }
1268:       }
1269:   }
1270: 
1271:   /**
1272:    * Read string array, expecting the probable indirection.
1273:    */
1274:   static String[] read_string_array(InputStream input)
1275:   {
1276:     gnuValueStream g = (gnuValueStream) input;
1277:     int previous = g.getPosition();
1278:     int l = input.read_long();
1279:     if (l != vt_INDIRECTION)
1280:       {
1281:         g.seek(previous);
1282:         String[] s = StringSeqHelper.read(input);
1283:         if (g.getRunTime() == null)
1284:           g.setRunTime(new gnuRuntime(null, null));
1285:         g.getRunTime().objectWritten(s, previous);
1286:         return s;
1287:       }
1288:     else
1289:       {
1290:         gnuRuntime r = g.getRunTime();
1291:         int base = g.getPosition();
1292:         int delta = input.read_long();
1293:         if (r == null)
1294:           {
1295:             previous = g.getPosition();
1296:             g.seek(base + delta);
1297:             String[] indir = StringSeqHelper.read(input);
1298:             g.seek(previous);
1299:             return indir;
1300:           }
1301:         else
1302:           {
1303:             return (String[]) r.isObjectWrittenAt(base + delta, delta);
1304:           }
1305:       }
1306:   }
1307: 
1308:   /**
1309:    * Write repository Id, probably shared.
1310:    */
1311:   static void write_string(OutputStream output, String id)
1312:   {
1313:     if (output instanceof gnuValueStream)
1314:       {
1315:         gnuValueStream b = (gnuValueStream) output;
1316:         if (b != null)
1317:           {
1318:             int written = b.getRunTime().idWrittenAt(id);
1319:             if (written >= 0)
1320:               {
1321:                 // Reuse existing id record.
1322:                 output.write_long(vt_INDIRECTION);
1323:                 int p = b.getPosition();
1324:                 output.write_long(written - p);
1325:               }
1326:             else
1327:               {
1328:                 b.getRunTime().singleIdWritten(id, b.getPosition());
1329:                 output.write_string(id);
1330:               }
1331:           }
1332:       }
1333:     else
1334:       output.write_string(id);
1335:   }
1336: 
1337:   /**
1338:    * Write repository Id, probably shared.
1339:    */
1340:   static void write_string_array(OutputStream output, String[] ids)
1341:   {
1342:     if (output instanceof gnuValueStream)
1343:       {
1344:         gnuValueStream b = (gnuValueStream) output;
1345:         if (b != null)
1346:           {
1347:             int written = b.getRunTime().idWrittenAt(ids);
1348:             if (written >= 0)
1349:               {
1350:                 // Reuse existing id record.
1351:                 output.write_long(vt_INDIRECTION);
1352:                 int p = b.getPosition();
1353:                 output.write_long(written - p);
1354:               }
1355:             else
1356:               {
1357:                 b.getRunTime().multipleIdsWritten(ids, b.getPosition());
1358:                 StringSeqHelper.write(output, ids);
1359:               }
1360:           }
1361:       }
1362:     else
1363:       StringSeqHelper.write(output, ids);
1364:   }
1365: 
1366:   /**
1367:    * Get the helper that could write the given object, or null if no pre-defined
1368:    * helper available for this object.
1369:    */
1370:   public static BoxedValueHelper getHelper(Class x, Object ids)
1371:   {
1372:     if (x != null && x.equals(String.class))
1373:       return m_StringValueHelper;
1374:     else if (x != null && x.isArray())
1375:       return new ArrayValueHelper(x);
1376:     else if (ids instanceof String)
1377:       return locateHelper((String) ids);
1378:     else if (ids instanceof String[])
1379:       {
1380:         String[] ia = (String[]) ids;
1381:         BoxedValueHelper h;
1382:         for (int i = 0; i < ia.length; i++)
1383:           {
1384:             h = locateHelper(ia[i]);
1385:             if (h != null)
1386:               return h;
1387:           }
1388:         return null;
1389:       }
1390:     else
1391:       return null;
1392:   }
1393: 
1394:   /**
1395:    * Get the helper that could write the given object, or null if no pre-defined
1396:    * helper available for this object.
1397:    */
1398:   public static BoxedValueHelper getHelper(Class x, String id)
1399:   {
1400:     if (x != null && x.equals(String.class))
1401:       return m_StringValueHelper;
1402:     else if (x != null && x.isArray())
1403:       return new ArrayValueHelper(x);
1404:     else
1405:       return locateHelper(id);
1406:   }
1407: 
1408:   /**
1409:    * Try to locate helper from the repository id.
1410:    */
1411:   static BoxedValueHelper locateHelper(String id)
1412:   {
1413:     if (id != null)
1414:       {
1415:         if (id.equals(m_StringValueHelper.get_id()))
1416:           return m_StringValueHelper;
1417:         else
1418:         // Try to locate helper for IDL type.
1419:         if (id.startsWith("IDL:"))
1420:           {
1421:             try
1422:               {
1423:                 Class helperClass = ObjectCreator.findHelper(id);
1424:                 if (BoxedValueHelper.class.isAssignableFrom(helperClass))
1425:                   return (BoxedValueHelper) helperClass.newInstance();
1426:                 else if (helperClass != null)
1427:                   return new IDLTypeHelper(helperClass);
1428:                 else
1429:                   return null;
1430:               }
1431:             catch (Exception ex)
1432:               {
1433:                 return null;
1434:               }
1435:           }
1436:       }
1437:     return null;
1438:   }
1439: 
1440:   /**
1441:    * Get the current position.
1442:    */
1443:   static int getCurrentPosition(InputStream x)
1444:   {
1445:     if (x instanceof gnuValueStream)
1446:       return ((gnuValueStream) x).getPosition();
1447:     else
1448:       return 0;
1449:   }
1450: 
1451:   /**
1452:    * Instantiate an instance of this class anyway; also in the case when it has
1453:    * no parameterless or any other constructor. The fields will be assigned
1454:    * while reading the class from the stream.
1455:    *
1456:    * @param clazz a class for that the instance should be instantiated.
1457:    */
1458:   public static Object instantiateAnyWay(Class clazz)
1459:     throws Exception
1460:   {
1461:     Class first_nonserial = clazz;
1462: 
1463:     while (Serializable.class.isAssignableFrom(first_nonserial)
1464:       || Modifier.isAbstract(first_nonserial.getModifiers()))
1465:       first_nonserial = first_nonserial.getSuperclass();
1466: 
1467:     final Class local_constructor_class = first_nonserial;
1468: 
1469:     Constructor constructor = local_constructor_class.getDeclaredConstructor(new Class[0]);
1470: 
1471:     return VMVio.allocateObject(clazz, constructor.getDeclaringClass(),
1472:       constructor);
1473:   }
1474: }