CDROutputObject.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2001, 2004, 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
26package com.sun.corba.se.impl.encoding;
27
28import java.io.IOException;
29import java.nio.ByteBuffer;
30
31import org.omg.CORBA.Any;
32import org.omg.CORBA.Principal;
33import org.omg.CORBA.TypeCode;
34import org.omg.CORBA.portable.InputStream;
35
36import com.sun.corba.se.pept.encoding.OutputObject;
37import com.sun.corba.se.pept.protocol.MessageMediator;
38
39import com.sun.corba.se.spi.encoding.CorbaOutputObject ;
40import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
41import com.sun.corba.se.spi.orb.ORB;
42import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
43import com.sun.corba.se.pept.transport.ByteBufferPool;
44import com.sun.corba.se.spi.transport.CorbaConnection;
45import com.sun.corba.se.spi.logging.CORBALogDomains;
46
47import com.sun.corba.se.spi.servicecontext.ServiceContexts;
48import com.sun.corba.se.impl.encoding.BufferManagerFactory;
49import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
50import com.sun.corba.se.impl.encoding.CDROutputStream;
51import com.sun.corba.se.impl.encoding.CDROutputStream_1_0;
52import com.sun.corba.se.impl.encoding.CodeSetConversion;
53import com.sun.corba.se.impl.encoding.CodeSetComponentInfo;
54import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
55import com.sun.corba.se.impl.orbutil.ORBUtility;
56import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
57import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
58import com.sun.corba.se.impl.logging.ORBUtilSystemException;
59import com.sun.corba.se.impl.logging.OMGSystemException;
60
61/**
62 * @author Harold Carr
63 */
64public class CDROutputObject extends CorbaOutputObject
65{
66    private Message header;
67    private ORB orb;
68    private ORBUtilSystemException wrapper;
69    private OMGSystemException omgWrapper;
70
71    // REVISIT - only used on sendCancelRequest.
72    private CorbaConnection connection;
73
74    private CDROutputObject(
75        ORB orb, GIOPVersion giopVersion, Message header,
76        BufferManagerWrite manager, byte streamFormatVersion,
77        CorbaMessageMediator mediator)
78    {
79        super(orb, giopVersion, header.getEncodingVersion(),
80              false, manager, streamFormatVersion,
81              ((mediator != null && mediator.getConnection() != null) ?
82               ((CorbaConnection)mediator.getConnection()).
83                     shouldUseDirectByteBuffers() : false));
84
85        this.header = header;
86        this.orb = orb;
87        this.wrapper = ORBUtilSystemException.get( orb, CORBALogDomains.RPC_ENCODING ) ;
88        this.omgWrapper = OMGSystemException.get( orb, CORBALogDomains.RPC_ENCODING ) ;
89
90        getBufferManager().setOutputObject(this);
91        this.corbaMessageMediator = mediator;
92    }
93
94    public CDROutputObject(ORB orb,
95                           MessageMediator messageMediator,
96                           Message header,
97                           byte streamFormatVersion)
98    {
99        this(
100            orb,
101            ((CorbaMessageMediator)messageMediator).getGIOPVersion(),
102            header,
103            BufferManagerFactory.newBufferManagerWrite(
104                ((CorbaMessageMediator)messageMediator).getGIOPVersion(),
105                header.getEncodingVersion(),
106                orb),
107            streamFormatVersion,
108            (CorbaMessageMediator)messageMediator);
109    }
110
111    // NOTE:
112    // Used in SharedCDR (i.e., must be grow).
113    // Used in msgtypes test.
114    public CDROutputObject(ORB orb,
115                           MessageMediator messageMediator,
116                           Message header,
117                           byte streamFormatVersion,
118                           int strategy)
119    {
120        this(
121            orb,
122            ((CorbaMessageMediator)messageMediator).getGIOPVersion(),
123            header,
124            BufferManagerFactory.
125                newBufferManagerWrite(strategy,
126                                      header.getEncodingVersion(),
127                                      orb),
128            streamFormatVersion,
129            (CorbaMessageMediator)messageMediator);
130    }
131
132    // REVISIT
133    // Used on sendCancelRequest.
134    // Used for needs addressing mode.
135    public CDROutputObject(ORB orb, CorbaMessageMediator mediator,
136                           GIOPVersion giopVersion,
137                           CorbaConnection connection, Message header,
138                           byte streamFormatVersion)
139    {
140        this(
141            orb,
142            giopVersion,
143            header,
144            BufferManagerFactory.
145            newBufferManagerWrite(giopVersion,
146                                  header.getEncodingVersion(),
147                                  orb),
148            streamFormatVersion,
149            mediator);
150        this.connection = connection ;
151    }
152
153    // XREVISIT
154    // Header should only be in message mediator.
155    // Another possibility: merge header and message mediator.
156    // REVISIT - make protected once all encoding together
157    public Message getMessageHeader() {
158        return header;
159    }
160
161    public final void finishSendingMessage() {
162        getBufferManager().sendMessage();
163    }
164
165    /**
166     * Write the contents of the CDROutputStream to the specified
167     * output stream.  Has the side-effect of pushing any current
168     * Message onto the Message list.
169     * @param s The output stream to write to.
170     */
171    public void writeTo(CorbaConnection connection)
172        throws java.io.IOException
173    {
174
175        //
176        // Update the GIOP MessageHeader size field.
177        //
178
179        ByteBufferWithInfo bbwi = getByteBufferWithInfo();
180
181        getMessageHeader().setSize(bbwi.byteBuffer, bbwi.getSize());
182
183        if (orb() != null) {
184            if (((ORB)orb()).transportDebugFlag) {
185                dprint(".writeTo: " + connection);
186            }
187            if (((ORB)orb()).giopDebugFlag) {
188                CDROutputStream_1_0.printBuffer(bbwi);
189            }
190        }
191        bbwi.byteBuffer.position(0).limit(bbwi.getSize());
192        connection.write(bbwi.byteBuffer);
193    }
194
195    /** overrides create_input_stream from CDROutputStream */
196    public org.omg.CORBA.portable.InputStream create_input_stream()
197    {
198        // XREVISIT
199        return null;
200        //return new XIIOPInputStream(orb(), getByteBuffer(), getIndex(),
201            //isLittleEndian(), getMessageHeader(), conn);
202    }
203
204    public CorbaConnection getConnection()
205    {
206        // REVISIT - only set when doing sendCancelRequest.
207        if (connection != null) {
208            return connection;
209        }
210        return (CorbaConnection) corbaMessageMediator.getConnection();
211    }
212
213    // XREVISIT - If CDROutputObject doesn't live in the iiop
214    // package, it will need this, here, to give package access
215    // to xgiop.
216    // REVISIT - make protected once all encoding together
217    public final ByteBufferWithInfo getByteBufferWithInfo() {
218        return super.getByteBufferWithInfo();
219    }
220
221    // REVISIT - make protected once all encoding together
222    public final void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
223        super.setByteBufferWithInfo(bbwi);
224    }
225
226    /**
227     * Override the default CDR factory behavior to get the
228     * negotiated code sets from the connection.
229     *
230     * These are only called once per message, the first time needed.
231     *
232     * In the local case, there is no Connection, so use the
233     * local code sets.
234     */
235    protected CodeSetConversion.CTBConverter createCharCTBConverter() {
236        CodeSetComponentInfo.CodeSetContext codesets = getCodeSets();
237
238        // If the connection doesn't have its negotiated
239        // code sets by now, fall back on the defaults defined
240        // in CDRInputStream.
241        if (codesets == null)
242            return super.createCharCTBConverter();
243
244        OSFCodeSetRegistry.Entry charSet
245            = OSFCodeSetRegistry.lookupEntry(codesets.getCharCodeSet());
246
247        if (charSet == null)
248            throw wrapper.unknownCodeset( charSet ) ;
249
250        return CodeSetConversion.impl().getCTBConverter(charSet,
251                                                        isLittleEndian(),
252                                                        false);
253    }
254
255    protected CodeSetConversion.CTBConverter createWCharCTBConverter() {
256
257        CodeSetComponentInfo.CodeSetContext codesets = getCodeSets();
258
259        // If the connection doesn't have its negotiated
260        // code sets by now, we have to throw an exception.
261        // See CORBA formal 00-11-03 13.9.2.6.
262        if (codesets == null) {
263            if (getConnection().isServer())
264                throw omgWrapper.noClientWcharCodesetCtx() ;
265            else
266                throw omgWrapper.noServerWcharCodesetCmp() ;
267        }
268
269        OSFCodeSetRegistry.Entry wcharSet
270            = OSFCodeSetRegistry.lookupEntry(codesets.getWCharCodeSet());
271
272        if (wcharSet == null)
273            throw wrapper.unknownCodeset( wcharSet ) ;
274
275        boolean useByteOrderMarkers
276            = ((ORB)orb()).getORBData().useByteOrderMarkers();
277
278        // With UTF-16:
279        //
280        // For GIOP 1.2, we can put byte order markers if we want to, and
281        // use the default of big endian otherwise.  (See issue 3405b)
282        //
283        // For GIOP 1.1, we don't use BOMs and use the endianness of
284        // the stream.
285        if (wcharSet == OSFCodeSetRegistry.UTF_16) {
286            if (getGIOPVersion().equals(GIOPVersion.V1_2)) {
287                return CodeSetConversion.impl().getCTBConverter(wcharSet,
288                                                                false,
289                                                                useByteOrderMarkers);
290            }
291
292            if (getGIOPVersion().equals(GIOPVersion.V1_1)) {
293                return CodeSetConversion.impl().getCTBConverter(wcharSet,
294                                                                isLittleEndian(),
295                                                                false);
296            }
297        }
298
299        // In the normal case, let the converter system handle it
300        return CodeSetConversion.impl().getCTBConverter(wcharSet,
301                                                        isLittleEndian(),
302                                                        useByteOrderMarkers);
303    }
304
305    // If we're local and don't have a Connection, use the
306    // local code sets, otherwise get them from the connection.
307    // If the connection doesn't have negotiated code sets
308    // yet, then we use ISO8859-1 for char/string and wchar/wstring
309    // are illegal.
310    private CodeSetComponentInfo.CodeSetContext getCodeSets() {
311        if (getConnection() == null)
312            return CodeSetComponentInfo.LOCAL_CODE_SETS;
313        else
314            return getConnection().getCodeSetContext();
315    }
316
317    protected void dprint(String msg)
318    {
319        ORBUtility.dprint("CDROutputObject", msg);
320    }
321}
322
323// End of file.
324