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 
  26 package com.sun.corba.se.impl.encoding;
  27 
  28 import java.nio.ByteBuffer;
  29 
  30 
  31 import com.sun.corba.se.impl.encoding.BufferManagerWrite;
  32 import com.sun.corba.se.impl.orbutil.ORBUtility;
  33 import com.sun.corba.se.pept.transport.ByteBufferPool;
  34 import com.sun.corba.se.spi.orb.ORB;
  35 
  36 
  37 // Notes about the class.
  38 // Assumptions, the ByteBuffer's position is set by the constructor's
  39 // index variable and the ByteBuffer's limit points to the end of the
  40 // data. Also, since the index variable tracks the current empty
  41 // position in the buffer, the ByteBuffer's position is updated
  42 // any time there's a call to this class's position().
  43 // Although, a ByteBuffer's length is it's capacity(), the context in
  44 // which length is used in this object, this.buflen is actually the
  45 // ByteBuffer limit().
  46 
  47 public class ByteBufferWithInfo
  48 {
  49     private ORB orb;
  50     private boolean debug;
  51     // REVISIT - index should eventually be replaced with byteBuffer.position()
  52     private int     index;     // Current empty position in buffer.
  53     // REVISIT - CHANGE THESE TO PRIVATE
  54     public ByteBuffer byteBuffer;// Marshal buffer.
  55     public int     buflen;     // Total length of buffer. // Unnecessary...
  56     public int     needed;     // How many more bytes are needed on overflow.
  57     public boolean fragmented; // Did the overflow operation fragment?
  58 
  59     public ByteBufferWithInfo(org.omg.CORBA.ORB orb,
  60                               ByteBuffer byteBuffer,
  61                               int index)
  62     {
  63         this.orb = (com.sun.corba.se.spi.orb.ORB)orb;
  64         debug = this.orb.transportDebugFlag;
  65         this.byteBuffer = byteBuffer;
  66         if (byteBuffer != null)
  67         {
  68             this.buflen = byteBuffer.limit();
  69         }
  70         position(index);
  71         this.needed = 0;
  72         this.fragmented = false;
  73     }
  74 
  75     public ByteBufferWithInfo(org.omg.CORBA.ORB orb, ByteBuffer byteBuffer)
  76     {
  77         this(orb, byteBuffer, 0);
  78     }
  79 
  80     public ByteBufferWithInfo(org.omg.CORBA.ORB orb,
  81                               BufferManagerWrite bufferManager)
  82     {
  83         this(orb, bufferManager, true);
  84     }
  85 
  86     // Right now, EncapsOutputStream's do not use pooled byte buffers.
  87     // EncapsOutputStream's is the only one that does not use pooled
  88     // byte buffers. Hence, the reason for the boolean 'usePooledByteBuffers'.
  89     // See EncapsOutputStream for additional information.
  90 
  91     public ByteBufferWithInfo(org.omg.CORBA.ORB orb,
  92                               BufferManagerWrite bufferManager,
  93                               boolean usePooledByteBuffers)
  94     {
  95         this.orb = (com.sun.corba.se.spi.orb.ORB)orb;
  96         debug = this.orb.transportDebugFlag;
  97 
  98         int bufferSize = bufferManager.getBufferSize();
  99 
 100         if (usePooledByteBuffers)
 101         {
 102             ByteBufferPool byteBufferPool = this.orb.getByteBufferPool();
 103             this.byteBuffer = byteBufferPool.getByteBuffer(bufferSize);
 104 
 105             if (debug)
 106             {
 107                 // print address of ByteBuffer gotten from pool
 108                 int bbAddress = System.identityHashCode(byteBuffer);
 109                 StringBuffer sb = new StringBuffer(80);
 110                 sb.append("constructor (ORB, BufferManagerWrite) - got ")
 111                   .append("ByteBuffer id (").append(bbAddress)
 112                   .append(") from ByteBufferPool.");
 113                 String msgStr = sb.toString();
 114                 dprint(msgStr);
 115             }
 116         }
 117         else
 118         {
 119              // don't allocate from pool, allocate non-direct ByteBuffer
 120              this.byteBuffer = ByteBuffer.allocate(bufferSize);
 121         }
 122 
 123         position(0);
 124         this.buflen = bufferSize;
 125         this.byteBuffer.limit(this.buflen);
 126         this.needed = 0;
 127         this.fragmented = false;
 128     }
 129 
 130     // Shallow copy constructor
 131     public ByteBufferWithInfo (ByteBufferWithInfo bbwi)
 132     {
 133         this.orb = bbwi.orb;
 134         this.debug = bbwi.debug;
 135         this.byteBuffer = bbwi.byteBuffer;
 136         this.buflen = bbwi.buflen;
 137         this.byteBuffer.limit(this.buflen);
 138         position(bbwi.position());
 139         this.needed = bbwi.needed;
 140         this.fragmented = bbwi.fragmented;
 141     }
 142 
 143     // So IIOPOutputStream seems more intuitive
 144     public int getSize()
 145     {
 146         return position();
 147     }
 148 
 149     // accessor to buflen
 150     public int getLength()
 151     {
 152          return buflen;
 153     }
 154 
 155     // get position in this buffer
 156     public int position()
 157     {
 158         // REVISIT - This should be changed to return the
 159         //           value of byteBuffer.position() rather
 160         //           than this.index. But, byteBuffer.position
 161         //           is manipulated via ByteBuffer writes, reads,
 162         //           gets and puts. These locations need to be
 163         //           investigated and updated before
 164         //           byteBuffer.position() can be returned here.
 165         // return byteBuffer.position();
 166         return index;
 167     }
 168 
 169     // set position in this buffer
 170     public void position(int newPosition)
 171     {
 172         // REVISIT - This should be changed to set only the
 173         //           value of byteBuffer.position rather
 174         //           than this.index. This change should be made
 175         //           in conjunction with the change to this.position().
 176         byteBuffer.position(newPosition);
 177         index = newPosition;
 178     }
 179 
 180     // mutator to buflen
 181     public void setLength(int theLength)
 182     {
 183         buflen = theLength;
 184         byteBuffer.limit(buflen);
 185     }
 186 
 187     // Grow byteBuffer to a size larger than position() + needed
 188     public void growBuffer(com.sun.corba.se.spi.orb.ORB orb)
 189     {
 190         // This code used to live directly in CDROutputStream.grow.
 191 
 192         // Recall that the byteBuffer size is 'really' the limit or
 193         // buflen.
 194 
 195         int newLength = byteBuffer.limit() * 2;
 196 
 197         while (position() + needed >= newLength)
 198             newLength = newLength * 2;
 199 
 200         ByteBufferPool byteBufferPool = orb.getByteBufferPool();
 201         ByteBuffer newBB = byteBufferPool.getByteBuffer(newLength);
 202 
 203         if (debug)
 204         {
 205             // print address of ByteBuffer just gotten
 206             int newbbAddress = System.identityHashCode(newBB);
 207             StringBuffer sb = new StringBuffer(80);
 208             sb.append("growBuffer() - got ByteBuffer id (");
 209             sb.append(newbbAddress).append(") from ByteBufferPool.");
 210             String msgStr = sb.toString();
 211             dprint(msgStr);
 212         }
 213 
 214         byteBuffer.position(0);
 215         newBB.put(byteBuffer);
 216 
 217         // return 'old' byteBuffer reference to the ByteBuffer pool
 218         if (debug)
 219         {
 220             // print address of ByteBuffer being released
 221             int bbAddress = System.identityHashCode(byteBuffer);
 222             StringBuffer sb = new StringBuffer(80);
 223             sb.append("growBuffer() - releasing ByteBuffer id (");
 224             sb.append(bbAddress).append(") to ByteBufferPool.");
 225             String msgStr2 = sb.toString();
 226             dprint(msgStr2);
 227         }
 228         byteBufferPool.releaseByteBuffer(byteBuffer);
 229 
 230         // update the byteBuffer with a larger ByteBuffer
 231         byteBuffer = newBB;
 232 
 233         // limit and buflen must be set to newLength.
 234         buflen = newLength;
 235         byteBuffer.limit(buflen);
 236     }
 237 
 238     public String toString()
 239     {
 240         StringBuffer str = new StringBuffer("ByteBufferWithInfo:");
 241 
 242         str.append(" buflen = " + buflen);
 243         str.append(" byteBuffer.limit = " + byteBuffer.limit());
 244         str.append(" index = " + index);
 245         str.append(" position = " + position());
 246         str.append(" needed = " + needed);
 247         str.append(" byteBuffer = " + (byteBuffer == null ? "null" : "not null"));
 248         str.append(" fragmented = " + fragmented);
 249 
 250         return str.toString();
 251     }
 252 
 253     protected void dprint(String msg)
 254     {
 255         ORBUtility.dprint("ByteBufferWithInfo", msg);
 256     }
 257 }