/**
  * Reads a string that has been encoded using a modified UTF-8 format from the bytes message
  * stream.
  *
  * <p>For more information on the UTF-8 format, see "File System Safe UCS Transformation Format
  * (FSS_UTF)", X/Open Preliminary Specification, X/Open Company Ltd., Document Number: P316. This
  * information also appears in ISO/IEC 10646, Annex P.
  *
  * @return a Unicode string from the bytes message stream
  * @throws JMSException if the JMS provider fails to read the message due to some internal error.
  * @throws MessageEOFException if unexpected end of bytes stream has been reached.
  * @throws MessageNotReadableException if the message is in write-only mode.
  */
 @Override
 public String readUTF() throws JMSException {
   initializeReading();
   try {
     return this.dataIn.readUTF();
   } catch (EOFException e) {
     throw JMSExceptionSupport.createMessageEOFException(e);
   } catch (IOException e) {
     throw JMSExceptionSupport.createMessageFormatException(e);
   }
 }
 private void initializeReading() throws JMSException {
   checkWriteOnlyBody();
   if (dataIn == null) {
     ByteSequence data = getContent();
     if (data == null) {
       data = new ByteSequence(new byte[] {}, 0, 0);
     }
     InputStream is = new ByteArrayInputStream(data);
     if (isCompressed()) {
       // keep track of the real length of the content if
       // we are compressed.
       try {
         DataInputStream dis = new DataInputStream(is);
         length = dis.readInt();
         dis.close();
       } catch (IOException e) {
         throw JMSExceptionSupport.create(e);
       }
       is = new InflaterInputStream(is);
     } else {
       length = data.getLength();
     }
     dataIn = new DataInputStream(is);
   }
 }
 /**
  * Writes a portion of a byte array to the bytes message stream.
  *
  * @param value the byte array value to be written
  * @param offset the initial offset within the byte array
  * @param length the number of bytes to use
  * @throws JMSException if the JMS provider fails to write the message due to some internal error.
  * @throws MessageNotWriteableException if the message is in read-only mode.
  */
 @Override
 public void writeBytes(byte[] value, int offset, int length) throws JMSException {
   initializeWriting();
   try {
     this.dataOut.write(value, offset, length);
   } catch (IOException ioe) {
     throw JMSExceptionSupport.create(ioe);
   }
 }
 /**
  * Writes a string to the bytes message stream using UTF-8 encoding in a machine-independent
  * manner.
  *
  * <p>For more information on the UTF-8 format, see "File System Safe UCS Transformation Format
  * (FSS_UTF)", X/Open Preliminary Specification, X/Open Company Ltd., Document Number: P316. This
  * information also appears in ISO/IEC 10646, Annex P.
  *
  * @param value the <code>String</code> value to be written
  * @throws JMSException if the JMS provider fails to write the message due to some internal error.
  * @throws MessageNotWriteableException if the message is in read-only mode.
  */
 @Override
 public void writeUTF(String value) throws JMSException {
   initializeWriting();
   try {
     this.dataOut.writeUTF(value);
   } catch (IOException ioe) {
     throw JMSExceptionSupport.create(ioe);
   }
 }
 /**
  * Reads a portion of the bytes message stream.
  *
  * <p>If the length of array <code>value</code> is less than the number of bytes remaining to be
  * read from the stream, the array should be filled. A subsequent call reads the next increment,
  * and so on.
  *
  * <p>If the number of bytes remaining in the stream is less than the length of array <code>value
  * </code>, the bytes should be read into the array. The return value of the total number of bytes
  * read will be less than the length of the array, indicating that there are no more bytes left to
  * be read from the stream. The next read of the stream returns -1.
  *
  * <p>If <code>length</code> is negative, or <code>length</code> is greater than the length of the
  * array <code>value</code>, then an <code>IndexOutOfBoundsException</code> is thrown. No bytes
  * will be read from the stream for this exception case.
  *
  * @param value the buffer into which the data is read
  * @param length the number of bytes to read; must be less than or equal to <code>value.length
  *     </code>
  * @return the total number of bytes read into the buffer, or -1 if there is no more data because
  *     the end of the stream has been reached
  * @throws JMSException if the JMS provider fails to read the message due to some internal error.
  * @throws MessageNotReadableException if the message is in write-only mode.
  */
 @Override
 public int readBytes(byte[] value, int length) throws JMSException {
   initializeReading();
   try {
     int n = 0;
     while (n < length) {
       int count = this.dataIn.read(value, n, length - n);
       if (count < 0) {
         break;
       }
       n += count;
     }
     if (n == 0 && length > 0) {
       n = -1;
     }
     return n;
   } catch (EOFException e) {
     throw JMSExceptionSupport.createMessageEOFException(e);
   } catch (IOException e) {
     throw JMSExceptionSupport.createMessageFormatException(e);
   }
 }
 @Override
 protected Message copy(Session session, Message m) throws JMSException {
   if (m instanceof ActiveMQBlobMessage) {
     ActiveMQBlobMessage b = (ActiveMQBlobMessage) m;
     ActiveMQBlobMessage copy =
         (ActiveMQBlobMessage) getAMQSession(session).createBlobMessage(b.getURL());
     try {
       copy.setProperties(b.getProperties());
     } catch (IOException e) {
       throw JMSExceptionSupport.create("Unable to copy message " + m, e);
     }
     return copy;
   } else {
     return super.copy(session, m);
   }
 }
  private void beforeEnd() throws JMSException {
    if (synchronizations == null) {
      return;
    }

    int size = synchronizations.size();
    try {
      for (; beforeEndIndex < size; ) {
        synchronizations.get(beforeEndIndex++).beforeEnd();
      }
    } catch (JMSException e) {
      throw e;
    } catch (Throwable e) {
      throw JMSExceptionSupport.create(e);
    }
  }
  private void initializeWriting() throws JMSException {
    checkReadOnlyBody();
    if (this.dataOut == null) {
      this.bytesOut = new ByteArrayOutputStream();
      OutputStream os = bytesOut;
      ActiveMQConnection connection = getConnection();
      if (connection != null && connection.isUseCompression()) {
        // keep track of the real length of the content if
        // we are compressed.
        try {
          os.write(new byte[4]);
        } catch (IOException e) {
          throw JMSExceptionSupport.create(e);
        }
        length = 0;
        compressed = true;
        final Deflater deflater = new Deflater(Deflater.BEST_SPEED);
        os =
            new FilterOutputStream(new DeflaterOutputStream(os, deflater)) {
              @Override
              public void write(byte[] arg0) throws IOException {
                length += arg0.length;
                out.write(arg0);
              }

              @Override
              public void write(byte[] arg0, int arg1, int arg2) throws IOException {
                length += arg2;
                out.write(arg0, arg1, arg2);
              }

              @Override
              public void write(int arg0) throws IOException {
                length++;
                out.write(arg0);
              }

              @Override
              public void close() throws IOException {
                super.close();
                deflater.end();
              }
            };
      }
      this.dataOut = new DataOutputStream(os);
    }
  }
 // DiscoveryAgent interface
 // -------------------------------------------------------------------------
 public void start() throws Exception {
   if (group == null) {
     throw new IOException("You must specify a group to discover");
   }
   String type = getType();
   if (!type.endsWith(".")) {
     LOG.warn("The type '" + type + "' should end with '.' to be a valid Rendezvous type");
     type += ".";
   }
   try {
     // force lazy construction
     getJmdns();
     if (listener != null) {
       LOG.info("Discovering service of type: " + type);
       jmdns.addServiceListener(type, this);
     }
   } catch (IOException e) {
     JMSExceptionSupport.create("Failed to start JmDNS service: " + e, e);
   }
 }
  private void afterCommit() throws JMSException {
    if (synchronizations == null) {
      return;
    }

    Throwable firstException = null;
    int size = synchronizations.size();
    for (int i = 0; i < size; i++) {
      try {
        synchronizations.get(i).afterCommit();
      } catch (Throwable t) {
        LOG.debug("Exception from afterCommit on {}", synchronizations.get(i), t);
        if (firstException == null) {
          firstException = t;
        }
      }
    }
    synchronizations = null;
    if (firstException != null) {
      throw JMSExceptionSupport.create(firstException);
    }
  }