docs: protected void prepareDataForNextChannel() {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "prepareDataForNextChannel");
          }
  
          // Ensure the output buffers are already set in place for the calling channel.
          if (getJITAllocateAction()) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "Allocation was done here, adjust and hand off buffers, JIT="
                               + getJITAllocateSize());
              }
  
              // Multiple cases to handle here. Remember, we allocated these buffers.
              // 1 - decNetBuffers has only 1 buffer and it is <= the JIT size
              // We can just send it up to the caller.
              // 2 - decNetBuffers has only 1 buffer, but it is > the JIT size
              // We need to copy it to a JIT sized buffer and save the rest of a future read.
              // 3 - decNetBuffers has multiple buffers, the first of which has the matching JIT size.
              // We should pass the first buffer back to the caller and save the rest of a future read.
              // 4 - decNetBuffers has multiple buffers, the first of which does not match the JIT size.
              // We have to check ensure the JIT size is honored. May have to do a buffer copy.
              int decryptedDataSize = SSLUtils.lengthOf(decryptedNetBuffers, 0);
              if (decryptedNetBuffers.length == 1) {
                  if (decryptedDataSize <= getJITAllocateSize()) {
  
                      // Case 1:
                      // There is only one decryptedNetBuffer and the size is less than the JIT.
                      // Therefore, we can return this buffer to the caller.
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "single decNetBuffer is okay to pass to caller");
                      }
                      // Data is currently between pos and lim. Adjust for calling channel.
                      SSLUtils.positionToLimit(decryptedNetBuffers);
                      // Reset the limits saved for the decryptedNetBuffers.
                      SSLUtils.setBufferLimits(decryptedNetBuffers, decryptedNetLimitInfo);
                      // Store the decrypted buffer to this context for reference by the caller.
                      setBuffer(decryptedNetBuffers[0]);
  
                  } else {
                      // Case 2:
                      // There is only one decryptedNetBuffer, but the size is greater than the JIT.
                      // Therefore, we have to copy the buffer into a JIT sized buffer
                      // and save the left overs.
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "only one decNetBuffer, but too big ("
                                       + decryptedDataSize + ") for JIT.  Need to copy.");
                      }
                      // Create a new buffer to hand to the caller.
                      // We want to reuse copyDataToCallerBuffers.
                      // It copies from decryptedNetBuffers to getBuffers() which
                      // are currently the same, so change it.
                      setBuffer(SSLUtils.allocateByteBuffer(getJITAllocateSize(), false));
                      getBuffer().limit(getJITAllocateSize());
                      // Copy from the decNetBuffers into the buffers to be sent to the caller.
                      copyDataToCallerBuffers();
                  }
  
              } else {
                  // There are > 1 decryptedNetBuffers.
                  // Check if the first one matches the JIT size.
                  // TODO this is wrong. should be using capacity() instead of
                  // remaining I think since after decrypt, remaining is less than
                  // buffer cap (decrypt 4 bytes and remaining is 8188 but buffer is
                  // the 8192 that JIT size is by default), meaning it's fine
                  // not sure about all cases though...
                  if (decryptedNetBuffers[0].remaining() == getJITAllocateSize()) {
                      // Case 3:
                      // Found a match. Return the first buffer to the caller and
                      // save the rest for a future read.
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "multiple buffers, first of which matches the JIT size");
                      }
                      // Data is currently between pos and lim. Adjust for calling channel.
                      decryptedNetBuffers[0].position(decryptedNetBuffers[0].limit());
                      // Store the decrypted buffer to this context for reference by the caller.
                      setBuffer(decryptedNetBuffers[0]);
                      // Now save the other buffers in the unconsumedDecData (which is null at this point)
                      if (null != unconsumedDecData) {
                          if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) {
                              Tr.event(tc, "Expected null unconsumed array, but isn't: "
                                           + SSLUtils.getBufferTraceInfo(unconsumedDecData));
                          }
                          // shouldn't release buffers we might not own (especially since
                          // they shouldn't even be here in the first place)
                          // WsByteBufferUtils.releaseBufferArray(unconsumedDecData);
                      }
                      // figure out if any more buffers exist with actual data to save
                      int size = 0;
                      for (int i = 1; i < decryptedNetBuffers.length; i++) {
                          // if there is nothing in this buffer, just release it
                          if (0 == decryptedNetBuffers[i].remaining()) {
                              decryptedNetBuffers[i].release();
                          } else {
                              size++;
                          }
                      }
                      if (0 < size) {
                          unconsumedDecData = new WsByteBuffer[size];
                          for (int i = 1, x = 0; x < size; i++, x++) {
                              unconsumedDecData[x] = decryptedNetBuffers[i];
                          }
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(tc, "unconsumedDecData: "
                                           + SSLUtils.getBufferTraceInfo(unconsumedDecData));
                          }
                      }
  
                  } else {
                      // Case 4:
                      // Multiple buffers, first of which doesn't match the JIT. Need to copy.
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "multiple buffers, first does not match the JIT size.");
                      }
                      // Create a new buffer to hand to the caller.
                      // We want to reuse copyDataToCallerBuffers.
                      // It copies from decryptedNetBuffers to getBuffers() which
                      // are currently the same, so change it.
                      setBuffer(SSLUtils.allocateByteBuffer(getJITAllocateSize(), false));
                      getBuffer().limit(getJITAllocateSize());
                      // Adjust the decryptedNetBuffers. Results from the JSSE keep
                      // untouched buffers with their pos = lim. Buffers with data
                      // have nonzero pos and lim. Unused buffers have zero
                      // pos and lim. We need the data to be between pos and lim
                      // for the copy. Zeroing out the pos enables this.
                      for (int i = 0; i < decryptedNetBuffers.length; i++) {
                          decryptedNetBuffers[i].position(0);
                      }
                      // Copy from the decNetBuffers into the buffers to be sent to the caller.
                      copyDataToCallerBuffers();
                  }
              }
  
          } else {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "Using channel provided buffers");
              }
              // Calling channel provided buffers to read into.
              if (decryptedNetBufferReleaseRequired) {
                  // User provided buffers were not originally adequate. Temporary
                  // buffers were allocated to hold the result.
                  for (int i = 0; i < this.decryptedNetBuffers.length; i++) {
                      if (null != this.decryptedNetBuffers[i]) {
                          this.decryptedNetBuffers[i].position(0);
                      }
                  }
                  copyDataToCallerBuffers();
              } else {
                  // User provided buffers were adequate
                  SSLUtils.positionToLimit(decryptedNetBuffers);
                  SSLUtils.setBufferLimits(decryptedNetBuffers, decryptedNetLimitInfo);
              }
          }
          // The decryptedNetBuffers are being given to the next channel.
          // Eliminate tracking of ownership.
          decryptedNetBuffers = null;
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
              Tr.debug(tc, "Buffers being sent to next channel: "
                           + SSLUtils.getBufferTraceInfo(getBuffers()));
          }
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "prepareDataForNextChannel");
          }
      }