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 
  26 package com.sun.corba.se.impl.encoding;
  27 
  28 import java.nio.ByteBuffer;
  29 
  30 import com.sun.org.omg.SendingContext.CodeBase;
  31 
  32 import com.sun.corba.se.pept.encoding.InputObject;
  33 
  34 import com.sun.corba.se.spi.logging.CORBALogDomains;
  35 
  36 import com.sun.corba.se.spi.orb.ORB;
  37 
  38 import com.sun.corba.se.spi.transport.CorbaConnection;
  39 
  40 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  41 
  42 import com.sun.corba.se.impl.encoding.BufferManagerFactory;
  43 import com.sun.corba.se.impl.encoding.CodeSetComponentInfo;
  44 import com.sun.corba.se.impl.encoding.CodeSetConversion;
  45 import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
  46 import com.sun.corba.se.impl.encoding.CDRInputStream;
  47 
  48 import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
  49 
  50 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  51 import com.sun.corba.se.impl.logging.OMGSystemException;
  52 
  53 import com.sun.corba.se.impl.orbutil.ORBUtility;
  54 
  55 /**
  56  * @author Harold Carr
  57  */
  58 public class CDRInputObject extends CDRInputStream
  59     implements
  60         InputObject
  61 {
  62     private CorbaConnection corbaConnection;
  63     private Message header;
  64     private boolean unmarshaledHeader;
  65     private ORB orb ;
  66     private ORBUtilSystemException wrapper ;
  67     private OMGSystemException omgWrapper ;
  68 
  69     public CDRInputObject(ORB orb,
  70                           CorbaConnection corbaConnection,
  71                           ByteBuffer byteBuffer,
  72                           Message header)
  73     {
  74         super(orb, byteBuffer, header.getSize(), header.isLittleEndian(),
  75               header.getGIOPVersion(), header.getEncodingVersion(),
  76               BufferManagerFactory.newBufferManagerRead(
  77                                           header.getGIOPVersion(),
  78                                           header.getEncodingVersion(),
  79                                           orb));
  80 
  81         this.corbaConnection = corbaConnection;
  82         this.orb = orb ;
  83         this.wrapper = ORBUtilSystemException.get( orb,
  84             CORBALogDomains.RPC_ENCODING ) ;
  85         this.omgWrapper = OMGSystemException.get( orb,
  86             CORBALogDomains.RPC_ENCODING ) ;
  87 
  88         if (orb.transportDebugFlag) {
  89             dprint(".CDRInputObject constructor:");
  90         }
  91 
  92         getBufferManager().init(header);
  93 
  94         this.header = header;
  95 
  96         unmarshaledHeader = false;
  97 
  98         setIndex(Message.GIOPMessageHeaderLength);
  99 
 100         setBufferLength(header.getSize());
 101     }
 102 
 103     // REVISIT - think about this some more.
 104     // This connection normally is accessed from the message mediator.
 105     // However, giop input needs to get code set info from the connetion
 106     // *before* the message mediator is available.
 107     public final CorbaConnection getConnection()
 108     {
 109         return corbaConnection;
 110     }
 111 
 112     // XREVISIT - Should the header be kept in the stream or the
 113     // message mediator?  Or should we not have a header and
 114     // have the information stored in the message mediator
 115     // directly?
 116     public Message getMessageHeader()
 117     {
 118         return header;
 119     }
 120 
 121     /**
 122      * Unmarshal the extended GIOP header
 123      * NOTE: May be fragmented, so should not be called by the ReaderThread.
 124      * See CorbaResponseWaitingRoomImpl.waitForResponse.  It is done
 125      * there in the client thread.
 126      */
 127     public void unmarshalHeader()
 128     {
 129         // Unmarshal the extended GIOP message from the buffer.
 130 
 131         if (!unmarshaledHeader) {
 132             try {
 133                 if (((ORB)orb()).transportDebugFlag) {
 134                     dprint(".unmarshalHeader->: " + getMessageHeader());
 135                 }
 136                 getMessageHeader().read(this);
 137                 unmarshaledHeader= true;
 138             } catch (RuntimeException e) {
 139                 if (((ORB)orb()).transportDebugFlag) {
 140                     dprint(".unmarshalHeader: !!ERROR!!: "
 141                            + getMessageHeader()
 142                            + ": " + e);
 143                 }
 144                 throw e;
 145             } finally {
 146                 if (((ORB)orb()).transportDebugFlag) {
 147                     dprint(".unmarshalHeader<-: " + getMessageHeader());
 148                 }
 149             }
 150         }
 151     }
 152 
 153     public final boolean unmarshaledHeader()
 154     {
 155         return unmarshaledHeader;
 156     }
 157 
 158     /**
 159      * Override the default CDR factory behavior to get the
 160      * negotiated code sets from the connection.
 161      *
 162      * These are only called once per message, the first time needed.
 163      *
 164      * In the local case, there is no Connection, so use the
 165      * local code sets.
 166      */
 167     protected CodeSetConversion.BTCConverter createCharBTCConverter() {
 168         CodeSetComponentInfo.CodeSetContext codesets = getCodeSets();
 169 
 170         // If the connection doesn't have its negotiated
 171         // code sets by now, fall back on the defaults defined
 172         // in CDRInputStream.
 173         if (codesets == null)
 174             return super.createCharBTCConverter();
 175 
 176         OSFCodeSetRegistry.Entry charSet
 177             = OSFCodeSetRegistry.lookupEntry(codesets.getCharCodeSet());
 178 
 179         if (charSet == null)
 180             throw wrapper.unknownCodeset( charSet ) ;
 181 
 182         return CodeSetConversion.impl().getBTCConverter(charSet, isLittleEndian());
 183     }
 184 
 185     protected CodeSetConversion.BTCConverter createWCharBTCConverter() {
 186 
 187         CodeSetComponentInfo.CodeSetContext codesets = getCodeSets();
 188 
 189         // If the connection doesn't have its negotiated
 190         // code sets by now, we have to throw an exception.
 191         // See CORBA formal 00-11-03 13.9.2.6.
 192         if (codesets == null) {
 193             if (getConnection().isServer())
 194                 throw omgWrapper.noClientWcharCodesetCtx() ;
 195             else
 196                 throw omgWrapper.noServerWcharCodesetCmp() ;
 197         }
 198 
 199         OSFCodeSetRegistry.Entry wcharSet
 200             = OSFCodeSetRegistry.lookupEntry(codesets.getWCharCodeSet());
 201 
 202         if (wcharSet == null)
 203             throw wrapper.unknownCodeset( wcharSet ) ;
 204 
 205         // For GIOP 1.2 and UTF-16, use big endian if there is no byte
 206         // order marker.  (See issue 3405b)
 207         //
 208         // For GIOP 1.1 and UTF-16, use the byte order the stream if
 209         // there isn't (and there shouldn't be) a byte order marker.
 210         //
 211         // GIOP 1.0 doesn't have wchars.  If we're talking to a legacy ORB,
 212         // we do what our old ORBs did.
 213         if (wcharSet == OSFCodeSetRegistry.UTF_16) {
 214             if (getGIOPVersion().equals(GIOPVersion.V1_2))
 215                 return CodeSetConversion.impl().getBTCConverter(wcharSet, false);
 216         }
 217 
 218         return CodeSetConversion.impl().getBTCConverter(wcharSet, isLittleEndian());
 219     }
 220 
 221     // If we're local and don't have a Connection, use the
 222     // local code sets, otherwise get them from the connection.
 223     // If the connection doesn't have negotiated code sets
 224     // yet, then we use ISO8859-1 for char/string and wchar/wstring
 225     // are illegal.
 226     private CodeSetComponentInfo.CodeSetContext getCodeSets() {
 227         if (getConnection() == null)
 228             return CodeSetComponentInfo.LOCAL_CODE_SETS;
 229         else
 230             return getConnection().getCodeSetContext();
 231     }
 232 
 233     public final CodeBase getCodeBase() {
 234         if (getConnection() == null)
 235             return null;
 236         else
 237             return getConnection().getCodeBase();
 238     }
 239 
 240     // -----------------------------------------------------------
 241     // Below this point are commented out methods with features
 242     // from the old stream.  We must find ways to address
 243     // these issues in the future.
 244     // -----------------------------------------------------------
 245 
 246     // XREVISIT
 247 //     private XIIOPInputStream(XIIOPInputStream stream) {
 248 //         super(stream);
 249 
 250 //         this.conn = stream.conn;
 251 //         this.msg = stream.msg;
 252 //         this.unmarshaledHeader = stream.unmarshaledHeader;
 253 //     }
 254 
 255     public CDRInputStream dup() {
 256         // XREVISIT
 257         return null;
 258         // return new XIIOPInputStream(this);
 259     }
 260 
 261     protected void dprint(String msg)
 262     {
 263         ORBUtility.dprint("CDRInputObject", msg);
 264     }
 265 }
 266 
 267 // End of file.