CDROutputStream_1_1.java revision 608:7e06bf1dcb09
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 */
25package com.sun.corba.se.impl.encoding;
26
27import org.omg.CORBA.CompletionStatus;
28import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
29import com.sun.corba.se.impl.encoding.CodeSetConversion;
30
31public 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}
150