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 package com.sun.corba.se.impl.encoding;
  26 
  27 import org.omg.CORBA.CompletionStatus;
  28 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  29 import com.sun.corba.se.impl.encoding.CodeSetConversion;
  30 
  31 public class CDROutputStream_1_1 extends CDROutputStream_1_0
  32 {
  33     // This is used to keep indirections working across fragments.  When added
  34     // to the current bbwi.position(), the result is the current position
  35     // in the byte stream without any fragment headers.
  36     //
  37     // It is equal to the following:
  38     //
  39     // n = number of buffers (0 is original buffer, 1 is first fragment, etc)
  40     //
  41     // n == 0, fragmentOffset = 0
  42     //
  43     // n > 0, fragmentOffset
  44     //          = sum i=[1,n] { bbwi_i-1_.size - buffer i header length }
  45     //
  46     protected int fragmentOffset = 0;
  47 
  48     protected void alignAndReserve(int align, int n) {
  49 
  50         // Notice that in 1.1, we won't end a fragment with
  51         // alignment padding.  We also won't guarantee that
  52         // our fragments end on evenly divisible 8 byte
  53         // boundaries.  There may be alignment
  54         // necessary with the header of the next fragment
  55         // since the header isn't aligned on an 8 byte
  56         // boundary, so we have to calculate it twice.
  57 
  58         int alignment = computeAlignment(align);
  59 
  60         if (bbwi.position() + n + alignment > bbwi.buflen) {
  61             grow(align, n);
  62 
  63             // Must recompute the alignment after a grow.
  64             // In the case of fragmentation, the alignment
  65             // calculation may no longer be correct.
  66 
  67             // People shouldn't be able to set their fragment
  68             // sizes so small that the fragment header plus
  69             // this alignment fills the entire buffer.
  70             alignment = computeAlignment(align);
  71         }
  72 
  73         bbwi.position(bbwi.position() + alignment);
  74     }
  75 
  76     protected void grow(int align, int n) {
  77         // Save the current size for possible post-fragmentation calculation
  78         int oldSize = bbwi.position();
  79 
  80         super.grow(align, n);
  81 
  82         // At this point, if we fragmented, we should have a ByteBufferWithInfo
  83         // with the fragment header already marshalled.  The size and length fields
  84         // should be updated accordingly, and the fragmented flag should be set.
  85         if (bbwi.fragmented) {
  86 
  87             // Clear the flag
  88             bbwi.fragmented = false;
  89 
  90             // Update fragmentOffset so indirections work properly.
  91             // At this point, oldSize is the entire length of the
  92             // previous buffer.  bbwi.position() is the length of the
  93             // fragment header of this buffer.
  94             fragmentOffset += (oldSize - bbwi.position());
  95         }
  96     }
  97 
  98     public int get_offset() {
  99         return bbwi.position() + fragmentOffset;
 100     }
 101 
 102     public GIOPVersion getGIOPVersion() {
 103         return GIOPVersion.V1_1;
 104     }
 105 
 106     public void write_wchar(char x)
 107     {
 108         // In GIOP 1.1, interoperability with wchar is limited
 109         // to 2 byte fixed width encodings.  CORBA formal 99-10-07 15.3.1.6.
 110         // Note that the following code prohibits UTF-16 with a byte
 111         // order marker (which would result in 4 bytes).
 112         CodeSetConversion.CTBConverter converter = getWCharConverter();
 113 
 114         converter.convert(x);
 115 
 116         if (converter.getNumBytes() != 2)
 117             throw wrapper.badGiop11Ctb(CompletionStatus.COMPLETED_MAYBE);
 118 
 119         alignAndReserve(converter.getAlignment(),
 120                         converter.getNumBytes());
 121 
 122         parent.write_octet_array(converter.getBytes(),
 123                                  0,
 124                                  converter.getNumBytes());
 125     }
 126 
 127     public void write_wstring(String value)
 128     {
 129         if (value == null) {
 130             throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
 131         }
 132 
 133         // The length is the number of code points (which are 2 bytes each)
 134         // including the 2 byte null.  See CORBA formal 99-10-07 15.3.2.7.
 135 
 136         int len = value.length() + 1;
 137 
 138         write_long(len);
 139 
 140         CodeSetConversion.CTBConverter converter = getWCharConverter();
 141 
 142         converter.convert(value);
 143 
 144         internalWriteOctetArray(converter.getBytes(), 0, converter.getNumBytes());
 145 
 146         // Write the 2 byte null ending
 147         write_short((short)0);
 148     }
 149 }