CDREncapsCodec.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2000, 2013, 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.interceptors;
27
28import org.omg.CORBA.Any;
29import org.omg.CORBA.ORB;
30import org.omg.CORBA.TypeCode;
31import org.omg.CORBA.LocalObject;
32
33import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
34import com.sun.corba.se.spi.logging.CORBALogDomains;
35
36import sun.corba.EncapsInputStreamFactory;
37
38import com.sun.corba.se.impl.corba.AnyImpl;
39import com.sun.corba.se.impl.encoding.EncapsInputStream;
40import com.sun.corba.se.impl.encoding.EncapsOutputStream;
41import com.sun.corba.se.impl.logging.ORBUtilSystemException;
42
43import org.omg.IOP.Codec;
44import org.omg.IOP.CodecPackage.FormatMismatch;
45import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
46import org.omg.IOP.CodecPackage.TypeMismatch;
47
48/**
49 * CDREncapsCodec is an implementation of Codec, as described
50 * in orbos/99-12-02, that supports CDR encapsulation version 1.0, 1.1, and
51 * 1.2.
52 */
53public final class CDREncapsCodec
54    extends org.omg.CORBA.LocalObject
55    implements Codec
56{
57    // The ORB that created the factory this codec was created from
58    private ORB orb;
59    ORBUtilSystemException wrapper;
60
61    // The GIOP version we are encoding for
62    private GIOPVersion giopVersion;
63
64    /*
65     *******************************************************************
66     * NOTE: CDREncapsCodec must remain immutable!  This is so that we
67     * can pre-create CDREncapsCodecs for each version of GIOP in
68     * CodecFactoryImpl.
69     *******************************************************************/
70
71    /**
72     * Creates a new codec implementation.  Uses the given ORB to create
73     * CDRInputStreams when necessary.
74     *
75     * @param orb The ORB to use to create a CDRInputStream or CDROutputStream
76     * @param major The major version of GIOP we are encoding for
77     * @param minor The minor version of GIOP we are encoding for
78     */
79    public CDREncapsCodec( ORB orb, int major, int minor ) {
80        this.orb = orb;
81        wrapper = ORBUtilSystemException.get(
82            (com.sun.corba.se.spi.orb.ORB)orb, CORBALogDomains.RPC_PROTOCOL ) ;
83
84        giopVersion = GIOPVersion.getInstance( (byte)major, (byte)minor );
85    }
86
87    /**
88     * Convert the given any into a CDR encapsulated octet sequence
89     */
90    public byte[] encode( Any data )
91        throws InvalidTypeForEncoding
92    {
93        if ( data == null )
94            throw wrapper.nullParam() ;
95        return encodeImpl( data, true );
96    }
97
98    /**
99     * Decode the given octet sequence into an any based on a CDR
100     * encapsulated octet sequence.
101     */
102    public Any decode ( byte[] data )
103        throws FormatMismatch
104    {
105        if( data == null )
106            throw wrapper.nullParam() ;
107        return decodeImpl( data, null );
108    }
109
110    /**
111     * Convert the given any into a CDR encapsulated octet sequence.  Only
112     * the data is stored.  The type code is not.
113     */
114    public byte[] encode_value( Any data )
115        throws InvalidTypeForEncoding
116    {
117        if( data == null )
118            throw wrapper.nullParam() ;
119        return encodeImpl( data, false );
120    }
121
122    /**
123     * Decode the given octet sequence into an any based on a CDR
124     * encapsulated octet sequence.  The type code is expected not to appear
125     * in the octet sequence, and the given type code is used instead.
126     */
127    public Any decode_value( byte[] data, TypeCode tc )
128        throws FormatMismatch, TypeMismatch
129    {
130        if( data == null )
131            throw wrapper.nullParam() ;
132        if( tc == null )
133            throw  wrapper.nullParam() ;
134        return decodeImpl( data, tc );
135    }
136
137    /**
138     * Convert the given any into a CDR encapsulated octet sequence.
139     * If sendTypeCode is true, the type code is sent with the message, as in
140     * a standard encapsulation.  If it is false, only the data is sent.
141     * Either way, the endian type is sent as the first part of the message.
142     */
143    private byte[] encodeImpl( Any data, boolean sendTypeCode )
144        throws InvalidTypeForEncoding
145    {
146        if( data == null )
147            throw wrapper.nullParam() ;
148
149        // _REVISIT_ Note that InvalidTypeForEncoding is never thrown in
150        // the body of this method.  This is due to the fact that CDR*Stream
151        // will never throw an exception if the encoding is invalid.  To
152        // fix this, the CDROutputStream must know the version of GIOP it
153        // is encoding for and it must check to ensure that, for example,
154        // wstring cannot be encoded in GIOP 1.0.
155        //
156        // As part of the GIOP 1.2 work, the CDRInput and OutputStream will
157        // be versioned.  This can be handled once this work is complete.
158
159        // Create output stream with default endianness.
160        EncapsOutputStream cdrOut =
161            sun.corba.OutputStreamFactory.newEncapsOutputStream(
162            (com.sun.corba.se.spi.orb.ORB)orb, giopVersion );
163
164        // This is an encapsulation, so put out the endian:
165        cdrOut.putEndian();
166
167        // Sometimes encode type code:
168        if( sendTypeCode ) {
169            cdrOut.write_TypeCode( data.type() );
170        }
171
172        // Encode value and return.
173        data.write_value( cdrOut );
174
175        return cdrOut.toByteArray();
176    }
177
178    /**
179     * Decode the given octet sequence into an any based on a CDR
180     * encapsulated octet sequence.  If the type code is null, it is
181     * expected to appear in the octet sequence.  Otherwise, the given
182     * type code is used.
183     */
184    private Any decodeImpl( byte[] data, TypeCode tc )
185        throws FormatMismatch
186    {
187        if( data == null )
188            throw wrapper.nullParam() ;
189
190        AnyImpl any = null;  // return value
191
192        // _REVISIT_ Currently there is no way for us to distinguish between
193        // a FormatMismatch and a TypeMismatch because we cannot get this
194        // information from the CDRInputStream.  If a RuntimeException occurs,
195        // it is turned into a FormatMismatch exception.
196
197        try {
198            EncapsInputStream cdrIn = EncapsInputStreamFactory.newEncapsInputStream( orb, data,
199                    data.length, giopVersion );
200
201
202            cdrIn.consumeEndian();
203
204            // If type code not specified, read it from octet stream:
205            if( tc == null ) {
206                tc = cdrIn.read_TypeCode();
207            }
208
209            // Create a new Any object:
210            any = new AnyImpl( (com.sun.corba.se.spi.orb.ORB)orb );
211            any.read_value( cdrIn, tc );
212        }
213        catch( RuntimeException e ) {
214            // See above note.
215            throw new FormatMismatch();
216        }
217
218        return any;
219    }
220}
221